From 02d0adcaba695a449a5aa3d766496ec524e469c9 Mon Sep 17 00:00:00 2001 From: weakestan <22886548@qq.com> Date: Tue, 7 Aug 2018 08:24:52 +0800 Subject: [PATCH] Update init.lua --- init.lua | 143 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 126 insertions(+), 17 deletions(-) diff --git a/init.lua b/init.lua index 2eb5966..3de5db2 100644 --- a/init.lua +++ b/init.lua @@ -1,19 +1,52 @@ require 'config' local match = string.match -local ngxmatch=ngx.re.match +--ngx_lua如果是0.9.2以上版本,建议正则过滤函数改为ngx.re.find,匹配效率会提高三倍左右。 +--因nginx和lua一起的关系,正则表达式使用\d\w\s会出问题, +--local ngxmatch=ngx.re.match +local ngxmatch=ngx.re.find local unescape=ngx.unescape_uri local get_headers = ngx.req.get_headers local optionIsOn = function (options) return options == "on" and true or false end +loghack=optionIsOn(loghack) +--载入socket.lua用于发送log到独立syslog服务器。 +local logger = require "socket" +if loghack then + + + if not logger.initted() then + local ok, err = logger.init{ + --host = '192.168.0.1', + host = 'logserver.local', + port = 514, + sock_type = "udp", --udp协议 + flush_limit = 1, --立即发送 + --drop_limit = 5678, + pool_size = 100,--连接池大小 + } + if not ok then + ngx.log(ngx.ERR, "failed to initialize the logger: ", + err) + return + end + end +end + + logpath = logdir rulepath = RulePath +logtofile = optionIsOn(logtofile) +logtoserver = optionIsOn(logtoserver) UrlDeny = optionIsOn(UrlDeny) PostCheck = optionIsOn(postMatch) CookieCheck = optionIsOn(cookieMatch) WhiteCheck = optionIsOn(whiteModule) PathInfoFix = optionIsOn(PathInfoFix) attacklog = optionIsOn(attacklog) +hackipdeny = optionIsOn(hackipdeny) CCDeny = optionIsOn(CCDeny) Redirect=optionIsOn(Redirect) +local file = io.open('config') + function getClientIp() IP = ngx.var.remote_addr if IP == nil then @@ -28,19 +61,38 @@ function write(logfile,msg) fd:flush() fd:close() end + +function swrite(msg) + --保存警告等级要高于nginx error_log的默认等级。 + ngx.log(ngx.CRIT,msg) + + + +end + function log(method,url,data,ruletag) if attacklog then local realIp = getClientIp() local ua = ngx.var.http_user_agent - local servername=ngx.var.server_name - local time=ngx.localtime() - if ua then - line = realIp.." ["..time.."] \""..method.." "..servername..url.."\" \""..data.."\" \""..ua.."\" \""..ruletag.."\"\n" - else - line = realIp.." ["..time.."] \""..method.." "..servername..url.."\" \""..data.."\" - \""..ruletag.."\"\n" + if ua == nil then + ua="null" end + local servername=ngx.var.host + local time=ngx.localtime() + if logtofile then local filename = logpath..'/'..servername.."_"..ngx.today().."_sec.log" + line=realIp.." ["..time.."]".."\""..method.." "..servername..url.."\""..data.."\""..ua.."\""..ruletag.."\"".."\n" write(filename,line) + end + if logtoserver then + line=realIp.."\""..method.." "..servername..url.."\""..data.."\""..ua.."\""..ruletag.."\"" + --line="lua_waf:"..line + swrite(line) + end + --发送ip到独立syslog服务器。 + if loghack then local bytes, err = logger.log(getClientIp()) end + --只要log记录,说明被攻击,利用denyhackip将ip记录。 + if hackipdeny then denyhackip(0) end end end ------------------------------------规则读取函数------------------------------------------------------------------- @@ -78,21 +130,35 @@ function whiteurl() if WhiteCheck then if wturlrules ~=nil then for _,rule in pairs(wturlrules) do - if ngxmatch(ngx.var.uri,rule,"isjo") then + --针对site:开始的进行域名匹配。增加白名单用处。 + local sitemod,_=string.find(rule,"site:") + if sitemod==1 then + rule=string.gsub(rule,"site:","",1) + --调试whiteurl + --if ngx.var.host=='domino.cqhrss.gov.cn' then + -- log('debug',ngx.var.uri,"",rule) + --end + if ngxmatch(ngx.var.host..ngx.var.uri,rule,"isjo") then return true - end + end + else + if ngxmatch(ngx.var.uri,rule,"isjo") then + return true + end + end end end end return false end + function fileExtCheck(ext) local items = Set(black_fileExt) ext=string.lower(ext) if ext then - for rule in pairs(items) do - if ngx.re.match(ext,rule,"isjo") then - log('POST',ngx.var.request_uri,"-","file attack with ext "..ext) + for rule,_ in pairs(items) do + if ngxmatch(ext,rule,"isjo") then + log('POST',ngx.var.request_uri,"-","file attack with ext "..ext) say_html() end end @@ -184,17 +250,25 @@ end function denycc() if CCDeny then local uri=ngx.var.uri - CCcount=tonumber(string.match(CCrate,'(.*)/')) - CCseconds=tonumber(string.match(CCrate,'/(.*)')) + local m, err = ngx.re.match(CCrate,'([0-9]+)/([0-9]+)/([0-9]+)') + local CCcount=tonumber(m[1]) --计数器上限 + local CCseconds=tonumber(m[2]) --计时器 + local CClimits=tonumber(m[3]) --阻止访问时间 local token = getClientIp()..uri local limit = ngx.shared.limit - local req,_=limit:get(token) + local req,_=limit:get(token) --计数器当前值 + if req then if req > CCcount then - ngx.exit(503) + ngx.exit(404) return true else - limit:incr(token,1) + if req == CCcount then limit:set(token,CCcount+1,CClimits) end + + limit:incr(token,1) + --调试在syslog日志中查看 + --swrite('计数器:'..token..'当前计数器'..req..'阻止访问时间:'..CClimits) + end else limit:set(token,1,CCseconds) @@ -203,6 +277,41 @@ function denycc() return false end +--chk为1表示检测值,不增加,不创建,返回检测结果。 +function denyhackip(chk) + if hackipdeny then + + local m, err = ngx.re.match(hackrate,'([0-9]+)/([0-9]+)/([0-9]+)') + local hicount=tonumber(m[1]) --计数器上限 + local hiseconds=tonumber(m[2]) --计时器 + local hilimits=tonumber(m[3]) --阻止访问时间 + local token = "hackip"..getClientIp() + local limit = ngx.shared.limit + local req,_=limit:get(token) --计数器当前值 + if req then + if req > hicount then + ngx.exit(404) + return true + else + + if req == hicount then + limit:set(token,hicount+1,hilimits) + swrite("ip:"..getClientIp().."因攻击被暂停访问"..hilimits.."秒。") + end + if chk ~=1 then limit:incr(token,1) end + --调试在syslog日志中查看 + --swrite("计数器:"..token.."检测状态:"..chk.."当前计数器"..req.."阻止访问时间:"..hilimits) + + + end + else + if chk ~=1 then limit:set(token,1,hiseconds) end + + end + end + return false +end + function get_boundary() local header = get_headers()["content-type"] if not header then