From 8d8245971a171e33c792b01aff1e7e391fdc6e5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E7=A5=A5=E8=B6=85?= Date: Sat, 20 Jan 2024 16:17:28 +0800 Subject: [PATCH] =?UTF-8?q?WAF=E7=AD=96=E7=95=A5=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E9=A1=B5=E9=9D=A2=E5=8A=A8=E4=BD=9C=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../default/servers/components/waf/policy.go | 1 + .../default/servers/components/waf/update.go | 23 ++++ .../server/http-firewall-actions-box.js | 23 +++- .../http-firewall-page-options-viewer.js | 15 +++ .../server/http-firewall-page-options.js | 67 +++++++++++ .../servers/components/waf/policy.html | 56 ++++++--- .../servers/components/waf/update.html | 108 +++++++++++------- 7 files changed, 229 insertions(+), 64 deletions(-) create mode 100644 web/public/js/components/server/http-firewall-page-options-viewer.js create mode 100644 web/public/js/components/server/http-firewall-page-options.js diff --git a/internal/web/actions/default/servers/components/waf/policy.go b/internal/web/actions/default/servers/components/waf/policy.go index 578bf087..2e7eacba 100644 --- a/internal/web/actions/default/servers/components/waf/policy.go +++ b/internal/web/actions/default/servers/components/waf/policy.go @@ -95,6 +95,7 @@ func (this *PolicyAction) RunGet(params struct { "modeInfo": firewallconfigs.FindFirewallMode(firewallPolicy.Mode), "groups": internalGroups, "blockOptions": firewallPolicy.BlockOptions, + "pageOptions": firewallPolicy.PageOptions, "captchaOptions": firewallPolicy.CaptchaOptions, "useLocalFirewall": firewallPolicy.UseLocalFirewall, "synFlood": firewallPolicy.SYNFlood, diff --git a/internal/web/actions/default/servers/components/waf/update.go b/internal/web/actions/default/servers/components/waf/update.go index 92c743be..51398f24 100644 --- a/internal/web/actions/default/servers/components/waf/update.go +++ b/internal/web/actions/default/servers/components/waf/update.go @@ -34,6 +34,7 @@ func (this *UpdateAction) RunGet(params struct { return } + // block options if firewallPolicy.BlockOptions == nil { firewallPolicy.BlockOptions = &firewallconfigs.HTTPFirewallBlockAction{ StatusCode: http.StatusForbidden, @@ -43,6 +44,11 @@ func (this *UpdateAction) RunGet(params struct { } } + // page options + if firewallPolicy.PageOptions == nil { + firewallPolicy.PageOptions = firewallconfigs.DefaultHTTPFirewallPageAction() + } + // mode if len(firewallPolicy.Mode) == 0 { firewallPolicy.Mode = firewallconfigs.FirewallModeDefend @@ -71,6 +77,7 @@ func (this *UpdateAction) RunGet(params struct { "isOn": firewallPolicy.IsOn, "mode": firewallPolicy.Mode, "blockOptions": firewallPolicy.BlockOptions, + "pageOptions": firewallPolicy.PageOptions, "captchaOptions": firewallPolicy.CaptchaOptions, "useLocalFirewall": firewallPolicy.UseLocalFirewall, "synFloodConfig": firewallPolicy.SYNFlood, @@ -107,6 +114,7 @@ func (this *UpdateAction) RunPost(params struct { Name string GroupCodes []string BlockOptionsJSON []byte + PageOptionsJSON []byte CaptchaOptionsJSON []byte Description string IsOn bool @@ -132,6 +140,19 @@ func (this *UpdateAction) RunPost(params struct { err := json.Unmarshal(params.BlockOptionsJSON, blockOptions) if err != nil { this.Fail("拦截动作参数校验失败:" + err.Error()) + return + } + + // 校验显示页面选项JSON + var pageOptions = &firewallconfigs.HTTPFirewallPageAction{} + err = json.Unmarshal(params.PageOptionsJSON, pageOptions) + if err != nil { + this.Fail("校验显示页面动作配置失败:" + err.Error()) + return + } + if pageOptions.Status < 100 && pageOptions.Status > 999 { + this.Fail("显示页面动作的状态码配置错误:" + types.String(pageOptions.Status)) + return } // 校验验证码选项JSON @@ -139,6 +160,7 @@ func (this *UpdateAction) RunPost(params struct { err = json.Unmarshal(params.CaptchaOptionsJSON, captchaOptions) if err != nil { this.Fail("验证码动作参数校验失败:" + err.Error()) + return } // 检查极验配置 @@ -170,6 +192,7 @@ func (this *UpdateAction) RunPost(params struct { Description: params.Description, FirewallGroupCodes: params.GroupCodes, BlockOptionsJSON: params.BlockOptionsJSON, + PageOptionsJSON: params.PageOptionsJSON, CaptchaOptionsJSON: params.CaptchaOptionsJSON, Mode: params.Mode, UseLocalFirewall: params.UseLocalFirewall, diff --git a/web/public/js/components/server/http-firewall-actions-box.js b/web/public/js/components/server/http-firewall-actions-box.js index 3db8e997..21f7ced2 100644 --- a/web/public/js/components/server/http-firewall-actions-box.js +++ b/web/public/js/components/server/http-firewall-actions-box.js @@ -105,6 +105,7 @@ Vue.component("http-firewall-actions-box", { tagTags: [], + pageUseDefault: true, pageStatus: 403, pageBody: defaultPageBody, defaultPageBody: defaultPageBody, @@ -302,6 +303,7 @@ Vue.component("http-firewall-actions-box", { this.tagTags = [] + this.pageUseDefault = true this.pageStatus = 403 this.pageBody = this.defaultPageBody @@ -429,8 +431,14 @@ Vue.component("http-firewall-actions-box", { } break case "page": + this.pageUseDefault = true this.pageStatus = 403 this.pageBody = this.defaultPageBody + if (typeof config.options.useDefault === "boolean") { + this.pageUseDefault = config.options.useDefault + } else { + this.pageUseDefault = false + } if (config.options.status != null) { this.pageStatus = config.options.status } @@ -533,6 +541,7 @@ Vue.component("http-firewall-actions-box", { } this.actionOptions = { + useDefault: this.pageUseDefault, status: pageStatus, body: this.pageBody } @@ -691,7 +700,7 @@ Vue.component("http-firewall-actions-box", { :{{config.options.tags.join(", ")}} - :[{{config.options.status}}] + :[{{config.options.status}}]  [默认页面] :{{config.options.url}} @@ -893,11 +902,17 @@ Vue.component("http-firewall-actions-box", { - 状态码 * + 使用默认提示 + + + + + + 状态码 * - - 网页内容 + + 网页内容 diff --git a/web/public/js/components/server/http-firewall-page-options-viewer.js b/web/public/js/components/server/http-firewall-page-options-viewer.js new file mode 100644 index 00000000..01dcd667 --- /dev/null +++ b/web/public/js/components/server/http-firewall-page-options-viewer.js @@ -0,0 +1,15 @@ +Vue.component("http-firewall-page-options-viewer", { + props: ["v-page-options"], + data: function () { + return { + options: this.vPageOptions + } + }, + template: `
+ 默认设置 +
+ 状态码:{{options.status}} / 提示内容:[{{options.body.length}}字符] +
+
+` +}) \ No newline at end of file diff --git a/web/public/js/components/server/http-firewall-page-options.js b/web/public/js/components/server/http-firewall-page-options.js new file mode 100644 index 00000000..253279a0 --- /dev/null +++ b/web/public/js/components/server/http-firewall-page-options.js @@ -0,0 +1,67 @@ +Vue.component("http-firewall-page-options", { + props: ["v-page-options"], + data: function () { + var defaultPageBody = ` + + + 403 Forbidden + + + +

403 Forbidden By WAF

+
Connection: \${remoteAddr} (Client) -> \${serverAddr} (Server)
+
Request ID: \${requestId}
+ +` + + return { + pageOptions: this.vPageOptions, + status: this.vPageOptions.status, + body: this.vPageOptions.body, + defaultPageBody: defaultPageBody, + isEditing: false + } + }, + watch: { + status: function (v) { + if (typeof v === "string" && v.length != 3) { + return + } + let statusCode = parseInt(v) + if (isNaN(statusCode)) { + this.pageOptions.status = 403 + } else { + this.pageOptions.status = statusCode + } + }, + body: function (v) { + this.pageOptions.body = v + } + }, + methods: { + edit: function () { + this.isEditing = !this.isEditing + } + }, + template: `
+ + 状态码:{{status}} / 提示内容:[{{pageOptions.body.length}}字符][无] + + + + + + + + + + +
状态码 *
网页内容 + +

[使用模板]

+
+
+` +}) \ No newline at end of file diff --git a/web/views/@default/servers/components/waf/policy.html b/web/views/@default/servers/components/waf/policy.html index 7c9e274c..39e01b06 100644 --- a/web/views/@default/servers/components/waf/policy.html +++ b/web/views/@default/servers/components/waf/policy.html @@ -26,12 +26,22 @@ + + +

动作配置

+ - + + + + + +
阻止动作设置阻止动作设置
显示页面动作设置 + +
人机识别动作配置 @@ -46,15 +56,12 @@

可以在合适的时候自动使用系统自带防火墙进行防御。

+ +

日志配置

+ - - - - - + +
SYN Flood防御 - 未启用 - -
记录访问日志记录访问日志 默认 开启 @@ -74,15 +81,12 @@ 不记录
+ +

区域封禁设置

+ - - - - - + +
最多检查内容尺寸 - 使用默认 - {{firewallPolicy.maxRequestBodySizeFormat}} -
区域封禁默认提示内容区域封禁默认提示内容 自定义 使用默认 @@ -95,6 +99,24 @@ 使用默认
+ +

其他配置

+ + + + + + + + + - - - - +
SYN Flood防御 + 未启用 + +
最多检查内容尺寸 + 使用默认 + {{firewallPolicy.maxRequestBodySizeFormat}} +
描述 diff --git a/web/views/@default/servers/components/waf/update.html b/web/views/@default/servers/components/waf/update.html index 94da3584..efcedcab 100644 --- a/web/views/@default/servers/components/waf/update.html +++ b/web/views/@default/servers/components/waf/update.html @@ -31,27 +31,84 @@

可以启用一些我们预置的规则组。

+ +

动作配置

+ + - + + + + + + +
阻止动作配置阻止动作配置
显示页面动作配置 + +
人机识别动作配置
+ +

日志配置

+ + + + + + + + + + + + + +
记录访问日志 + + +

选中后,总是记录WAF相关访问日志,即使服务中没有开启访问日志。

+
记录请求Body + +

选中后,表示在访问日志中记录匹配的请求内容。注意:此选项会明显增加访问日志占用空间,请谨慎开启。

+
记录区域封禁日志 + +

选中后,表示在访问日志中记录区域封禁(地区和省份)事件。

+
+ +

区域封禁设置

+ + + + + + + + + +
区域封禁默认提示内容 + +

当客户端所在区域被封禁时提示页面的HTML内容;不填则表示使用默认的提示内容;支持请求变量。

+
省份封禁默认提示内容 + +

当客户端所在省份被封禁时提示页面的HTML内容;不填则表示使用默认的提示内容;支持请求变量。

+
+ +

其他配置

+ + - + @@ -60,28 +117,6 @@ - - - - - - - - - - - - - - - - - - - -
使用系统防火墙使用系统防火墙 -

开启后,可以在合适的时候自动使用系统自带防火墙进行防御。

+

开启后,可以在合适的时候自动使用系统自带防火墙进行防御;建议在每个边缘节点都安装nftables以提升封禁性能。

记录访问日志 - - -

选中后,总是记录WAF相关访问日志,即使服务中没有开启访问日志。

-
记录请求Body - -

选中后,表示在访问日志中记录匹配的请求内容。注意:此选项会明显增加访问日志占用空间,请谨慎开启。

-
记录区域封禁日志 - -

选中后,表示在访问日志中记录区域封禁(地区和省份)事件。

-
最多检查内容尺寸 @@ -93,20 +128,6 @@

当前:{{maxRequestBodySizeFormat}}。WAF能够分析的最大文件内容尺寸,0表示默认,默认为512K;此值越大,对应使用的系统内存越多,除非特殊情况,否则请谨慎修改。

区域封禁默认提示内容 - -

当客户端所在区域被封禁时提示页面的HTML内容;不填则表示使用默认的提示内容;支持请求变量。

-
省份封禁默认提示内容 - -

当客户端所在省份被封禁时提示页面的HTML内容;不填则表示使用默认的提示内容;支持请求变量。

-
描述 @@ -124,5 +145,6 @@
+ \ No newline at end of file