1
0
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:
zhengkunwang 2024-03-16 22:44:06 +08:00 committed by GitHub
parent 7784ee9575
commit cbfedb5d5e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 179 additions and 85 deletions

View File

@ -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',

View File

@ -2024,7 +2024,7 @@ const message = {
count4xx: '4xx 數量',
count5xx: '5xx 數量',
todayStatus: '今日狀態',
reqMap: '請求地圖30',
reqMap: '攔截地圖30',
resource: '來源',
count: '數量',
hight: '高',

View File

@ -2025,7 +2025,7 @@ const message = {
count4xx: '4xx 数量',
count5xx: '5xx 数量',
todayStatus: '今日状态',
reqMap: '请求地图30',
reqMap: '拦截地图30',
resource: '来源',
count: '数量',
hight: '高',

View File

@ -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",

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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的请求"
}
]

View 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"
}
]
}

View 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"
},
]
}

View File

@ -156,4 +156,5 @@ if config.is_waf_on() then
lib.cookie_check()
lib.post_check()
lib.header_check()
end

View File

@ -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