diff --git a/backend/i18n/lang/en.yaml b/backend/i18n/lang/en.yaml
index 26b56cc72..a175e38da 100644
--- a/backend/i18n/lang/en.yaml
+++ b/backend/i18n/lang/en.yaml
@@ -166,3 +166,7 @@ CutWebsiteLogSuccess: "{{ .name }} website log cut successfully, backup path {{
#toolbox
ErrNotExistUser: "The current user does not exist. Please modify and retry!"
ErrBanAction: "Setting failed, the current {{ .name }} service is unavailable, please check and try again!"
+
+#waf
+ErrScope: "Modification of this configuration is not supported"
+ErrStateChange: "State modification failed"
\ No newline at end of file
diff --git a/backend/i18n/lang/zh-Hant.yaml b/backend/i18n/lang/zh-Hant.yaml
index df28f8727..a5293e109 100644
--- a/backend/i18n/lang/zh-Hant.yaml
+++ b/backend/i18n/lang/zh-Hant.yaml
@@ -167,3 +167,7 @@ CutWebsiteLogSuccess: "{{ .name }} 網站日誌切割成功,備份路徑 {{ .p
#toolbox
ErrNotExistUser: "當前使用者不存在,請修改後重試!"
ErrBanAction: "設置失敗,當前 {{ .name }} 服務不可用,請檢查後重試!"
+
+#waf
+ErrScope: "不支援修改此配置"
+ErrStateChange: "狀態修改失敗"
diff --git a/backend/i18n/lang/zh.yaml b/backend/i18n/lang/zh.yaml
index c6d0e132b..9594919cf 100644
--- a/backend/i18n/lang/zh.yaml
+++ b/backend/i18n/lang/zh.yaml
@@ -165,4 +165,8 @@ CutWebsiteLogSuccess: "{{ .name }} 网站日志切割成功,备份路径 {{ .p
#toolbox
ErrNotExistUser: "当前用户不存在,请修改后重试!"
-ErrBanAction: "设置失败,当前 {{ .name }} 服务不可用,请检查后重试!"
\ No newline at end of file
+ErrBanAction: "设置失败,当前 {{ .name }} 服务不可用,请检查后重试!"
+
+#waf
+ErrScope: "不支持修改此配置"
+ErrStateChange: "状态修改失败"
\ No newline at end of file
diff --git a/frontend/src/components/config-card/index.vue b/frontend/src/components/config-card/index.vue
new file mode 100644
index 000000000..dd63e4d59
--- /dev/null
+++ b/frontend/src/components/config-card/index.vue
@@ -0,0 +1,56 @@
+
+
+
+ {{ description }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts
index 6f9475743..07d70f665 100644
--- a/frontend/src/lang/modules/en.ts
+++ b/frontend/src/lang/modules/en.ts
@@ -2157,7 +2157,7 @@ const message = {
request: 'request',
count4xx: '4xx quantity',
count5xx: '5xx quantity',
- todayStatus: 'Today status',
+ todayStatus: 'Today Status',
reqMap: 'Request map (30 days)',
resource: 'source',
count: 'Quantity',
@@ -2167,6 +2167,45 @@ const message = {
interceptCount: 'Interception number',
requestTrends: 'Request Trends (7 days)',
interceptTrends: 'Intercept Trends (7 days)',
+ whiteList: 'whitelist',
+ blackList: 'blacklist',
+ ipBlackListHelper: 'IPs in the blacklist cannot access the website',
+ ipWhiteListHelper: 'IPs in the whitelist are not restricted by any rules',
+ uaBlackListHelper: 'Requests carrying User-Agent in the blacklist will be intercepted',
+ uaWhiteListHelper: 'Requests carrying User-Agent in the whitelist are not restricted by any rules',
+ urlBlackListHelper: 'Requests for URLs in the blacklist will be intercepted',
+ urlWhiteListHelper: 'Requests for URLs in the whitelist are not restricted by any rules',
+ ccHelper:
+ 'If any website has been requested more than {1} times in {0} seconds, this IP will be blocked for {2} seconds',
+ blockTime: 'Block time',
+ attackHelper:
+ 'The cumulative interception exceeds {1} times within {0} seconds, block this IP for {2} seconds',
+ notFoundHelper:
+ 'The cumulative request returned 404 more than {1} times within {0} seconds, block this IP for {2} seconds',
+ frequencyLimit: 'frequency limit',
+ regionLimit: 'region limit',
+ defaultRule: 'Default rule',
+ accessFrequencyLmit: 'Access frequency limit',
+ attackLimit: 'Attack frequency limit',
+ notFoundLimit: '404 frequency limit',
+ urlLimit: 'URL frequency limit',
+ urlLimitHelper: 'Set access frequency for a single URL',
+ sqliDefense: 'SQL injection defense',
+ sqliHelper: 'Identify SQL injection in requests and intercept',
+ xssHelper: 'Identify XSS in the request and intercept it',
+ xssDefense: 'XSS Defense',
+ uaDefense: 'Malicious User-Agent Rule',
+ uaHelper: 'Contains common malicious crawler rules',
+ argsDefense: 'Malicious parameter rules',
+ argsHelper: 'Prohibit malicious parameters in requests',
+ cookieDefense: 'Malicious Cookie Rule',
+ cookieHelper: 'Prohibit malicious cookies from being carried in requests',
+ headerDefense: 'Malicious Header Rule',
+ headerHelper: 'Prohibit requests from containing malicious headers',
+ httpRule: 'HTTP request method rules',
+ httpHelper: 'Restrict the request method type of the website',
+ geoRule: 'Regional access restrictions',
+ geoHelper: 'Restrict access to your website from certain regions',
},
monitor: {
name: 'Website Monitoring',
diff --git a/frontend/src/lang/modules/tw.ts b/frontend/src/lang/modules/tw.ts
index 907a75814..01930af17 100644
--- a/frontend/src/lang/modules/tw.ts
+++ b/frontend/src/lang/modules/tw.ts
@@ -2025,6 +2025,42 @@ const message = {
interceptCount: '攔截數',
requestTrends: '請求趨勢(7天)',
interceptTrends: '攔截趨勢(7天)',
+ whiteList: '白名單',
+ blackList: '黑名單',
+ ipBlackListHelper: '黑名單中的 IP 無法存取網站',
+ ipWhiteListHelper: '白名單中的 IP 不受任何規則限制',
+ uaBlackListHelper: '攜帶黑名單中的 User-Agent 的請求將被攔截',
+ uaWhiteListHelper: '攜帶白名單中的 User-Agent 的請求不受任何規則限制',
+ urlBlackListHelper: '請求黑名單中的 URL 將被攔截',
+ urlWhiteListHelper: '請求白名單中的 URL 請求不受任何規則限制',
+ ccHelper: '{0} 秒內累積請求任意網站超過 {1} 次,封鎖此 IP {2} 秒',
+ blockTime: '封鎖時間',
+ attackHelper: '{0} 秒內累計攔截超過 {1} 次,封鎖此 IP {2} 秒',
+ notFoundHelper: '{0} 秒內累計請求回傳 404 超過 {1} 次,封鎖此 IP {2} 秒',
+ frequencyLimit: '頻率限制',
+ regionLimit: '地區限制',
+ defaultRule: '預設規則',
+ accessFrequencyLmit: '存取頻率限制',
+ attackLimit: '攻擊頻率限制',
+ notFoundLimit: '404 頻率限制',
+ urlLimit: 'URL 頻率限制',
+ urlLimitHelper: '為單一 URL 設定存取頻率',
+ sqliDefense: 'SQL 注入防禦',
+ sqliHelper: '辨識請求中的 SQL 注入並攔截',
+ xssHelper: '辨識請求中的 XSS 並攔截',
+ xssDefense: 'XSS 防禦',
+ uaDefense: '惡意 User-Agent 規則',
+ uaHelper: '包含常見的惡意爬蟲規則',
+ argsDefense: '惡意參數規則',
+ argsHelper: '在禁止請求中攜帶惡意參數',
+ cookieDefense: '惡意 Cookie 規則',
+ cookieHelper: '禁止請求中攜帶惡意 Cookie',
+ headerDefense: '惡意 Header 規則',
+ headerHelper: '禁止請求中攜帶惡意 Header',
+ httpRule: 'HTTP 請求方法規則',
+ httpHelper: '限制網站的請求方法類型',
+ geoRule: '地區存取限制',
+ geoHelper: '限制某些地區造訪你的網站',
},
monitor: {
name: '網站監控',
diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts
index fd39316b4..40867161a 100644
--- a/frontend/src/lang/modules/zh.ts
+++ b/frontend/src/lang/modules/zh.ts
@@ -2026,6 +2026,42 @@ const message = {
interceptCount: '拦截数',
requestTrends: '请求趋势(7日)',
interceptTrends: '拦截趋势(7日)',
+ whiteList: '白名单',
+ blackList: '黑名单',
+ ipBlackListHelper: '黑名单中的 IP 无法访问网站',
+ ipWhiteListHelper: '白名单中的 IP 不受任何规则限制',
+ uaBlackListHelper: '携带黑名单中的 User-Agent 的请求将被拦截',
+ uaWhiteListHelper: '携带白名单中的 User-Agent 的请求不受任何规则限制',
+ urlBlackListHelper: '请求黑名单中的 URL 将被拦截',
+ urlWhiteListHelper: '请求白名单中的 URL 请求不受任何规则限制',
+ ccHelper: '{0} 秒内累计请求任意网站超过 {1} 次,封锁此 IP {2} 秒',
+ blockTime: '封禁时间',
+ attackHelper: '{0} 秒内累计拦截超过 {1} 次,封锁此 IP {2} 秒',
+ notFoundHelper: '{0} 秒内累计请求返回 404 超过 {1} 次,封锁此 IP {2} 秒',
+ frequencyLimit: '频率限制',
+ regionLimit: '地区限制',
+ defaultRule: '默认规则',
+ accessFrequencyLmit: '访问频率限制',
+ attackLimit: '攻击频率限制',
+ notFoundLimit: '404 频率限制',
+ urlLimit: 'URL 频率限制',
+ urlLimitHelper: '为单个 URL 设置访问频率',
+ sqliDefense: 'SQL 注入防御',
+ sqliHelper: '识别请求中的 SQL 注入并拦截',
+ xssHelper: '识别请求中的 XSS 并拦截',
+ xssDefense: 'XSS 防御',
+ uaDefense: '恶意 User-Agent 规则',
+ uaHelper: '包含常见的恶意爬虫规则',
+ argsDefense: '恶意参数规则',
+ argsHelper: '禁止请求中携带恶意参数',
+ cookieDefense: '恶意 Cookie 规则',
+ cookieHelper: '禁止请求中携带恶意 Cookie',
+ headerDefense: '恶意 Header 规则',
+ headerHelper: '禁止请求中携带恶意 Header',
+ httpRule: 'HTTP 请求方法规则',
+ httpHelper: '限制网站的请求方法类型',
+ geoRule: '地区访问限制',
+ geoHelper: '限制某些地区访问你的网站',
},
monitor: {
name: '网站监控',
diff --git a/plugins/openresty/waf/conf/global.json b/plugins/openresty/waf/conf/global.json
index a50d57ef4..2c36408b5 100644
--- a/plugins/openresty/waf/conf/global.json
+++ b/plugins/openresty/waf/conf/global.json
@@ -117,7 +117,7 @@
"action": "deny",
"code": 403,
"type": "fileExtCheck",
- "extList": [
+ "rules": [
"php",
"jsp",
"asp",
diff --git a/plugins/openresty/waf/lib/lib.lua b/plugins/openresty/waf/lib/lib.lua
index 96bc74cae..936251775 100644
--- a/plugins/openresty/waf/lib/lib.lua
+++ b/plugins/openresty/waf/lib/lib.lua
@@ -531,7 +531,7 @@ function _M.post_check()
local match = ngx_re_match(m[0], 'Content-Disposition: form-data; (.+)filename="(.+)\\.(.*)"', 'ijo')
if match then
local extension = match[3]
- for _, ext in ipairs(rule.extList) do
+ for _, ext in ipairs(rule.rules) do
if extension == ext then
exec_action(rule)
end
diff --git a/plugins/openresty/waf/lib/utils.lua b/plugins/openresty/waf/lib/utils.lua
index b1dc1f299..b7d163fe3 100644
--- a/plugins/openresty/waf/lib/utils.lua
+++ b/plugins/openresty/waf/lib/utils.lua
@@ -1,3 +1,4 @@
+local geoip = require "geoip"
local sub_str = string.sub
local pairs = pairs
local insert_table = table.insert
@@ -6,6 +7,7 @@ local ipairs = ipairs
local type = type
local find_str = string.find
local gmatch_str = string.gmatch
+local cjson = require "cjson"
local _M = {}
@@ -114,6 +116,32 @@ function _M.get_real_ip()
return "unknown"
end
+function _M.get_geo_ip(ip)
+ if _M.is_intranet_address(ip) then
+ return {
+ country = { ["zh"] = "内网", ["en"] = "intranet" },
+ province = { ["zh"] = "内网", ["en"] = "intranet" },
+ city = { ["zh"] = "内网", ["en"] = "intranet" },
+ longitude = 0,
+ latitude = 0,
+ iso = "local"
+ }
+ else
+ geoip.init()
+ local geo_res = geoip.lookup(ip)
+ local msg = "访问 IP " .. ip
+ if geo_res.country then
+ msg = msg .. " 国家 " .. cjson.encode(geo_res.country)
+ end
+ if geo_res.province then
+ msg = msg .. " 省份 " .. cjson.encode(geo_res.province)
+ end
+ ngx.log(ngx.ERR, msg)
+ return geo_res
+
+ end
+end
+
function _M.get_header(headerKey)
return ngx.req.get_headers(20000)[headerKey]
end
diff --git a/plugins/openresty/waf/log_and_traffic.lua b/plugins/openresty/waf/log_and_traffic.lua
index 7ce81e4aa..a485e40e8 100644
--- a/plugins/openresty/waf/log_and_traffic.lua
+++ b/plugins/openresty/waf/log_and_traffic.lua
@@ -215,6 +215,16 @@ if config.is_waf_on() then
count_not_found()
local is_attack = ngx.ctx.is_attack
+ if not ngx.ctx.ip then
+ ngx.ctx.ip = utils.get_real_ip()
+ ngx.ctx.geoip = utils.get_geo_ip(ngx.ctx.ip)
+ local ua = utils.get_header("user-agent")
+ if not ua then
+ ua = ""
+ end
+ end
+
+
local wafdb = utils.get_wafdb(config.waf_db_path)
if wafdb ~= nil then
count_req_status(wafdb,is_attack)
diff --git a/plugins/openresty/waf/waf.lua b/plugins/openresty/waf/waf.lua
index 96d0dadbb..39acc1ddd 100644
--- a/plugins/openresty/waf/waf.lua
+++ b/plugins/openresty/waf/waf.lua
@@ -42,20 +42,7 @@ local function get_website_key()
return s_name
end
-local function get_geo_ip(ip)
- if utils.is_intranet_address(ip) then
- return {
- country = { ["zh"] = "内网", ["en"] = "intranet" },
- province = { ["zh"] = "内网", ["en"] = "intranet" },
- city = { ["zh"] = "内网", ["en"] = "intranet" },
- longitude = 0,
- latitude = 0,
- iso = "local"
- }
- else
- return geoip.lookup(ip)
- end
-end
+
local function init()
local ip = utils.get_real_ip()
@@ -64,21 +51,10 @@ local function init()
if not ua then
ua = ""
end
-
- geoip.init()
ngx.ctx.ua = ua
- ngx.ctx.geoip = get_geo_ip(ip)
-
- local msg = "访问 IP " .. ip
- if ngx.ctx.geoip.country then
- msg = msg .. " 国家 " .. cjson.encode(ngx.ctx.geoip.country)
- end
- if ngx.ctx.geoip.province then
- msg = msg .. " 省份 " .. cjson.encode(ngx.ctx.geoip.province)
- end
- ngx.log(ngx.ERR, msg)
-
+ ngx.ctx.geoip = utils.get_geo_ip(ip)
+
ngx.ctx.website_key = get_website_key()
ngx.ctx.method = ngx.req.get_method()
ngx.ctx.content_type = utils.get_header("content-type")
@@ -144,8 +120,6 @@ local function waf_api()
end
end
-ngx.log(ngx.ERR,"access waf")
-
if config.is_waf_on() then
init()
waf_api()