1 Star 0 Fork 8

pjjg/xwaf

forked from eeenet/xwaf 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
waf.lua 37.49 KB
一键复制 编辑 原始数据 按行查看 历史
akang 提交于 2024-04-15 11:58 +08:00 . create
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998
local rulematch = ngx.re.find
local unescape = ngx.unescape_uri
local config = require("config")
local string = require("string")
local util = require("util")
local _M = {
RULES = {}
}
function _M.load_rules()
--_M.RULES = util.get_rules(config.rule_dir)
--_M.RULES = util.get_rules_json()
ngx.log(ngx.INFO,"load_rules")
util.insert_wafrules_table()
util.load_blackip()
--for k, v in pairs(_M.RULES)
for k, v in pairs(util.RULE_TABLE)
do
ngx.log(ngx.INFO, string.format("%s:load_rule", k))
--for kk, vv in pairs(v)
--do
-- ngx.log(ngx.INFO, string.format("type:%s,index:%s,Rule:%s",k,kk, vv))
--end
end
--return _M.RULES
end
function _M.get_rule(rule_file_name)
--ngx.log(ngx.DEBUG, rule_file_name)
--ngx.log(ngx.DEBUG, util.RULE_TABLE.useragent)
--return _M.RULES[rule_file_name]
return util.RULE_TABLE[rule_file_name]
end
-- exclude
function _M.exclude_action()
ngx.log(ngx.DEBUG,"xwaf_exclude_action")
--ngx.log(ngx.DEBUG,ngx.req.get_method())
--ngx.log(ngx.DEBUG,ngx.var.request_method)
if ngx.var.request_method == "OPTIONS" or ngx.var.request_method == "HEAD" then
return true
end
if ngx.var.uri == "/xf/verify.html" then
ngx.header.content_type = "text/html"
ngx.status = ngx.HTTP_OK
ngx.say(config.verify_html)
ngx.exit(200)
end
if rulematch(ngx.var.uri,"/403.html|/404.html|/499.html|/500.html|/502.html|/503.html|/504.html|/50x.html|/xf/verify.html","joi") then
return true
end
--exclude cookies
--local USER_COOKIE = ngx.var.http_cookie
--if USER_COOKIE ~= nil then
-- if rulematch(USER_COOKIE, "aa=count", "joi") then
-- ngx.log(ngx.DEBUG,"exclude_cookie_aa")
-- return true
-- end
--end
if ngx.var.request_method == "POST" then
--exclude upload file
ngx.req.read_body()
local headers = ngx.req.get_headers()
--ngx.log(ngx.DEBUG,string.sub(headers["content-type"],1,20))
local content_type = headers["content-type"]
if content_type ~= nil and type(content_type) ~= "table" then
if string.sub(content_type, 1, 20) == "multipart/form-data;" then
--ngx.log(ngx.INFO,string.format("xwaf_exclude_uploadfile:%s",string.sub(content_type, 1, 20)))
ngx.log(ngx.INFO,string.format("xwaf_exclude_uploadfile:%s",string.sub(content_type, 1, 20)))
return true
end
end
--exclude resp beyond 5MB
--local hdlength = ngx.req.get_headers()['content-length']
--ngx.log(ngx.DEBUG,ngx.req.get_headers()['content-length'])
--if hdlength ~= nil then
-- if tonumber(hdlength) > 5242880 then
-- return true
-- end
--end
end
end
-- white ip check
function _M.white_ip_check()
ngx.log(ngx.DEBUG,"white_ip_check")
if util.GET("white_ip_check") then
local IP_WHITE_RULE = _M.get_rule('whiteip')
local WHITE_IP = util.get_all_ip()
if IP_WHITE_RULE ~= nil then
for _, rule in pairs(IP_WHITE_RULE) do
--if rule ~= "" and rulematch(string.gsub(WHITE_IP,"[.]","_"), string.gsub(rule,"[.]","_"), "jo") then
if rule ~= "" and rulematch(WHITE_IP, rule, "jo") then
util.log_record('bwlist',WHITE_IP,'WHITE_IP', ngx.var.request_uri, "-", "-")
return true
end
end
end
end
end
-- bad ip check
function _M.bad_ip_check(wafenable)
ngx.log(ngx.DEBUG,"bad_ip_check")
local BAD_IP = util.get_client_ip()
local ret = false
if BAD_IP ~= "" then
local limitbadip = ngx.shared.blackip
local ret,_ = limitbadip:get(BAD_IP)
if ret ~= nil and ret > 0 then
--ret = true
util.log_record('bwlist',BAD_IP,'BAD_IP', ngx.var.request_uri, "-", "-")
if wafenable == "record" then
return true
else
--ngx.exit(403)
util.waf_output()
end
end
end
return ret
end
-- deny blackip in dict
function _M.blackip_v2_check(wafenable)
local riskip_check = util.GET("risk_ip_check")
local blackip_check = util.GET("black_ip_check")
local wafmodel = util.GET("waf_model")
if riskip_check or blackip_check or wafmodel == "deny" then
--if util.GET("black_ip_check") then
ngx.log(ngx.DEBUG,"blackip_v2_check")
local BLACK_IP = util.get_all_ip()
if BLACK_IP ~= "" then
local blackip = ngx.shared.blackip
local biparry = util.split(BLACK_IP,",")
for _, bip in pairs(biparry) do
--ngx.log(ngx.DEBUG,bip)
-- blackip
if blackip_check then
--ip
local ret,_ = blackip:get(bip)
if ret ~= nil and ret > 0 then
local attackType = "BLACK_IP"
util.log_record('bwlist',bip, attackType, ngx.var.request_uri, "-", "-")
if wafenable == "record" then
return true
else
util.waf_output()
end
end
--cip
local cip = util.getcip_ip(bip)
if cip ~= "" then
local retc,_ = blackip:get(cip)
if retc ~= nil and retc == 1 then
util.log_record('bwlist',cip,'BLACK_IP', ngx.var.request_uri, "-", "-")
if wafenable == "record" then
return true
else
util.waf_output()
end
end
end
end
--riskip
if riskip_check then
local ret,_ = blackip:get('risk'..bip)
if ret ~= nil then
local attackType = "RISK_IP_LIMIT"
if ret == "waf" then
attackType = "RISK_IP_WAF"
end
if wafenable == "record" then
util.log_record('bwlist',bip, attackType, ngx.var.request_uri, "-", "-")
return true
else
local riskmodel = util.GET("waf_riskip_model")
--prevent record log repeat
if riskmodel == "deny" then
util.log_record('bwlist',bip, attackType, ngx.var.request_uri, "-", "-")
end
util.waf_risk_output(ret)
end
end
end
--badip
if wafmodel == "deny" then
local ret,_ = blackip:get('bad'..bip)
if ret ~= nil and ret > 0 then
local attackType = "BAD_IP"
util.log_record('bwlist',bip, attackType, ngx.var.request_uri, "-", "-")
if wafenable == "record" then
return true
else
util.waf_output()
end
end
end
end
end
end
end
-- deny riskip in dict
function _M.riskip_check(wafenable)
if util.GET("risk_ip_check") then
ngx.log(ngx.DEBUG,"risk_ip_check")
local BLACK_IP = util.get_all_ip()
local ret = false
if BLACK_IP ~= "" then
local riskip = ngx.shared.riskip
local biparry = util.split(BLACK_IP,",")
for _, bip in pairs(biparry) do
local ret,_ = riskip:get(bip)
if ret ~= nil and ret > 0 then
util.log_record('bwlist',bip,'RISK_IP', ngx.var.request_uri, "-", "-")
if wafenable == "record" then
return true
else
util.waf_risk_output()
end
end
end
end
end
end
-- deny black ip
function _M.black_ip_check(wafenable)
ngx.log(ngx.DEBUG,"black_ip_check")
if util.GET("black_ip_check") then
local IP_BLACK_RULE = _M.get_rule('blackip')
local BLACK_IP = util.get_all_ip()
if IP_BLACK_RULE ~= nil then
for _, rule in pairs(IP_BLACK_RULE) do
if rule ~= "" and rulematch(BLACK_IP, rule, "jo") then
util.log_record('bwlist',BLACK_IP,'BLACK_IP', ngx.var.request_uri, "-", "-")
if wafenable == "record" then
return true
else
--ngx.exit(403)
util.waf_output()
end
end
end
end
end
end
-- url deny check
function _M.url_deny_check(wafenable)
ngx.log(ngx.DEBUG,"waf_urldeny_check")
if util.GET("waf_urldeny_check") then
local xhost = util.get_host()
local REQ_URI = ngx.var.request_uri
if config.urldeny_rule ~= nil then
for _,x in ipairs(config.urldeny_rule) do
--规则启用,对象不为空才往下执行
if x.deny_enable and x.deny_key ~= "" then
if x.deny_host ~= "" then
--域名不为空并匹配时只有指定的URL匹配才行
if xhost == x.deny_host then
local LogT = ""
local Rule_Token = ""
if x.deny_url ~= "/" then
if rulematch(REQ_URI,x.deny_url,"joi") then
if x.deny_type == "referer" then
Rule_Token = util.get_referer()
LogT = "_RF"
elseif x.deny_type == "useragent" then
Rule_Token = util.get_user_agent()
LogT = "_UA"
elseif x.deny_type == "ip" then
Rule_Token = util.get_all_ip()
LogT = "_IP"
end
if rulematch(Rule_Token,x.deny_key,"joi") then
util.log_record('bwlist',x.deny_key,'URL_DENY'..LogT, REQ_URI, "-", "-")
if wafenable == "record" then
return true
else
util.waf_output()
end
end
end
else
--url为空时则该域名下的请求进行匹配
if x.deny_type == "referer" then
Rule_Token = util.get_referer()
LogT = "_RF"
elseif x.deny_type == "useragent" then
Rule_Token = util.get_user_agent()
LogT = "_UA"
elseif x.deny_type == "ip" then
Rule_Token = util.get_all_ip()
LogT = "_IP"
end
if rulematch(Rule_Token,x.deny_key,"joi") then
util.log_record('bwlist',x.deny_key,'URL_DENY'..LogT, REQ_URI, "-", "-")
if wafenable == "record" then
return true
else
util.waf_output()
end
end
end
end
else
--当域名为空时,url也要不能为空,否则是全局配置,全局配置在ua和ip白名单设置
if x.deny_url ~= "/" and rulematch(REQ_URI,x.deny_url,"joi") then
local LogT = ""
local Rule_Token = ""
if x.deny_type == "referer" then
Rule_Token = util.get_referer()
LogT = "_RF"
elseif x.deny_type == "useragent" then
Rule_Token = util.get_user_agent()
LogT = "_UA"
elseif x.deny_type == "ip" then
Rule_Token = util.get_all_ip()
LogT = "_IP"
end
if rulematch(Rule_Token,x.deny_key,"joi") then
util.log_record('bwlist',x.deny_key,'URL_DENY'..LogT, REQ_URI, "-", "-")
if wafenable == "record" then
return true
else
util.waf_output()
end
end
end
end
end
end
end
end
end
-- allow white url
function _M.white_url_check()
ngx.log(ngx.DEBUG,"white_url_check")
if util.GET("white_url_check") then
local URL_WHITE_RULES = _M.get_rule('whiteurl')
if URL_WHITE_RULES ~= nil then
local REQ_URI = ngx.var.request_uri
if URL_WHITE_RULES ~= nil then
for _,rule in pairs(URL_WHITE_RULES) do
if rule ~= "" and rulematch(REQ_URI, rule, "joi") then
util.log_record('bwlist',REQ_URI,'WHITE_URL', ngx.var.request_uri, "-", "-")
return true
end
end
end
end
end
end
-- white ua check
function _M.white_ua_check()
ngx.log(ngx.DEBUG,"white_ua_check")
if util.GET("white_ua_check") then
local UA_WHITE_RULE = _M.get_rule('whiteua')
if UA_WHITE_RULE ~= nil then
local WHITE_UA = util.get_user_agent()
if WHITE_UA ~= "" then
for _, rule in pairs(UA_WHITE_RULE) do
--if rule ~= "" and rulematch(string.gsub(WHITE_UA,"[.]","_"), string.gsub(rule,"[.]","_"), "joi") then
if rule ~= "" and rulematch(WHITE_UA, rule, "joi") then
util.log_record('bwlist',WHITE_UA,'WHITE_UA', ngx.var.request_uri, "-", "-")
return true
end
end
end
end
end
end
-- white referer check
function _M.white_rf_check()
ngx.log(ngx.DEBUG,"white_rf_check")
if util.GET("white_rf_check") then
local RF_WHITE_RULE = _M.get_rule('whiterf')
if RF_WHITE_RULE ~= nil then
local WHITE_RF = util.get_referer()
if WHITE_RF ~= "" then
for _, rule in pairs(RF_WHITE_RULE) do
if rule ~= "" and rulematch(WHITE_RF, rule, "joi") then
util.log_record('bwlist',WHITE_RF,'WHITE_RF', ngx.var.request_uri, "-", "-")
return true
end
end
end
end
end
end
-- deny cookie
function _M.cookie_attack_check(wafenable)
ngx.log(ngx.DEBUG,"cookie_attack_check")
if util.GET("cookie_check") then
local COOKIE_RULES = _M.get_rule('cookie')
if COOKIE_RULES ~= nil then
local USER_COOKIE = ngx.var.http_cookie
if USER_COOKIE ~= nil then
for _, rule in pairs(COOKIE_RULES) do
if rule ~="" and rulematch(USER_COOKIE, rule, "jo") then
util.log_record('waf',USER_COOKIE,'DENY_COOKIE', ngx.var.request_uri, "-", rule)
if wafenable == "on" then
util.waf_output()
end
return true
end
end
end
end
end
return false
end
-- check head length
function _M.request_head_check(wafenable)
ngx.log(ngx.DEBUG,"request_head_check")
local urllength = util.GET("waf_url_length")
if tonumber(urllength) > 0 then
if #(ngx.var.request_uri) > tonumber(urllength) then
util.log_record('waf',post_data,'URL_TooLong', ngx.var.request_uri, "-", rule)
if wafenable == "on" then
util.waf_output()
end
return true
end
end
return false
end
-- deny url
function _M.url_attack_check(wafenable)
ngx.log(ngx.DEBUG,"url_attack_check")
if util.GET("url_check") then
local URL_RULES = _M.get_rule('url')
if URL_RULES ~= nil then
local REQ_URI = ngx.var.request_uri
if URL_RULES ~= nil then
for _,rule in pairs(URL_RULES) do
if rule ~="" and rulematch(REQ_URI,rule,"joi") then
util.log_record('waf',REQ_URI,'DENY_URI', ngx.var.request_uri, "-", rule)
if wafenable == "on" then
util.waf_output()
end
return true
end
end
end
end
end
return false
end
-- deny urlargs
function _M.url_args_attack_check(wafenable)
ngx.log(ngx.DEBUG,"urlargs_attack_check")
if util.GET("url_args_check") then
local ARGS_RULES = _M.get_rule('args')
if ARGS_RULES ~= nil then
for _,rule in pairs(ARGS_RULES) do
local REQ_ARGS = ngx.req.get_uri_args()
for key, val in pairs(REQ_ARGS) do
local ARGS_DATA = {}
if type(val) == 'table' then
if #val > 1 then
ngx.log(ngx.DEBUG,string.format("exception key,key:%s",key))
return true
end
if type(val[1]) == "boolean" then
return true
end
ARGS_DATA = table.concat(val, " ")
else
ARGS_DATA = val
end
--ngx.log(ngx.DEBUG, ARGS_DATA,rule)
if ARGS_DATA and type(ARGS_DATA) ~= "boolean" and rule ~="" and rulematch(unescape(ARGS_DATA), rule, "joi") then
util.log_record('waf',ARGS_DATA,'DENY_ARGS', ngx.var.request_uri, "-", rule)
if wafenable == "on" then
util.waf_output()
end
return true
end
end
end
end
end
return false
end
-- deny useragent
function _M.user_agent_attack_check(wafenable)
ngx.log(ngx.DEBUG,"useragent_attack_check")
if util.GET("user_agent_check") then
local USER_AGENT_RULES = _M.get_rule('useragent')
if USER_AGENT_RULES ~= nil then
local USER_AGENT = util.get_user_agent()
if USER_AGENT ~= "" and USER_AGENT_RULES ~= nil then
for _, rule in pairs(USER_AGENT_RULES) do
if rule ~= "" and rulematch(USER_AGENT, rule, "joi") then
util.log_record('waf',USER_AGENT,'DENY_UA', ngx.var.request_uri, "-", rule)
if wafenable == "on" then
util.waf_output()
end
return true
end
end
end
end
end
return false
end
-- deny referer
function _M.referer_attack_check(wafenable)
ngx.log(ngx.DEBUG,"referer_attack_check")
if util.GET("referer_check") then
local REFERER_RULE = _M.get_rule('referer')
if REFERER_RULE ~= nil then
local referer = util.get_referer()
if referer ~= "" then
for _, rule in pairs(REFERER_RULE) do
if rule ~= "" and rulematch(referer, rule, "joi") then
util.log_record('waf',referer,'DENY_REFERER', ngx.var.request_uri, "-", rule)
if wafenable == "on" then
util.waf_output()
end
return true
end
end
end
end
end
end
-- deny postdata
function _M.post_attack_check(wafenable)
ngx.log(ngx.DEBUG,"post_attack_check")
if util.GET("post_check") then
ngx.req.read_body()
local POST_RULES = _M.get_rule('post')
if POST_RULES ~= nil then
for _, rule in pairs(POST_RULES) do
local POST_ARGS = ngx.req.get_post_args() or {}
for _, v in pairs(POST_ARGS) do
local post_data = ""
if type(v) == "table" then
if type(v[1]) == "boolean" then
return true
end
post_data = table.concat(v, ", ")
else
post_data = v
end
--ngx.log(ngx.DEBUG,tostring(post_data))
if rule ~= "" and rulematch(tostring(post_data), rule, "joi") then
util.log_record('waf',post_data,'DENY_POSTDATA', ngx.var.request_uri, "-", rule)
if wafenable == "on" then
util.waf_output()
end
return true
end
end
end
end
end
return false
end
--limit core func
function limit_core_func(limit_host,limit_type,limit_url,limit_key,limit_speed,rateV,limit_downrate)
local dToken = ""
if limit_host ~= "" then
dToken = "host"..limit_host
end
local urlToken = ""
local logTypePre = ""
if limit_url ~= "" then
urlToken = limit_url
logTypePre = "URL_"
end
if limit_type == "ip" then
local logType = logTypePre.."IP_LIMIT"
ngx.log(ngx.DEBUG,logType)
local IP_TOKEN = util.get_realip()
local AllIp = util.get_all_ip()
local limit_token = dToken..urlToken..IP_TOKEN
local iskeepon = true
if limit_key ~= "" then
if rulematch(AllIp, limit_key, "jo") then
limit_token = dToken..urlToken..limit_type..limit_key
--limit_key不为空并匹配时独立限流,不循环规则
iskeepon = false
else
return iskeepon
end
end
local result = util.Reqlimit(limit_token,logType,rateV,limit_speed,ngx.var.request_uri)
if iskeepon == false then
return false
end
return result
end
if limit_type == "cip" then
local logType = logTypePre.."CIP_LIMIT"
ngx.log(ngx.DEBUG,logType)
local IP_TOKEN = util.getcip_realip()
local AllIp = util.get_all_ip()
local limit_token = dToken..urlToken..IP_TOKEN
local iskeepon = true
if limit_key ~= "" then
if rulematch(AllIp, limit_key, "jo") then
limit_token = dToken..urlToken..limit_type..limit_key
--limit_key不为空并匹配时独立限流,不循环规则
iskeepon = false
else
return iskeepon
end
end
local result = util.Reqlimit(limit_token,logType,rateV,limit_speed,ngx.var.request_uri)
if iskeepon == false then
return false
end
return result
end
if limit_type == "ipuri" then
local logType = logTypePre.."IPURI_LIMIT"
ngx.log(ngx.DEBUG,logType)
local IP_TOKEN = util.get_realip()
if IP_TOKEN ~= "" then
local limit_token = dToken..urlToken..IP_TOKEN..ngx.var.uri
if limit_key ~= "" and rulematch(limit_token, limit_key, "joi") then
limit_token = dToken..urlToken..limit_type..limit_key
end
local result = util.Reqlimit(limit_token,logType,rateV,limit_speed,ngx.var.request_uri)
return result
end
end
if limit_type == "useragent" then
local logType = logTypePre.."UA_LIMIT"
ngx.log(ngx.DEBUG,logType)
local UA_TOKEN = util.get_user_agent()
if UA_TOKEN ~= "" then
local limit_token = dToken..urlToken..UA_TOKEN
local iskeepon = true
if limit_key ~= "" then
if rulematch(UA_TOKEN, limit_key, "joi") then
limit_token = dToken..urlToken..limit_type..limit_key
--limit_key不为空并匹配时独立限流,不循环规则
iskeepon = false
else
return iskeepon
end
end
local result = util.Reqlimit(limit_token,logType,rateV,limit_speed,ngx.var.request_uri)
if iskeepon == false then
return false
end
return result
end
end
if limit_type == "referer" then
local logType = logTypePre.."RF_LIMIT"
ngx.log(ngx.DEBUG,logType)
local RF_TOKEN = util.get_referer()
if RF_TOKEN ~= "" then
local limit_token = dToken..urlToken..RF_TOKEN
local iskeepon = true
if limit_key ~= "" then
if rulematch(RF_TOKEN, limit_key, "joi") then
limit_token = dToken..urlToken..limit_type..limit_key
--limit_key不为空并匹配时独立限流,不循环规则
iskeepon = false
else
return iskeepon
end
end
local result = util.Reqlimit(limit_token,logType,rateV,limit_speed,ngx.var.request_uri)
if iskeepon == false then
return false
end
return result
end
end
if limit_type == "args" then
local logType = logTypePre.."ARGS_LIMIT"
ngx.log(ngx.DEBUG,logType)
local ARGS_TOKEN = ngx.var.args
if ARGS_TOKEN ~= "" and limit_key ~= "" then
limit_token = dToken..urlToken..limit_type..limit_key
if rulematch(ARGS_TOKEN, limit_key, "joi") then
local result = util.Reqlimit(limit_token,logType,rateV,limit_speed,ngx.var.request_uri)
--因为args 的limit_key不为空,所以匹配后独立限流,不循环规则,所以直接返回false
return false
end
end
end
if limit_type == "all" then
local logType = logTypePre.."ALL_LIMIT"
ngx.log(ngx.DEBUG,logType)
local limit_token = dToken..urlToken.."all"
local result = util.Reqlimit(limit_token,logType,rateV,limit_speed,ngx.var.request_uri)
return result
end
end
--limit downrate func
function limit_rate_func(limit_host,limit_type,limit_url,limit_key,limit_downrate,rate_score,last_downrate)
local Rule_Token = ""
if limit_type == "args" then
Rule_Token = ngx.var.args
elseif limit_type == "url" then
Rule_Token = ngx.var.request_uri
elseif limit_type == "useragent" then
Rule_Token = util.get_user_agent()
elseif limit_type == "referer" then
Rule_Token = util.get_referer()
elseif limit_type == "ip" then
Rule_Token = util.get_all_ip()
end
local xscore = 0
--host
local xhost = util.get_host()
if limit_host ~= "" then
if xhost == limit_host then
xscore = xscore + 8
else
return rate_score,last_downrate
end
end
if limit_host == "" then
xscore = xscore + 4
end
--url
if limit_url ~= "/" then
if rulematch(ngx.var.request_uri, limit_url, "joi") then
xscore = xscore + 4
else
return rate_score,last_downrate
end
end
if limit_url == "/" then
xscore = xscore + 2
end
--key
if limit_key ~= "" then
if rulematch(Rule_Token,limit_key,"joi") then
xscore = xscore + 2
else
if limit_type == "all" then
xscore = xscore + 1
else
return rate_score,last_downrate
end
end
end
if limit_key == "" then
xscore = xscore + 1
end
if xscore > 0 and xscore > rate_score then
return xscore, limit_downrate
end
return rate_score,last_downrate
end
--custom_urllimit
function _M.custom_urllimit_check()
ngx.log(ngx.DEBUG,"reqlimit_rule")
if config.reqlimit_rule ~= nil then
--初始化一个速率,当匹配到第一条规则时,重置速率值,往后的匹配到的规则也不再重置该速率
local now_limit_rate = 0
local rate_score = 0
--针对域名进行设置
local xhost = util.get_host()
for _,x in ipairs(config.reqlimit_rule) do
--local rateV = x.limit_rate
--local rateV = tonumber(string.match(x.limit_rate, '(.*)/'))
--local expireT = tonumber(string.match(x.limit_rate, '/(.*)'))
--限制下载速度
if x.limit_enable == "true" and x.limit_downrate > 0 then
rate_score, now_limit_rate = limit_rate_func(x.limit_host,x.limit_type,x.limit_url,x.limit_key,x.limit_downrate,rate_score,now_limit_rate)
end
if x.limit_enable == "true" and x.limit_rate > 0 then
--判断是否继续循环规则
local isKeepOn = true
--有设置域名的情况
if xhost == x.limit_host then
--URL非斜杠时限制
if x.limit_url ~= "/" then
if rulematch(ngx.var.request_uri, x.limit_url, "joi") then
isKeepOn = limit_core_func(x.limit_host,x.limit_type,x.limit_url,x.limit_key,x.limit_speed,x.limit_rate)
end
else
isKeepOn = limit_core_func(x.limit_host,x.limit_type,"",x.limit_key,x.limit_speed,x.limit_rate)
end
--没设置域名的情况,else是将有域名的和没有域名的计数进行排斥统计,避免重复计数
else
--当限流规则的域名为空才走全局已经启用的规则。不为空如果和请求的域名不相等时不需要处理。例如:限流规则里全部设置了域名时,避免不同域名的请求走到全局无域名的逻辑。
if x.limit_host == "" then
if x.limit_url ~= "/" then
if rulematch(ngx.var.request_uri, x.limit_url, "joi") then
isKeepOn = limit_core_func("",x.limit_type,x.limit_url,x.limit_key,x.limit_speed,x.limit_rate)
end
else
isKeepOn = limit_core_func("",x.limit_type,"",x.limit_key,x.limit_speed,x.limit_rate)
end
end
end
if isKeepOn == false then
ngx.log(ngx.DEBUG, string.format("%s:ISKEEPON", isKeepOn))
break
end
end
end
--限制下载速度
if now_limit_rate ~= nil and now_limit_rate > 0 then
ngx.log(ngx.DEBUG, string.format("limit_downrate:%d", now_limit_rate))
ngx.var.limit_rate = string.format("%dk", now_limit_rate)
end
end
return false
end
function _M.waf_check(wafenable)
ngx.log(ngx.DEBUG,"waf_check")
--if wafenable == "on" or wafenable == "record" then
--exclude inranet request
if util.GET("waf_exclude_intranet") then
local REMOTE_ADDR = ngx.var.remote_addr
if rulematch(REMOTE_ADDR,"^192\\.168\\.|^10\\.|^172\\.(16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31)\\.","jo") then
ngx.log(ngx.DEBUG,"waf_exclude_intranet")
return true
end
end
--exclude js css xml
if util.GET("waf_exclude_static_file") then
local REQ_URI = ngx.var.uri
if rulematch(REQ_URI,"\\.(js|ico|css|jpeg|jpg|png|swf|webp|gif|xml|mp4|mp3|m3u8|ts|mjs|ttf|scss)$","joi") then
ngx.log(ngx.DEBUG,"waf_exclude_static")
return true
end
end
if _M.request_head_check(wafenable) then
elseif _M.user_agent_attack_check(wafenable) then
elseif _M.url_attack_check(wafenable) then
elseif _M.cookie_attack_check(wafenable) then
elseif _M.referer_attack_check(wafenable) then
elseif _M.url_args_attack_check(wafenable) then
elseif _M.post_attack_check(wafenable) then
else
return
end
--end
end
-- limit check
function _M.req_limit_check()
ngx.log(ngx.DEBUG,"reqlimit_check")
local limitenable = util.GET("reqlimit_enable")
if limitenable == "on" or limitenable == "record" then
--exclude inranet request
if util.GET("reqlimit_exclude_intranet") then
local REMOTE_ADDR = ngx.var.remote_addr
if rulematch(REMOTE_ADDR,"^192\\.168\\.|^10\\.|^172\\.(16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31)\\.","jo") then
ngx.log(ngx.DEBUG,string.format("reqlimit_exclude_intranet,ip:%s",REMOTE_ADDR))
return true
end
--if rulematch(REMOTE_ADDR,"^100\\.(120|121|123|124|125)\\.","jo") then
if rulematch(REMOTE_ADDR,"^100\\.[6-9][0-9]\\.|^100\\.[1-2][0-9]{2}\\.","jo") then
local xrealIp = util.get_realip()
if rulematch(xrealIp,"^192\\.168\\.|^10\\.|^172\\.(16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31)\\.","jo") then
ngx.log(ngx.DEBUG,string.format("reqlimit_exclude_intranet,ip:%s",xrealIp))
return true
end
end
end
--exclude reqlimit white list
if util.GET("reqlimit_white_enable") then
if config.reqlimit_whitelist ~= nil then
for _,x in ipairs(config.reqlimit_whitelist) do
local Rule_Token = ""
if x.ruletype == "args" then
Rule_Token = ngx.var.args
elseif x.ruletype == "url" then
Rule_Token = ngx.var.request_uri
elseif x.ruletype == "useragent" then
Rule_Token = util.get_user_agent()
elseif x.ruletype == "referer" then
Rule_Token = util.get_referer()
elseif x.ruletype == "ip" then
Rule_Token = util.get_all_ip()
end
if x.enable and rulematch(Rule_Token,x.ruleitem,"joi") then
ngx.log(ngx.DEBUG,"reqlimit_white")
return true
end
end
end
end
--排除子请求。
if util.GET("reqlimit_exclude_subrequest") then
if ngx.is_subrequest then
ngx.log(ngx.DEBUG,"reqlimit_exclude_subrequest")
return true
end
end
--排除内部请求,例如404下一跳等,但对于rewrite break的请求也会忽略。
if util.GET("reqlimit_exclude_internalrequest") then
if ngx.req.is_internal() then
ngx.log(ngx.DEBUG,"reqlimit_exclude_internalrequest")
return true
end
end
--exclude js css xml
if util.GET("reqlimit_exclude_static") then
--local REQ_URI = ngx.var.request_uri
local REQ_URI = ngx.var.uri
if rulematch(REQ_URI,"\\.(js|ico|css|jpeg|jpg|png|swf|webp|gif|xml|mp4|mp3|m3u8|ts|mjs|ttf|scss)$","joi") then
ngx.log(ngx.DEBUG,"reqlimit_exclude_static")
return true
end
end
--exclude cookie
if util.GET("reqlimit_exclude_cookie") then
local USER_COOKIE = ngx.var.http_cookie
if USER_COOKIE ~= nil then
if rulematch(USER_COOKIE, config.exclude_cookie, "joi") then
ngx.log(ngx.DEBUG,"reqlimit_exclude_cookie")
return true
end
end
end
_M.custom_urllimit_check()
else
return false
end
end
-- waf start
function _M.check()
local wafenable = util.GET("waf_enable")
if wafenable ~= "on" and wafenable ~= "record" then
return
end
if _M.exclude_action() then
elseif _M.white_ip_check() then
elseif _M.white_url_check() then
elseif _M.white_ua_check() then
elseif _M.white_rf_check() then
elseif _M.blackip_v2_check(wafenable) then
elseif _M.url_deny_check(wafenable) then
elseif _M.req_limit_check() then
elseif _M.waf_check(wafenable) then
else
return
end
end
return _M
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/pjjg/xwaf.git
git@gitee.com:pjjg/xwaf.git
pjjg
xwaf
xwaf
master

搜索帮助