mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-19 08:19:15 +08:00
feat(waf): 优化请求次数记录方式 (#4210)
This commit is contained in:
parent
7784ee9575
commit
cbfedb5d5e
@ -2167,7 +2167,7 @@ const message = {
|
||||
count4xx: '4xx quantity',
|
||||
count5xx: '5xx quantity',
|
||||
todayStatus: 'Today Status',
|
||||
reqMap: 'Request map (30 days)',
|
||||
reqMap: 'Attack map (30 days)',
|
||||
resource: 'source',
|
||||
count: 'Quantity',
|
||||
hight: 'high',
|
||||
|
@ -2024,7 +2024,7 @@ const message = {
|
||||
count4xx: '4xx 數量',
|
||||
count5xx: '5xx 數量',
|
||||
todayStatus: '今日狀態',
|
||||
reqMap: '請求地圖(30日)',
|
||||
reqMap: '攔截地圖(30日)',
|
||||
resource: '來源',
|
||||
count: '數量',
|
||||
hight: '高',
|
||||
|
@ -2025,7 +2025,7 @@ const message = {
|
||||
count4xx: '4xx 数量',
|
||||
count5xx: '5xx 数量',
|
||||
todayStatus: '今日状态',
|
||||
reqMap: '请求地图(30日)',
|
||||
reqMap: '拦截地图(30日)',
|
||||
resource: '来源',
|
||||
count: '数量',
|
||||
hight: '高',
|
||||
|
@ -1,7 +1,9 @@
|
||||
{
|
||||
"waf": "on",
|
||||
"mode": "protection",
|
||||
"secret": "qwer1234",
|
||||
"waf": {
|
||||
"state": "on",
|
||||
"mode": "protection",
|
||||
"secret": "qwer1234"
|
||||
},
|
||||
"redis": {
|
||||
"state": "off",
|
||||
"host": "127.0.0.1",
|
||||
@ -11,7 +13,9 @@
|
||||
"poolSize": 10
|
||||
},
|
||||
"ipWhite": {
|
||||
"state": "on"
|
||||
"state": "on",
|
||||
"type": "ipWhite",
|
||||
"action": "allow"
|
||||
},
|
||||
"ipBlack": {
|
||||
"state": "on",
|
||||
@ -21,7 +25,9 @@
|
||||
"res": "ip"
|
||||
},
|
||||
"urlWhite": {
|
||||
"state": "on"
|
||||
"type": "urlWhite",
|
||||
"state": "on",
|
||||
"action": "allow"
|
||||
},
|
||||
"urlBlack": {
|
||||
"type": "urlBlack",
|
||||
@ -30,7 +36,9 @@
|
||||
"action": "deny"
|
||||
},
|
||||
"uaWhite": {
|
||||
"state": "off"
|
||||
"type": "uaWhite",
|
||||
"state": "off",
|
||||
"action": "allow"
|
||||
},
|
||||
"uaBlack": {
|
||||
"type": "uaBlack",
|
||||
@ -64,7 +72,9 @@
|
||||
"geoRestrict": {
|
||||
"state": "on",
|
||||
"rules": [],
|
||||
"action": "deny"
|
||||
"code": 444,
|
||||
"action": "deny",
|
||||
"type": "geoRestrict"
|
||||
},
|
||||
"defaultIpBlack": {
|
||||
"state": "on",
|
||||
@ -87,7 +97,6 @@
|
||||
"cc": {
|
||||
"state": "off",
|
||||
"type": "cc",
|
||||
"rule": "cc",
|
||||
"tokenTimeOut": 1800,
|
||||
"threshold": 120,
|
||||
"duration": 60,
|
||||
@ -98,7 +107,6 @@
|
||||
"ccurl": {
|
||||
"state": "off",
|
||||
"type": "urlcc",
|
||||
"rule": "urlcc",
|
||||
"action": "deny",
|
||||
"ipBlock": "on",
|
||||
"ipBlockTime": 600
|
||||
@ -112,18 +120,11 @@
|
||||
"ipBlock": "on",
|
||||
"ipBlockTime": 600
|
||||
},
|
||||
"fileExtCheck": {
|
||||
"fileExt": {
|
||||
"state": "on",
|
||||
"action": "deny",
|
||||
"code": 403,
|
||||
"type": "fileExtCheck",
|
||||
"rules": [
|
||||
"php",
|
||||
"jsp",
|
||||
"asp",
|
||||
"exe",
|
||||
"sh"
|
||||
]
|
||||
"type": "fileExtCheck"
|
||||
},
|
||||
"cookie": {
|
||||
"type": "cookie",
|
||||
|
@ -145,15 +145,15 @@ function _M.get_html_res(name)
|
||||
end
|
||||
|
||||
function _M.is_waf_on()
|
||||
return config.global_config["waf"] == "on" and true or false
|
||||
return _M.is_global_state_on("waf")
|
||||
end
|
||||
|
||||
function _M.is_redis_on()
|
||||
return config.global_config["redis"] == "on" and true or false
|
||||
return _M.is_global_state_on("redis")
|
||||
end
|
||||
|
||||
function _M.get_secret()
|
||||
return config.global_config["secret"]
|
||||
return config.global_config["waf"]["secret"]
|
||||
end
|
||||
|
||||
return _M
|
@ -35,13 +35,12 @@ local function init_db_config(db_path)
|
||||
if not ok then
|
||||
return false
|
||||
end
|
||||
local wafdb
|
||||
wafdb = sqlite3.open(db_path)
|
||||
local wafdb = sqlite3.open(db_path)
|
||||
if wafdb == nil then
|
||||
return false
|
||||
end
|
||||
wafdb:exec([[PRAGMA journal_mode = wal]])
|
||||
wafdb:exec([[PRAGMA synchronous = 0]])
|
||||
wafdb:exec([[PRAGMA synchronous = OFF]])
|
||||
wafdb:exec([[PRAGMA page_size = 8192]])
|
||||
wafdb:exec([[PRAGMA journal_size_limit = 2147483648]])
|
||||
return wafdb
|
||||
|
@ -142,7 +142,11 @@ function _M.exec_action(rule_config, match_rule, data)
|
||||
|
||||
local msg = "访问 IP " .. ngx.ctx.ip .. " 访问 URL" .. ngx.var.uri .. " 触发动作 " .. action .. " 规则类型 " .. rule_config.type
|
||||
if match_rule then
|
||||
msg = msg .. " 触发规则 " .. match_rule.type
|
||||
if match_rule.type then
|
||||
msg = msg .. " 触发规则类型 " .. match_rule.type
|
||||
else
|
||||
msg = msg .. " 触发规则 " .. match_rule.rule
|
||||
end
|
||||
end
|
||||
|
||||
ngx.log(ngx.ERR, msg)
|
||||
|
@ -465,7 +465,6 @@ function _M.args_check()
|
||||
end
|
||||
if val_arr and type(val_arr) ~= "boolean" and val_arr ~= "" then
|
||||
local m, mr = match_rule(args_list, utils.unescape_uri(val_arr))
|
||||
ngx.log(ngx.ERR, "args_check: ", m, " ", mr.rule, " ", val_arr)
|
||||
if m then
|
||||
exec_action(get_global_config("args"), mr)
|
||||
return
|
||||
@ -531,7 +530,7 @@ function _M.post_check()
|
||||
|
||||
local boundary = get_boundary()
|
||||
|
||||
if boundary and is_site_state_on('fileExtCheck') then
|
||||
if boundary and is_state_on('fileExt') then
|
||||
if not ngx_re_match(content_type, '^multipart/form-data; boundary=') or not ngx_re_find(content_type, [[multipart]], 'ijo')then
|
||||
return
|
||||
end
|
||||
@ -548,7 +547,7 @@ function _M.post_check()
|
||||
return
|
||||
end
|
||||
|
||||
local rule = get_site_config("fileExtCheck")
|
||||
local rule = get_site_rule("fileExt")
|
||||
while true do
|
||||
local m = iterator()
|
||||
if m then
|
||||
|
@ -138,7 +138,7 @@ local function write_req_log(attack)
|
||||
is_block = is_block,
|
||||
is_attack = is_attack
|
||||
}
|
||||
local code = stmt:step()
|
||||
stmt:step()
|
||||
stmt:finalize()
|
||||
|
||||
local code2 = 101
|
||||
@ -160,11 +160,9 @@ local function write_req_log(attack)
|
||||
|
||||
wafdb:execute([[COMMIT]])
|
||||
|
||||
if code ~= 101 or code2 ~= 101 then
|
||||
local error_msg = wafdb:errmsg()
|
||||
if error_msg then
|
||||
ngx.log(ngx.ERR, "insert attack_log error ", error_msg .. " ")
|
||||
end
|
||||
local error_msg = wafdb:errmsg()
|
||||
if error_msg then
|
||||
ngx.log(ngx.ERR, "insert attack_log error ", error_msg .. " ")
|
||||
end
|
||||
|
||||
end
|
||||
@ -201,45 +199,25 @@ local function count_not_found()
|
||||
end
|
||||
end
|
||||
|
||||
local add_count = function(shared_dict,key)
|
||||
local count, _ = shared_dict:incr(key, 1)
|
||||
if not count then
|
||||
shared_dict:set(key, 1)
|
||||
end
|
||||
end
|
||||
|
||||
local function count_req_status(is_attack)
|
||||
local wafdb = utils.get_wafdb(config.waf_db_path)
|
||||
if not wafdb then
|
||||
ngx.log(ngx.ERR, "get log db failed")
|
||||
return
|
||||
end
|
||||
|
||||
local today = ngx.today()
|
||||
local status = ngx.status
|
||||
|
||||
local stmt_exist = wafdb:prepare("SELECT COUNT(*) FROM waf_stat WHERE day = ?")
|
||||
stmt_exist:bind_values(today)
|
||||
stmt_exist:step()
|
||||
local count = stmt_exist:get_uvalues()
|
||||
stmt_exist:finalize()
|
||||
|
||||
local req_count_update = 1
|
||||
local count_4xx_update = (status >= 400 and status < 500) and 1 or 0
|
||||
local count_5xx_update = (status >= 500) and 1 or 0
|
||||
local attack_count_update = is_attack and 1 or 0
|
||||
local code = 0
|
||||
|
||||
if count > 0 then
|
||||
local stmt = wafdb:prepare("UPDATE waf_stat SET req_count = req_count + ?, count4xx = count4xx + ?, count5xx = count5xx + ?, attack_count = attack_count + ? WHERE day = ?")
|
||||
stmt:bind_values(req_count_update, count_4xx_update, count_5xx_update, attack_count_update, today)
|
||||
code = stmt:step()
|
||||
stmt:finalize()
|
||||
else
|
||||
local stmt = wafdb:prepare("INSERT INTO waf_stat (day, req_count, count4xx, count5xx, attack_count,create_date) VALUES (?, ?, ?, ?, ?,DATETIME('now'))")
|
||||
stmt:bind_values(today, req_count_update, count_4xx_update, count_5xx_update, attack_count_update)
|
||||
code = stmt:step()
|
||||
stmt:finalize()
|
||||
local req_count = ngx.shared.dict_req_count
|
||||
add_count(req_count, "req_count")
|
||||
if (status >= 400 and status < 500) then
|
||||
add_count(req_count, "count_4xx")
|
||||
end
|
||||
|
||||
if code ~= 101 then
|
||||
local error_msg = wafdb:errmsg()
|
||||
if error_msg then
|
||||
ngx.log(ngx.ERR, "update waf_stat error ", error_msg .. " ")
|
||||
end
|
||||
if (status >= 500) then
|
||||
add_count(req_count, "count_5xx")
|
||||
end
|
||||
if is_attack then
|
||||
add_count(req_count, "attack_count")
|
||||
end
|
||||
end
|
||||
|
||||
@ -250,12 +228,10 @@ if config.is_waf_on() then
|
||||
if not ngx.ctx.ip then
|
||||
ngx.ctx.ip = utils.get_real_ip()
|
||||
ngx.ctx.ip_location = utils.get_ip_location(ngx.ctx.ip)
|
||||
local ua = utils.get_header("user-agent")
|
||||
if not ua then
|
||||
ua = ""
|
||||
end
|
||||
end
|
||||
|
||||
count_req_status(is_attack)
|
||||
write_req_log(is_attack)
|
||||
if is_attack then
|
||||
write_req_log(is_attack)
|
||||
end
|
||||
end
|
||||
|
@ -2,21 +2,23 @@
|
||||
"rules": [
|
||||
{
|
||||
"state": "on",
|
||||
"rule": "no Cookie",
|
||||
"name": "拦截不带Cookie的请求",
|
||||
"name": "no cookie",
|
||||
"conditions": [
|
||||
{
|
||||
"field": "URL",
|
||||
"pattern": "/test/\\d+\\.html"
|
||||
"pattern": "eq",
|
||||
"rule": "/test/\\d+\\.html"
|
||||
},
|
||||
{
|
||||
"field": "Cookie",
|
||||
"pattern": ""
|
||||
"pattern": "eq",
|
||||
"rule": ""
|
||||
}
|
||||
],
|
||||
"action": "deny",
|
||||
"autoIpBlock": "off",
|
||||
"ipBlockTimeout": 60,
|
||||
"res": "",
|
||||
"ipBlock": "off",
|
||||
"ipBlockTime": 60,
|
||||
"description": "拦截不带Cookie的请求"
|
||||
}
|
||||
]
|
||||
|
34
plugins/openresty/waf/rules/fileExt.json
Normal file
34
plugins/openresty/waf/rules/fileExt.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"rules": [
|
||||
{
|
||||
"state": "on",
|
||||
"rule": "php",
|
||||
"name": "php",
|
||||
"type": "fileExt"
|
||||
},
|
||||
{
|
||||
"state": "on",
|
||||
"rule": "jsp",
|
||||
"name": "jsp",
|
||||
"type": "fileExt"
|
||||
},
|
||||
{
|
||||
"state": "on",
|
||||
"rule": "asp",
|
||||
"name": "asp",
|
||||
"type": "fileExt"
|
||||
},
|
||||
{
|
||||
"state": "on",
|
||||
"rule": "exe",
|
||||
"name": "exe",
|
||||
"type": "fileExt"
|
||||
},
|
||||
{
|
||||
"state": "on",
|
||||
"rule": "sh",
|
||||
"name": "sh",
|
||||
"type": "fileExt"
|
||||
}
|
||||
]
|
||||
}
|
16
plugins/openresty/waf/rules/geoRestrict.json
Normal file
16
plugins/openresty/waf/rules/geoRestrict.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"rules": [
|
||||
{
|
||||
"state": "on",
|
||||
"name": "appFilter1",
|
||||
"rule": "/TomcatBypass/Command/Base64",
|
||||
"type": "appFilter"
|
||||
},
|
||||
{
|
||||
"state": "on",
|
||||
"name": "appFilter2",
|
||||
"rule": "j\\S*ndi\\S*:\\S*(?:dap|dns)\\S+",
|
||||
"type": "appFilter"
|
||||
},
|
||||
]
|
||||
}
|
@ -156,4 +156,5 @@ if config.is_waf_on() then
|
||||
lib.cookie_check()
|
||||
lib.post_check()
|
||||
lib.header_check()
|
||||
|
||||
end
|
@ -1,2 +1,64 @@
|
||||
local uuid = require 'resty.uuid'
|
||||
uuid.seed()
|
||||
local utils = require "utils"
|
||||
local config = require "config"
|
||||
|
||||
uuid.seed()
|
||||
|
||||
local update_req_count = function()
|
||||
local req_count = ngx.shared.dict_req_count
|
||||
local req_count_update = req_count:get("req_count") or 0
|
||||
req_count:set("req_count", 0)
|
||||
local count_4xx_update = req_count:get("count_4xx") or 0
|
||||
req_count:set("count_4xx", 0)
|
||||
local count_5xx_update = req_count:get("count_5xx") or 0
|
||||
req_count:set("count_5xx", 0)
|
||||
local attack_count_update = req_count:get("attack_count") or 0
|
||||
req_count:set("attack_count", 0)
|
||||
|
||||
if req_count_update == 0 and count_4xx_update == 0 and count_5xx_update == 0 and attack_count_update == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
local today = ngx.today()
|
||||
local wafdb = utils.get_wafdb(config.waf_db_path)
|
||||
if not wafdb then
|
||||
ngx.log(ngx.ERR, "get log db failed")
|
||||
return
|
||||
end
|
||||
|
||||
wafdb:execute([[BEGIN TRANSACTION]])
|
||||
|
||||
local stmt_exist = wafdb:prepare("SELECT COUNT(*) FROM waf_stat WHERE day = ?")
|
||||
stmt_exist:bind_values(today)
|
||||
stmt_exist:step()
|
||||
local count = stmt_exist:get_uvalues()
|
||||
stmt_exist:finalize()
|
||||
|
||||
local code = 0
|
||||
if count > 0 then
|
||||
local stmt = wafdb:prepare("UPDATE waf_stat SET req_count = req_count + ?, count4xx = count4xx + ?, count5xx = count5xx + ?, attack_count = attack_count + ? WHERE day = ?")
|
||||
stmt:bind_values(req_count_update, count_4xx_update, count_5xx_update, attack_count_update, today)
|
||||
code = stmt:step()
|
||||
stmt:finalize()
|
||||
else
|
||||
local stmt = wafdb:prepare("INSERT INTO waf_stat (day, req_count, count4xx, count5xx, attack_count,create_date) VALUES (?, ?, ?, ?, ?,DATETIME('now'))")
|
||||
stmt:bind_values(today, req_count_update, count_4xx_update, count_5xx_update, attack_count_update)
|
||||
code = stmt:step()
|
||||
stmt:finalize()
|
||||
end
|
||||
|
||||
wafdb:execute([[COMMIT]])
|
||||
|
||||
--local error_msg = wafdb:errmsg()
|
||||
--if error_msg then
|
||||
-- ngx.log(ngx.ERR, "update waf_stat error ", error_msg .. " ")
|
||||
--end
|
||||
end
|
||||
|
||||
if 0 == ngx.worker.id() then
|
||||
local ok, err = ngx.timer.every(2, update_req_count)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, "failed to create the timer: ", err)
|
||||
return
|
||||
end
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user