优化IP名单

* 增加IP灰名单,用于仅记录并观察IP
This commit is contained in:
GoEdgeLab
2024-05-05 18:56:25 +08:00
parent c4d45456b8
commit 71c7b7dcc7
27 changed files with 259 additions and 22 deletions

View File

@@ -39,8 +39,8 @@ func (this *ListsAction) RunGet(params struct {
this.ErrorPage(err)
return
}
count := countResp.Count
page := this.NewPage(count)
var count = countResp.Count
var page = this.NewPage(count)
this.Data["page"] = page.AsHTML()
// 列表
@@ -53,9 +53,9 @@ func (this *ListsAction) RunGet(params struct {
this.ErrorPage(err)
return
}
itemMaps := []maps.Map{}
var itemMaps = []maps.Map{}
for _, item := range itemsResp.IpItems {
expiredTime := ""
var expiredTime = ""
if item.ExpiredAt > 0 {
expiredTime = timeutil.FormatTime("Y-m-d H:i:s", item.ExpiredAt)
}

View File

@@ -42,6 +42,9 @@ func (this *BindHTTPFirewallPopupAction) RunGet(params struct {
for _, ref := range inboundConfig.PublicDenyListRefs {
selectedIds = append(selectedIds, ref.ListId)
}
for _, ref := range inboundConfig.PublicGreyListRefs {
selectedIds = append(selectedIds, ref.ListId)
}
}
// 公共的名单

View File

@@ -60,7 +60,7 @@ func (this *CreateIPPopupAction) RunPost(params struct {
CSRF *actionutils.CSRF
}) {
// 校验IPList
if params.ListId != firewallconfigs.GlobalListId {
if !firewallconfigs.IsGlobalListId(params.ListId) {
existsResp, err := this.RPC().IPListRPC().ExistsEnabledIPList(this.AdminContext(), &pb.ExistsEnabledIPListRequest{IpListId: params.ListId})
if err != nil {
this.ErrorPage(err)

View File

@@ -34,9 +34,11 @@ func (this *HttpFirewallAction) RunPost(params struct {
refs = inboundConfig.PublicDenyListRefs
case ipconfigs.IPListTypeWhite:
refs = inboundConfig.PublicAllowListRefs
case ipconfigs.IPListTypeGrey:
refs = inboundConfig.PublicGreyListRefs
}
listMaps := []maps.Map{}
var listMaps = []maps.Map{}
for _, ref := range refs {
listResp, err := this.RPC().IPListRPC().FindEnabledIPList(this.AdminContext(), &pb.FindEnabledIPListRequest{IpListId: ref.ListId})
if err != nil {

View File

@@ -84,7 +84,7 @@ func (this *IndexAction) RunGet(params struct {
var itemMaps = []maps.Map{}
for _, result := range itemsResp.Results {
var item = result.IpItem
expiredTime := ""
var expiredTime = ""
if item.ExpiredAt > 0 {
expiredTime = timeutil.FormatTime("Y-m-d H:i:s", item.ExpiredAt)
}

View File

@@ -7,6 +7,7 @@ import (
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ipconfigs"
"github.com/iwind/TeaGo/maps"
)
@@ -26,10 +27,12 @@ func InitIPList(action *actionutils.ParentAction, listId int64) error {
var typeName = ""
switch list.Type {
case "black":
case ipconfigs.IPListTypeBlack:
typeName = "黑名单"
case "white":
case ipconfigs.IPListTypeWhite:
typeName = "白名单"
case ipconfigs.IPListTypeGrey:
typeName = "灰名单"
}
// IP数量

View File

@@ -17,6 +17,7 @@ func init() {
GetPost("", new(IndexAction)).
Get("/ipadmin/allowList", new(ipadmin.AllowListAction)).
Get("/ipadmin/denyList", new(ipadmin.DenyListAction)).
Get("/ipadmin/greyList", new(ipadmin.GreyListAction)).
GetPost("/ipadmin/countries", new(ipadmin.CountriesAction)).
Get("/ipadmin/selectCountriesPopup", new(ipadmin.SelectCountriesPopupAction)).
Get("/ipadmin/selectProvincesPopup", new(ipadmin.SelectProvincesPopupAction)).

View File

@@ -5,6 +5,7 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ipconfigs"
"github.com/iwind/TeaGo/maps"
timeutil "github.com/iwind/TeaGo/utils/time"
"time"
@@ -34,7 +35,7 @@ func (this *AllowListAction) RunGet(params struct {
// 创建
if listId == 0 {
listId, err = dao.SharedIPListDAO.CreateIPListForServerId(this.AdminContext(), params.ServerId, "white")
listId, err = dao.SharedIPListDAO.CreateIPListForServerId(this.AdminContext(), params.ServerId, ipconfigs.IPListTypeWhite)
if err != nil {
this.ErrorPage(err)
return

View File

@@ -5,6 +5,7 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ipconfigs"
"github.com/iwind/TeaGo/maps"
timeutil "github.com/iwind/TeaGo/utils/time"
"time"
@@ -34,7 +35,7 @@ func (this *DenyListAction) RunGet(params struct {
// 创建
if listId == 0 {
listId, err = dao.SharedIPListDAO.CreateIPListForServerId(this.AdminContext(), params.ServerId, "black")
listId, err = dao.SharedIPListDAO.CreateIPListForServerId(this.AdminContext(), params.ServerId, ipconfigs.IPListTypeBlack)
if err != nil {
this.ErrorPage(err)
return

View File

@@ -0,0 +1,140 @@
package ipadmin
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ipconfigs"
"github.com/iwind/TeaGo/maps"
timeutil "github.com/iwind/TeaGo/utils/time"
"time"
)
type GreyListAction struct {
actionutils.ParentAction
}
func (this *GreyListAction) Init() {
this.Nav("", "setting", "greyList")
this.SecondMenu("waf")
}
func (this *GreyListAction) RunGet(params struct {
FirewallPolicyId int64
ServerId int64
}) {
this.Data["featureIsOn"] = true
this.Data["firewallPolicyId"] = params.FirewallPolicyId
listId, err := dao.SharedIPListDAO.FindGreyIPListIdWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)
return
}
// 创建
if listId == 0 {
listId, err = dao.SharedIPListDAO.CreateIPListForServerId(this.AdminContext(), params.ServerId, ipconfigs.IPListTypeGrey)
if err != nil {
this.ErrorPage(err)
return
}
}
this.Data["listId"] = listId
// 数量
countResp, err := this.RPC().IPItemRPC().CountIPItemsWithListId(this.AdminContext(), &pb.CountIPItemsWithListIdRequest{IpListId: listId})
if err != nil {
this.ErrorPage(err)
return
}
var count = countResp.Count
var page = this.NewPage(count)
this.Data["page"] = page.AsHTML()
// 列表
itemsResp, err := this.RPC().IPItemRPC().ListIPItemsWithListId(this.AdminContext(), &pb.ListIPItemsWithListIdRequest{
IpListId: listId,
Offset: page.Offset,
Size: page.Size,
})
if err != nil {
this.ErrorPage(err)
return
}
var itemMaps = []maps.Map{}
for _, item := range itemsResp.IpItems {
var expiredTime = ""
if item.ExpiredAt > 0 {
expiredTime = timeutil.FormatTime("Y-m-d H:i:s", item.ExpiredAt)
}
// policy
var sourcePolicyMap = maps.Map{"id": 0}
if item.SourceHTTPFirewallPolicy != nil {
sourcePolicyMap = maps.Map{
"id": item.SourceHTTPFirewallPolicy.Id,
"name": item.SourceHTTPFirewallPolicy.Name,
"serverId": item.SourceHTTPFirewallPolicy.ServerId,
}
}
// group
var sourceGroupMap = maps.Map{"id": 0}
if item.SourceHTTPFirewallRuleGroup != nil {
sourceGroupMap = maps.Map{
"id": item.SourceHTTPFirewallRuleGroup.Id,
"name": item.SourceHTTPFirewallRuleGroup.Name,
}
}
// set
var sourceSetMap = maps.Map{"id": 0}
if item.SourceHTTPFirewallRuleSet != nil {
sourceSetMap = maps.Map{
"id": item.SourceHTTPFirewallRuleSet.Id,
"name": item.SourceHTTPFirewallRuleSet.Name,
}
}
// server
var sourceServerMap = maps.Map{"id": 0}
if item.SourceServer != nil {
sourceServerMap = maps.Map{
"id": item.SourceServer.Id,
"name": item.SourceServer.Name,
}
}
itemMaps = append(itemMaps, maps.Map{
"id": item.Id,
"value": item.Value,
"ipFrom": item.IpFrom,
"ipTo": item.IpTo,
"createdTime": timeutil.FormatTime("Y-m-d", item.CreatedAt),
"expiredTime": expiredTime,
"lifeSeconds": item.ExpiredAt - time.Now().Unix(),
"reason": item.Reason,
"type": item.Type,
"isExpired": item.ExpiredAt > 0 && item.ExpiredAt < time.Now().Unix(),
"eventLevelName": firewallconfigs.FindFirewallEventLevelName(item.EventLevel),
"sourcePolicy": sourcePolicyMap,
"sourceGroup": sourceGroupMap,
"sourceSet": sourceSetMap,
"sourceServer": sourceServerMap,
})
}
this.Data["items"] = itemMaps
// WAF是否启用
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
if err != nil {
this.ErrorPage(err)
return
}
this.Data["wafIsOn"] = webConfig.FirewallRef != nil && webConfig.FirewallRef.IsOn
this.Show()
}

View File

@@ -154,7 +154,7 @@ Vue.component("ip-list-table", {
</div>
</td>
<td>
<span v-if="item.type != 'all'" :class="{green: item.list != null && item.list.type == 'white'}">
<span v-if="item.type != 'all'" :class="{green: item.list != null && item.list.type == 'white', grey: item.list != null && item.list.type == 'grey'}">
<span v-if="item.value != null && item.value.length > 0"><keyword :v-word="keyword">{{item.value}}</keyword></span>
<span v-else>
<keyword :v-word="keyword">{{item.ipFrom}}</keyword> <span> <span class="small red" v-if="item.isRead != null && !item.isRead">&nbsp;New&nbsp;</span>&nbsp;<a :href="'/servers/iplists?ip=' + item.ipFrom" v-if="vShowSearchButton" title="搜索此IP"><span><i class="icon search small" style="color: #ccc"></i></span></a></span>
@@ -174,13 +174,14 @@ Vue.component("ip-list-table", {
<span v-if="item.list != null && item.list.id > 0">
@
<a :href="'/servers/iplists/list?listId=' + item.list.id" v-if="item.policy.id == 0"><span>[<span v-if="item.list.type == 'black'">黑</span><span v-if="item.list.type == 'white'">白</span>名单:{{item.list.name}}]</span></a>
<span v-else>[<span v-if="item.list.type == 'black'">黑</span><span v-if="item.list.type == 'white'">白</span>名单:{{item.list.name}}</span>
<a :href="'/servers/iplists/list?listId=' + item.list.id" v-if="item.policy.id == 0"><span>[<span v-if="item.list.type == 'black'">黑</span><span v-if="item.list.type == 'white'">白</span><span v-if="item.list.type == 'grey'">灰</span>名单:{{item.list.name}}]</span></a>
<span v-else>[<span v-if="item.list.type == 'black'">黑</span><span v-if="item.list.type == 'white'">白</span><span v-if="item.list.type == 'grey'">灰</span>名单:{{item.list.name}}</span>
<span v-if="item.policy.id > 0">
<span v-if="item.policy.server != null">
<a :href="'/servers/server/settings/waf/ipadmin/allowList?serverId=' + item.policy.server.id + '&firewallPolicyId=' + item.policy.id" v-if="item.list.type == 'white'">[网站:{{item.policy.server.name}}]</a>
<a :href="'/servers/server/settings/waf/ipadmin/denyList?serverId=' + item.policy.server.id + '&firewallPolicyId=' + item.policy.id" v-if="item.list.type == 'black'">[网站:{{item.policy.server.name}}]</a>
<a :href="'/servers/server/settings/waf/ipadmin/greyList?serverId=' + item.policy.server.id + '&firewallPolicyId=' + item.policy.id" v-if="item.list.type == 'grey'">[网站:{{item.policy.server.name}}]</a>
</span>
<span v-else>
<a :href="'/servers/components/waf/ipadmin/lists?firewallPolicyId=' + item.policy.id + '&type=' + item.list.type">[策略:{{item.policy.name}}]</a>

View File

@@ -175,7 +175,7 @@ Vue.component("http-cache-config-box", {
<td>添加X-Cache报头</td>
<td>
<checkbox v-model="cacheConfig.addStatusHeader"></checkbox>
<p class="comment">选中后自动在响应Header中增加<code-label>X-Cache: BYPASS|MISS|HIT|PURGE</code-label>在浏览器端查看X-Cache值时请先禁用浏览器缓存避免影响观察。</p>
<p class="comment">选中后自动在响应报头中增加<code-label>X-Cache: BYPASS|MISS|HIT|PURGE</code-label>在浏览器端查看X-Cache值时请先禁用浏览器缓存避免影响观察。</p>
</td>
</tr>
<tr>

View File

@@ -896,6 +896,7 @@ Vue.component("http-firewall-actions-box", {
<select class="ui dropdown auto-width" v-model="recordIPType">
<option value="black">黑名单</option>
<option value="white">白名单</option>
<option value="grey">灰名单</option>
</select>
</td>
</tr>

View File

@@ -11,6 +11,11 @@ Vue.component("http-firewall-actions-view", {
<span v-if="action.options.scope == 'server'">[网站]</span>
<span v-if="action.options.scope == 'global'">[网站和策略]</span>
</span>
<span class="grey small" v-if="action.code.toLowerCase() == 'record_ip'">
<span v-if="action.options.type == 'black'" class="red">黑名单</span>
<span v-if="action.options.type == 'white'" class="green">白名单</span>
<span v-if="action.options.type == 'grey'" class="grey">灰名单</span>
</span>
</div>
</span>
</div>

View File

@@ -4,5 +4,6 @@
<span class="item disabled">|</span>
<menu-item :href="'/servers/components/waf/ipadmin/lists?firewallPolicyId=' + firewallPolicyId + '&type=white'" :active="subMenuItem == 'white'">白名单</menu-item>
<menu-item :href="'/servers/components/waf/ipadmin/lists?firewallPolicyId=' + firewallPolicyId + '&type=black'" :active="subMenuItem == 'black'">黑名单</menu-item>
<menu-item :href="'/servers/components/waf/ipadmin/lists?firewallPolicyId=' + firewallPolicyId + '&type=grey'" :active="subMenuItem == 'grey'">灰名单</menu-item>
<menu-item :href="'/servers/components/waf/ipadmin/test?firewallPolicyId=' + firewallPolicyId" :active="subMenuItem == 'test'">IP检查</menu-item>
</second-menu>

View File

@@ -1,4 +1,6 @@
<first-menu>
<menu-item :href="'/servers/iplists'">IP列表</menu-item>
<raquo-item></raquo-item>
<menu-item :href="'/servers/iplists/lists?type=' + list.type">{{list.typeName}}</menu-item>
<span class="disabled item">|</span>
<menu-item :href="'/servers/iplists/list?listId=' + list.id" code="list">"{{list.name}}"详情</menu-item>

View File

@@ -1,10 +1,11 @@
<first-menu>
<menu-item href="/servers/iplists" code="index">IP列表</menu-item>
<span class="disabled item">|</span>
<menu-item href="/servers/iplists/lists?type=black" :active="type == 'black'">公共黑名单</menu-item>
<menu-item href="/servers/iplists/lists?type=white" :active="type == 'white'">公共白名单</menu-item>
<menu-item href="/servers/iplists/lists?type=black" :active="type == 'black'">黑名单</menu-item>
<menu-item href="/servers/iplists/lists?type=white" :active="type == 'white'">白名单</menu-item>
<menu-item href="/servers/iplists/lists?type=grey" :active="type == 'grey'">灰名单</menu-item>
<span class="item disabled" v-if="type.length > 0">|</span>
<menu-item @click.prevent="createList" v-if="type.length > 0">[创建名单]</menu-item>
<span class="item disabled" v-if="type.length > 0">|</span>
<span class="item" v-if="type.length > 0"><tip-icon content="全局名单自动生效非全局名单可以在WAF策略里引用。"></tip-icon></span>
<span class="item" v-if="type.length > 0"><tip-icon content="创建名单时可以选择“全局有效”就会成为全局有效名单,全局有效名单对所有网站自动生效;非全局有效名单可以在WAF策略里引用。<br/><br/>黑名单其中的IP将会被禁止访问。<br/>白名单其中的IP将会自动放行优先级高于黑名单。<br/>灰名单其中的IP仅作为记录和观察使用不影响黑名单和白名单的作用。"></tip-icon></span>
</first-menu>

View File

@@ -22,6 +22,7 @@
<td class="center">
<span v-if="list.type == 'black'">黑名单</span>
<span v-if="list.type == 'white'">白名单</span>
<span v-if="list.type == 'grey'">灰名单</span>
</td>
<td>{{list.description}}</td>
<td class="center">

View File

@@ -2,6 +2,7 @@
<h3 v-if="list.type == 'white'">添加IP到白名单</h3>
<h3 v-if="list.type == 'black'">添加IP到黑名单</h3>
<h3 v-if="list.type == 'grey'">添加IP到灰名单</h3>
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
<input type="hidden" name="listId" :value="listId"/>

View File

@@ -1,6 +1,7 @@
{$layout "layout_popup"}
<h3>创建<var v-if="type == 'black'">黑名单</var><var v-if="type == 'white'">白名单</var></h3>
<h3>创建<var v-if="type == 'black'">黑名单</var><var v-if="type == 'white'">白名单</var><var v-if="type == 'grey'">灰名单</var>
</h3>
<form class="ui form" data-tea-action="$" data-tea-success="success">
<csrf-token></csrf-token>
@@ -24,7 +25,11 @@
<select class="ui dropdown auto-width" name="type" v-model="type">
<option value="black">黑名单</option>
<option value="white">白名单</option>
<option value="grey">灰名单</option>
</select>
<p class="comment" v-if="type == 'black'">黑名单中的IP将会被禁止访问。</p>
<p class="comment" v-if="type == 'white'">白名单中的IP将会自动放行优先级高于黑名单。</p>
<p class="comment" v-if="type == 'grey'">灰名单中的IP仅作为记录和观察使用不影响黑名单和白名单的作用。</p>
</td>
</tr>
<tr>

View File

@@ -12,6 +12,7 @@
<option value="">[类型]</option>
<option value="black">黑名单</option>
<option value="white">白名单</option>
<option value="grey">灰名单</option>
</select>
</div>
<div class="ui field">

View File

@@ -38,8 +38,9 @@
<div v-if="list.isGlobal" style="margin-top: 0.3em"><grey-label>全局</grey-label></div>
</td>
<td class="center">
<span v-if="list.type == 'black'">黑名单</span>
<span v-if="list.type == 'white'">白名单</span>
<span v-if="list.type == 'black'"><span class="red">黑名单</span></span>
<span v-if="list.type == 'white'"><span class="green">白名单</span></span>
<span v-if="list.type == 'grey'"><span class="grey">灰名单</span></span>
</td>
<td>{{list.description}}</td>
<td class="center">

View File

@@ -1,7 +1,7 @@
Tea.context(function () {
this.createList = function () {
teaweb.popup(Tea.url(".createPopup", {type: this.type}), {
height: "30em",
height: "32em",
callback: function (resp) {
teaweb.success("保存成功", function () {
window.location = "/servers/iplists/lists?type=" + resp.data.list.type

View File

@@ -21,6 +21,7 @@
<td class="center">
<span v-if="list.type == 'black'">黑名单</span>
<span v-if="list.type == 'white'">白名单</span>
<span v-if="list.type == 'grey'">灰名单</span>
</td>
<td>{{list.description}}</td>
<td class="center">

View File

@@ -7,5 +7,6 @@
<menu-item :href="'/servers/server/settings/waf/ipadmin/provinces?serverId=' + serverId + '&firewallPolicyId='+firewallPolicyId" code="province">省份封禁</menu-item>
<menu-item :href="'/servers/server/settings/waf/ipadmin/allowList?serverId=' + serverId + '&firewallPolicyId='+firewallPolicyId" code="allowList">白名单</menu-item>
<menu-item :href="'/servers/server/settings/waf/ipadmin/denyList?serverId=' + serverId + '&firewallPolicyId='+firewallPolicyId" code="denyList">黑名单</menu-item>
<menu-item :href="'/servers/server/settings/waf/ipadmin/greyList?serverId=' + serverId + '&firewallPolicyId='+firewallPolicyId" code="greyList">灰名单</menu-item>
<menu-item :href="'/servers/server/settings/waf/ipadmin/test?serverId=' + serverId + '&firewallPolicyId='+firewallPolicyId" code="test">IP检查</menu-item>
</first-menu>

View File

@@ -0,0 +1,26 @@
{$layout}
{$template "../../settings_menu"}
{$template "/left_menu_with_menu"}
<div class="right-box with-menu">
{$template "../menu"}
<warning-message v-if="!featureIsOn">尚未为当前用户开通此功能。</warning-message>
{$ if .featureIsOn}
<second-menu>
<menu-item @click.prevent="createIP('grey')">添加IP</menu-item>
<span class="item">|</span>
<div class="item"><ip-list-bind-box :v-http-firewall-policy-id="firewallPolicyId" :v-type="'grey'"></ip-list-bind-box></div>
<span class="item">|</span>
<span class="item">ID: {{listId}} &nbsp; <tip-icon content="ID可以用于使用API操作此IP名单灰名单中的IP仅作为记录和观察使用不影响黑名单和白名单的作用。"></tip-icon></span>
</second-menu>
<warning-message v-if="!wafIsOn">当前WAF未启用设置将在<a :href="'/servers/server/settings/waf?serverId=' + serverId">[启用]</a>后生效。</warning-message>
<p class="comment" v-if="items.length == 0">暂时还没有IP。</p>
<ip-list-table v-if="items.length > 0" :v-items="items" @update-item="updateItem" @delete-item="deleteItem"></ip-list-table>
<div class="page" v-html="page"></div>
{$end}
</div>

View File

@@ -0,0 +1,38 @@
Tea.context(function () {
this.updateItem = function (itemId) {
teaweb.popup(Tea.url(".updateIPPopup?listId=" + this.listId, {itemId: itemId}), {
height: "30em",
callback: function () {
teaweb.success("保存成功", function () {
teaweb.reload()
})
}
})
}
this.deleteItem = function (itemId) {
let that = this
teaweb.confirm("确定要删除这个IP吗", function () {
that.$post(".deleteIP")
.params({
"listId": this.listId,
"itemId": itemId
})
.refresh()
})
}
/**
* 添加IP名单菜单
*/
this.createIP = function (type) {
teaweb.popup("/servers/iplists/createIPPopup?listId=" + this.listId + '&type=' + type, {
height: "30em",
callback: function () {
teaweb.success("保存成功", function () {
teaweb.reload()
})
}
})
}
})