From ebdc61f8428f9b15f57ab2badac8cb7aa8d9402e Mon Sep 17 00:00:00 2001 From: WenJun Date: Wed, 24 Sep 2014 13:40:25 +0800 Subject: [PATCH 01/19] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E9=BB=91=E5=90=8D=E5=8D=95=E5=92=8C=E8=AE=B0=E5=BD=95=E8=9C=98?= =?UTF-8?q?=E8=9B=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.lua | 7 +++++-- guard.lua | 26 ++++++++++++++++++++++++++ init.lua | 2 ++ runtime.lua | 9 +++++++++ url-protect/black_ip_list.txt | 0 url-protect/white_ip_list.txt | 15 +++++++++++++++ 6 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 url-protect/black_ip_list.txt diff --git a/config.lua b/config.lua index 79487be..1d6eb96 100644 --- a/config.lua +++ b/config.lua @@ -66,7 +66,7 @@ local Config = { whiteTime = 600, -- 用于生成token密码的key过期时间 - keyExpire = 600, + keyExpire = 0, -- 匹配url模式,可选值requestUri,uri -- 值requestUri时,url-protect目录下的正则匹配的是浏览器最初请求的地址且没有被decode,带参数的链接 @@ -80,7 +80,10 @@ local Config = { reCaptchaPage = baseDir.."html/reCatchaPage.html", -- 白名单ip文件,文件内容为正则表达式。 - whiteIpModules = { state = "Off", ipList = baseDir.."url-protect/white_ip_list.txt" }, + whiteIpModules = { state = "On", ipList = baseDir.."url-protect/white_ip_list.txt" }, + + -- 黑名单ip文件,文件内容为正则表达式。 + blackIpModules = { state = "On", ipList = baseDir.."url-protect/black_ip_list.txt" }, -- 如果需要从请求头获取真实ip,此值就需要设置,如x-forwarded-for -- 当state为on时,此设置才有效 diff --git a/guard.lua b/guard.lua index 7efc2b9..b8265bb 100644 --- a/guard.lua +++ b/guard.lua @@ -49,6 +49,32 @@ function Guard:ipInWhiteList(ip) end end +function Guard:ipInFileBlackList(ip) + if _Conf.fileBlackIpModulesIsOn then + self:debug("[IpInFileBlackList] fileBlackIpModules is on.",ip,"") + + if ngx.re.match(ip, _Conf.fileBlackIpList) then --匹配黑名单列表 + self:debug("[ipInFileBlackList] ip "..ip.. " match black list ".._Conf.fileBlackIpList,ip,"") + return true + else + return false + end + end +end + + +--收集不在白名单中的蜘蛛ip +function Guard:collectSpiderIp(ip, headers) + spiderPattern = "baiduspider|360spider|sogou web spider|sogou inst spider|mediapartners|adsbot-google|googlebot" + userAgent = string.lower(headers["user-agent"]) + if ngx.re.match(userAgent, spiderPattern) then + local filename = _Conf.logPath.."/spider_ip.log" + local file = io.open(filename, "a+") + file:write(os.date('%Y-%m-%d %H:%M:%S').." IP "..ip.." UA "..userAgent.."\n") + file:close() + end +end + --黑名单模块 function Guard:blackListModules(ip,reqUri) local blackKey = ip.."black" diff --git a/init.lua b/init.lua index 477c5c0..4f13cf2 100644 --- a/init.lua +++ b/init.lua @@ -139,6 +139,7 @@ _Conf = { --解析开关设置 limitReqModulesIsOn = optionIsOn(Config.limitReqModules.state), whiteIpModulesIsOn = optionIsOn(Config.whiteIpModules.state), + fileBlackIpModulesIsOn = optionIsOn(Config.blackIpModules.state) realIpFromHeaderIsOn = optionIsOn(Config.realIpFromHeader.state), autoEnableIsOn = optionIsOn(Config.autoEnable.state), redirectModulesIsOn = optionIsOn(Config.redirectModules.state), @@ -151,6 +152,7 @@ _Conf = { limitUrlProtect = parseRuleFile(Config.limitReqModules.urlProtect), cookieUrlProtect = parseRuleFile(Config.cookieModules.urlProtect), whiteIpList = parseRuleFile(Config.whiteIpModules.ipList), + fileBlackIpList = parseRuleFile(Config.blackIpModules.ipList), --读取文件到内存 captchaPage = readFile2Mem(Config.captchaPage), diff --git a/runtime.lua b/runtime.lua index aa1d3df..dc157d2 100644 --- a/runtime.lua +++ b/runtime.lua @@ -28,9 +28,18 @@ else if _Conf.autoEnableIsOn then ngx.timer.at(0,Guard.autoSwitch) end + + --永久黑名单 + if Guard:ipInFileBlackList(ip) then + ngx.exit(404) + end + --白名单模块 if not Guard:ipInWhiteList(ip) then + --收集不在白名单库里面的蜘蛛 + Guard:collectSpiderIp(ip, headers) + --黑名单模块 Guard:blackListModules(ip,reqUri) diff --git a/url-protect/black_ip_list.txt b/url-protect/black_ip_list.txt new file mode 100644 index 0000000..e69de29 diff --git a/url-protect/white_ip_list.txt b/url-protect/white_ip_list.txt index e69de29..c19d3ad 100644 --- a/url-protect/white_ip_list.txt +++ b/url-protect/white_ip_list.txt @@ -0,0 +1,15 @@ +61.135.186.* +61.155.149.* +61.182.137.* +117.27.149.* +117.34.28.* +119.188.132.* +119.188.14.* +119.63.193.* +123.125.71.* +180.76.5.* +180.76.6.* +183.60.235.* +185.10.104.* +220.181.108.* +222.216.190.* \ No newline at end of file From 58942386505b274f5f928da3b96058abc88bd17c Mon Sep 17 00:00:00 2001 From: WenJun Date: Wed, 24 Sep 2014 15:04:34 +0800 Subject: [PATCH 02/19] ... --- config.lua | 4 ++-- url-protect/limit.txt | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/config.lua b/config.lua index 1d6eb96..1b37c03 100644 --- a/config.lua +++ b/config.lua @@ -9,7 +9,7 @@ local Config = { -- state : 为此模块的状态,表示开启或关闭,可选值为On或Off; -- maxReqs,amongTime : 在amongTime秒内允许请求的最大次数maxReqs,如默认的是在10s内最大允许请求50次。 -- urlProtect : 指定限制请求次数的url正则表达式文件,默认值为\.php$,表示只限制php的请求(当然,当urlMatchMode = "uri"时,此正则才能起作用) - limitReqModules = { state = "On" , maxReqs = 50 , amongTime = 10, urlProtect = baseDir.."url-protect/limit.txt" }, + limitReqModules = { state = "On" , maxReqs = 5 , amongTime = 86400, urlProtect = baseDir.."url-protect/limit.txt" }, -- 主动防御,302响应头跳转模块。利用cc控制端不支持解析响应头的特点,来识别是否为正常用户,当有必要时才建议开启。 @@ -60,7 +60,7 @@ local Config = { sudoPass = '', -- 表示http-guard封锁ip的时间 - blockTime = 600, + blockTime = 86400, -- JsJumpModules redirectModules cookieModules验证通过后,ip在白名单的时间 whiteTime = 600, diff --git a/url-protect/limit.txt b/url-protect/limit.txt index c317c7e..8cf991b 100644 --- a/url-protect/limit.txt +++ b/url-protect/limit.txt @@ -1 +1,2 @@ -\.php$ \ No newline at end of file +\.php$ +\.html$ \ No newline at end of file From 6aabec92740174df2292fd5810377f7eef539a10 Mon Sep 17 00:00:00 2001 From: WenJun Date: Wed, 24 Sep 2014 15:07:24 +0800 Subject: [PATCH 03/19] fix bug --- init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/init.lua b/init.lua index 4f13cf2..5411438 100644 --- a/init.lua +++ b/init.lua @@ -139,7 +139,7 @@ _Conf = { --解析开关设置 limitReqModulesIsOn = optionIsOn(Config.limitReqModules.state), whiteIpModulesIsOn = optionIsOn(Config.whiteIpModules.state), - fileBlackIpModulesIsOn = optionIsOn(Config.blackIpModules.state) + fileBlackIpModulesIsOn = optionIsOn(Config.blackIpModules.state), realIpFromHeaderIsOn = optionIsOn(Config.realIpFromHeader.state), autoEnableIsOn = optionIsOn(Config.autoEnable.state), redirectModulesIsOn = optionIsOn(Config.redirectModules.state), From 50f80a7765814d91a347af9e381990f244a5541a Mon Sep 17 00:00:00 2001 From: WenJun Date: Wed, 24 Sep 2014 15:09:06 +0800 Subject: [PATCH 04/19] update config --- config.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.lua b/config.lua index 1b37c03..0adc274 100644 --- a/config.lua +++ b/config.lua @@ -1,5 +1,5 @@ -- http-guard安装目录,修改为实际安装到的目录。 -baseDir = '/data/www/waf/' +baseDir = '/home/http-guard/' local Config = { -- key是否动态生成,可选static,dynamic,如果选dynamic,下面所有的keySecret不需要更改,如果选static,修改手动修改下面的keySecret From e068c41190d34c6012c694d48fa6631defc2b61f Mon Sep 17 00:00:00 2001 From: WenJun Date: Wed, 24 Sep 2014 15:25:21 +0800 Subject: [PATCH 05/19] fix bug --- captcha/getImg.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/captcha/getImg.php b/captcha/getImg.php index c976054..0daa5af 100644 --- a/captcha/getImg.php +++ b/captcha/getImg.php @@ -10,7 +10,7 @@ function getAuthImage($text) { $buttum_c = ImageColorAllocate($im,$tmpC0,$tmpC1,$tmpC2); imagefill($im, 16, 13, $buttum_c); - $font = '/data/www/waf/captcha/t1.ttf'; + $font = __DIR__ . '/t1.ttf'; for ($i=0;$i Date: Wed, 24 Sep 2014 15:37:13 +0800 Subject: [PATCH 06/19] update config --- config.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.lua b/config.lua index 0adc274..65744e6 100644 --- a/config.lua +++ b/config.lua @@ -83,7 +83,7 @@ local Config = { whiteIpModules = { state = "On", ipList = baseDir.."url-protect/white_ip_list.txt" }, -- 黑名单ip文件,文件内容为正则表达式。 - blackIpModules = { state = "On", ipList = baseDir.."url-protect/black_ip_list.txt" }, + blackIpModules = { state = "Off", ipList = baseDir.."url-protect/black_ip_list.txt" }, -- 如果需要从请求头获取真实ip,此值就需要设置,如x-forwarded-for -- 当state为on时,此设置才有效 From 76e7dd1c448eb256ad16356a21cd332624ca44b2 Mon Sep 17 00:00:00 2001 From: WenJun Date: Wed, 24 Sep 2014 16:43:42 +0800 Subject: [PATCH 07/19] =?UTF-8?q?=E8=AE=B0=E5=BD=95=E6=80=BB=E8=AE=BF?= =?UTF-8?q?=E9=97=AE=E5=A4=A7=E4=BA=8E20=E7=9A=84IP?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- guard.lua | 8 ++++++++ runtime.lua | 1 - url-protect/limit.txt | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/guard.lua b/guard.lua index b8265bb..dcdb61e 100644 --- a/guard.lua +++ b/guard.lua @@ -108,6 +108,14 @@ function Guard:limitReqModules(ip,reqUri,address) self:debug("[limitReqModules] ip "..ip.. " request exceed ".._Conf.limitReqModules.maxReqs,ip,reqUri) _Conf.dict:set(blackKey,0,_Conf.blockTime) --添加此ip到黑名单 self:log("[limitReqModules] IP "..ip.." visit "..newReqTimes.." times,block it.") + + --大于20次的特别记录下来 + if newReqTimes > 20 then + local filename = _Conf.logPath.."/large_flow.log" + local file = io.open(filename, "a+") + file:write(os.date('%Y-%m-%d %H:%M:%S').." IP "..ip.."\n") + file:close() + end end end diff --git a/runtime.lua b/runtime.lua index dc157d2..f9a38cd 100644 --- a/runtime.lua +++ b/runtime.lua @@ -34,7 +34,6 @@ else ngx.exit(404) end - --白名单模块 if not Guard:ipInWhiteList(ip) then --收集不在白名单库里面的蜘蛛 diff --git a/url-protect/limit.txt b/url-protect/limit.txt index 8cf991b..49902fd 100644 --- a/url-protect/limit.txt +++ b/url-protect/limit.txt @@ -1,2 +1,3 @@ \.php$ +\.html$ \.html$ \ No newline at end of file From 8f0c20a8dfb22163e4d9476b7d654f3a4c8632ab Mon Sep 17 00:00:00 2001 From: WenJun Date: Wed, 24 Sep 2014 23:12:14 +0800 Subject: [PATCH 08/19] =?UTF-8?q?=E5=AE=8C=E6=88=90=E4=B8=93=E9=97=A8?= =?UTF-8?q?=E9=92=88=E5=AF=B9=E7=81=AB=E8=BD=A6=E5=A4=B4=E7=9A=84=E5=8D=95?= =?UTF-8?q?UA=E7=9A=84=E6=8B=A6=E6=88=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.lua | 5 +++ guard.lua | 60 ++++++++++++++++++++++++++++++++--- init.lua | 2 ++ runtime.lua | 10 ++++-- url-protect/white_ip_list.txt | 3 +- 5 files changed, 71 insertions(+), 9 deletions(-) diff --git a/config.lua b/config.lua index 65744e6..6c5e0ff 100644 --- a/config.lua +++ b/config.lua @@ -5,6 +5,11 @@ local Config = { -- key是否动态生成,可选static,dynamic,如果选dynamic,下面所有的keySecret不需要更改,如果选static,修改手动修改下面的keySecret keyDefine = "dynamic", + -- 被动防御,限制UA请求模块。根据在一定时间内统计到的单个UA请求次数作限制(专门针对火车头采集工具) + -- state : 为此模块的状态,表示开启或关闭,可选值为On或Off; + -- maxReqs,amongTime : 在amongTime秒内允许请求的最大次数maxReqs,如默认的是在10s内最大允许请求50次。 + limitUaModules = { state = "On" , maxReqs = 5 , amongTime = 5}, + -- 被动防御,限制请求模块。根据在一定时间内统计到的请求次数作限制,建议始终开启 -- state : 为此模块的状态,表示开启或关闭,可选值为On或Off; -- maxReqs,amongTime : 在amongTime秒内允许请求的最大次数maxReqs,如默认的是在10s内最大允许请求50次。 diff --git a/guard.lua b/guard.lua index dcdb61e..ca778be 100644 --- a/guard.lua +++ b/guard.lua @@ -65,8 +65,8 @@ end --收集不在白名单中的蜘蛛ip function Guard:collectSpiderIp(ip, headers) - spiderPattern = "baiduspider|360spider|sogou web spider|sogou inst spider|mediapartners|adsbot-google|googlebot" - userAgent = string.lower(headers["user-agent"]) + local spiderPattern = "baiduspider|360spider|sogou web spider|sogou inst spider|mediapartners|adsbot-google|googlebot" + local userAgent = string.lower(headers["user-agent"]) if ngx.re.match(userAgent, spiderPattern) then local filename = _Conf.logPath.."/spider_ip.log" local file = io.open(filename, "a+") @@ -76,15 +76,65 @@ function Guard:collectSpiderIp(ip, headers) end --黑名单模块 -function Guard:blackListModules(ip,reqUri) +function Guard:blackListModules(ip, reqUri, headers) local blackKey = ip.."black" if _Conf.dict:get(blackKey) then --判断ip是否存在黑名单字典 self:debug("[blackListModules] ip "..ip.." in blacklist",ip,reqUri) self:takeAction(ip,reqUri) --存在则执行相应动作 - end + end + + if _Conf.limitUaModulesIsOn then + local userAgent = headers["user-agent"] + --不存在UA直接抛验证码 + if not userAgent then + self:debug("[limitUaModules] ip "..ip.." not have ua", ip, reqUri) + self:takeAction(ip,reqUri) --存在则执行相应动作 + end + + local blackUaKey = uaMd5 .. 'BlackUAKey' + if _Conf.dict:get(blackUaKey) then --判断ua是否存在黑名单字典 + self:debug("[blackListModules] ip "..ip.." in ua blacklist".." "..userAgent, ip, reqUri) + self:takeAction(ip,reqUri) --存在则执行相应动作 + end + end end ---限制请求速率模块 +--限制UA请求速率模块 +function Guard:limitUaModules(ip, reqUri, address, headers) + local userAgent = headers["user-agent"] + --不存在UA直接抛验证码 + if not userAgent then + self:debug("[limitUaModules] ip "..ip.." not have ua", ip, reqUri) + self:takeAction(ip,reqUri) --存在则执行相应动作 + end + + local uaMd5 = ngx.md5(userAgent) + local blackUaKey = uaMd5 .. 'BlackUAKey' + local limitUaKey = uaMd5 .. 'LimitUaKey' + local uaTimes = _Conf.dict:get(limitUaKey) --获取此ua请求的次数 + + --增加一次请求记录 + if uaTimes then + _Conf.dict:incr(limitUaKey, 1) + else + _Conf.dict:set(limitUaKey, 1, _Conf.limitUaModules.amongTime) + uaTimes = 0 + end + + local newUaTimes = uaTimes + 1 + self:debug("[limitUaModules] newUaTimes " .. newUaTimes .. " " .. userAgent, ip, reqUri) + + --判断请求数是否大于阀值,大于则添加黑名单 + if newUaTimes > _Conf.limitUaModules.maxReqs then --判断是否请求数大于阀值 + self:debug("[limitUaModules] ip "..ip.. " request exceed ".._Conf.limitUaModules.maxReqs.." "..userAgent, ip, reqUri) + _Conf.dict:set(blackUaKey, 0, _Conf.blockTime) --添加此ip到黑名单 + self:log("[limitUaModules] IP "..ip.." visit "..newReqTimes.." times,block it. "..userAgent) + end + +end + + +--限制IP请求速率模块 function Guard:limitReqModules(ip,reqUri,address) if ngx.re.match(address,_Conf.limitUrlProtect,"i") then self:debug("[limitReqModules] address "..address.." match reg ".._Conf.limitUrlProtect,ip,reqUri) diff --git a/init.lua b/init.lua index 5411438..3b992af 100644 --- a/init.lua +++ b/init.lua @@ -121,6 +121,7 @@ end _Conf = { --引入原始设置 + limitUaModules = Config.limitUaModules, limitReqModules = Config.limitReqModules, redirectModules = Config.redirectModules, JsJumpModules = Config.JsJumpModules, @@ -137,6 +138,7 @@ _Conf = { captchaKey = Config.captchaKey, --解析开关设置 + limitUaModulesIsOn = optionIsOn(Config.limitUaModules.state), limitReqModulesIsOn = optionIsOn(Config.limitReqModules.state), whiteIpModulesIsOn = optionIsOn(Config.whiteIpModules.state), fileBlackIpModulesIsOn = optionIsOn(Config.blackIpModules.state), diff --git a/runtime.lua b/runtime.lua index f9a38cd..c664041 100644 --- a/runtime.lua +++ b/runtime.lua @@ -40,9 +40,15 @@ else Guard:collectSpiderIp(ip, headers) --黑名单模块 - Guard:blackListModules(ip,reqUri) + Guard:blackListModules(ip, reqUri, headers) - --限制请求速率模块 + --限制UA请求速率模块 + if _Conf.limitUaModulesIsOn then + Guard:debug("[limitUaModules] limitUaModules is on.",ip,reqUri) + Guard:limitUaModules(ip, reqUri, address, headers) + end + + --限制IP请求速率模块 if _Conf.limitReqModulesIsOn then --limitReq模块是否开启 Guard:debug("[limitReqModules] limitReqModules is on.",ip,reqUri) Guard:limitReqModules(ip,reqUri,address) diff --git a/url-protect/white_ip_list.txt b/url-protect/white_ip_list.txt index c19d3ad..e27eed5 100644 --- a/url-protect/white_ip_list.txt +++ b/url-protect/white_ip_list.txt @@ -2,7 +2,7 @@ 61.155.149.* 61.182.137.* 117.27.149.* -117.34.28.* +117.34.28.1.* 119.188.132.* 119.188.14.* 119.63.193.* @@ -10,6 +10,5 @@ 180.76.5.* 180.76.6.* 183.60.235.* -185.10.104.* 220.181.108.* 222.216.190.* \ No newline at end of file From 04dc987d3ed9c443c581a57deb16663c1de56597 Mon Sep 17 00:00:00 2001 From: WenJun Date: Wed, 24 Sep 2014 23:26:37 +0800 Subject: [PATCH 09/19] fix bug --- guard.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/guard.lua b/guard.lua index ca778be..f0e8706 100644 --- a/guard.lua +++ b/guard.lua @@ -90,7 +90,8 @@ function Guard:blackListModules(ip, reqUri, headers) self:debug("[limitUaModules] ip "..ip.." not have ua", ip, reqUri) self:takeAction(ip,reqUri) --存在则执行相应动作 end - + + local uaMd5 = ngx.md5(userAgent) local blackUaKey = uaMd5 .. 'BlackUAKey' if _Conf.dict:get(blackUaKey) then --判断ua是否存在黑名单字典 self:debug("[blackListModules] ip "..ip.." in ua blacklist".." "..userAgent, ip, reqUri) From e495e5f84232ed984c3cc0b375ab40178f0fdff9 Mon Sep 17 00:00:00 2001 From: WenJun Date: Wed, 24 Sep 2014 23:28:23 +0800 Subject: [PATCH 10/19] fix bug --- guard.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guard.lua b/guard.lua index f0e8706..b0078e7 100644 --- a/guard.lua +++ b/guard.lua @@ -129,7 +129,7 @@ function Guard:limitUaModules(ip, reqUri, address, headers) if newUaTimes > _Conf.limitUaModules.maxReqs then --判断是否请求数大于阀值 self:debug("[limitUaModules] ip "..ip.. " request exceed ".._Conf.limitUaModules.maxReqs.." "..userAgent, ip, reqUri) _Conf.dict:set(blackUaKey, 0, _Conf.blockTime) --添加此ip到黑名单 - self:log("[limitUaModules] IP "..ip.." visit "..newReqTimes.." times,block it. "..userAgent) + self:log("[limitUaModules] IP "..ip.." visit "..newUaTimes.." times,block it. "..userAgent) end end From a4b996c77714124b54d1fd25a6a28aae40a0917a Mon Sep 17 00:00:00 2001 From: WenJun Date: Wed, 24 Sep 2014 23:28:46 +0800 Subject: [PATCH 11/19] no message --- url-protect/limit.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/url-protect/limit.txt b/url-protect/limit.txt index 49902fd..2a9e9d0 100644 --- a/url-protect/limit.txt +++ b/url-protect/limit.txt @@ -1,3 +1,3 @@ \.php$ \.html$ -\.html$ \ No newline at end of file +\.png$ \ No newline at end of file From 8f8d5207475eec3e897c8f0e17b91d85225dc9b7 Mon Sep 17 00:00:00 2001 From: WenJun Date: Wed, 24 Sep 2014 23:37:57 +0800 Subject: [PATCH 12/19] =?UTF-8?q?=E5=BC=80=E5=90=AFdebug=EF=BC=8C=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E9=80=9A=E8=BF=87=E4=BA=8B=E5=90=8E=E5=88=A0=E9=99=A4?= =?UTF-8?q?UA=E8=AE=BF=E9=97=AE=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.lua | 4 ++-- guard.lua | 21 ++++++++++++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/config.lua b/config.lua index 6c5e0ff..692f31d 100644 --- a/config.lua +++ b/config.lua @@ -8,7 +8,7 @@ local Config = { -- 被动防御,限制UA请求模块。根据在一定时间内统计到的单个UA请求次数作限制(专门针对火车头采集工具) -- state : 为此模块的状态,表示开启或关闭,可选值为On或Off; -- maxReqs,amongTime : 在amongTime秒内允许请求的最大次数maxReqs,如默认的是在10s内最大允许请求50次。 - limitUaModules = { state = "On" , maxReqs = 5 , amongTime = 5}, + limitUaModules = { state = "On" , maxReqs = 5 , amongTime = 300}, -- 被动防御,限制请求模块。根据在一定时间内统计到的请求次数作限制,建议始终开启 -- state : 为此模块的状态,表示开启或关闭,可选值为On或Off; @@ -98,7 +98,7 @@ local Config = { captchaDir = baseDir.."captcha/", -- 是否开启debug日志 - debug = false, + debug = true, --日志目录,一般不需要修改.但需要设置logs所有者为nginx运行用户,如nginx运行用户为www,则命令为chown www logs logPath = baseDir.."logs/", diff --git a/guard.lua b/guard.lua index b0078e7..3e036dd 100644 --- a/guard.lua +++ b/guard.lua @@ -90,7 +90,7 @@ function Guard:blackListModules(ip, reqUri, headers) self:debug("[limitUaModules] ip "..ip.." not have ua", ip, reqUri) self:takeAction(ip,reqUri) --存在则执行相应动作 end - + local uaMd5 = ngx.md5(userAgent) local blackUaKey = uaMd5 .. 'BlackUAKey' if _Conf.dict:get(blackUaKey) then --判断ua是否存在黑名单字典 @@ -619,8 +619,27 @@ function Guard:verifyCaptcha(ip) local captchaValue = _Conf.dict_captcha:get(captchaNum) --从字典获取post value对应的验证码值 if captchaValue == postValue then --比较验证码是否相等 self:debug("[verifyCaptcha] captcha is valid.delete from blacklist",ip,"") + _Conf.dict:delete(ip.."black") --从黑名单删除 _Conf.dict:delete(ip.."limitreqkey") --访问记录删除 + + if _Conf.limitUaModulesIsOn then + local headers = ngx.req.get_headers() + local userAgent = headers["user-agent"] + --不存在UA直接抛验证码 + if not userAgent then + self:debug("[limitUaModules] ip "..ip.." not have ua", ip, reqUri) + self:takeAction(ip,reqUri) --存在则执行相应动作 + end + + local uaMd5 = ngx.md5(userAgent) + local blackUaKey = uaMd5 .. 'BlackUAKey' + local limitUaKey = uaMd5 .. 'LimitUaKey' + + _Conf.dict:delete(blackUaKey) --从黑名单删除 + _Conf.dict:delete(limitUaKey) --访问记录删除 + end + local expire = ngx.time() + _Conf.keyExpire local captchaKey = ngx.md5(table.concat({ip,_Conf.captchaKey,expire})) local captchaKey = string.sub(captchaKey,"1","10") From 8b50cfbe78c388fd4aec2b760563cabc72e91342 Mon Sep 17 00:00:00 2001 From: WenJun Date: Thu, 25 Sep 2014 10:20:36 +0800 Subject: [PATCH 13/19] update config --- html/captcha.html | 180 ++++++++++++++++-- html/captcha.old.html | 24 +++ ...eCatchaPage.html => reCatchaPage.old.html} | 0 logs/foo | 0 4 files changed, 184 insertions(+), 20 deletions(-) create mode 100644 html/captcha.old.html rename html/{reCatchaPage.html => reCatchaPage.old.html} (100%) delete mode 100644 logs/foo diff --git a/html/captcha.html b/html/captcha.html index 9124bf2..ea255de 100644 --- a/html/captcha.html +++ b/html/captcha.html @@ -1,24 +1,164 @@ + - - - 请输入验证码 - - - -
-

很抱歉...

-

您的查询看起来类似于来自计算机软件的自动请求。为了保护我们的用户,请原谅我们现在暂时不能处理您的请求。

-

要继续访问网页,请输入下面所示字符:

-
- Captcha image + + + + 请输入验证码 + + + +
+
+
+

很抱歉...

+

您的查询看起来类似于来自计算机软件的自动请求。

+

为了保护我们的用户,请原谅我们现在暂时不能处理您的请求。

+

要继续访问网页,请输入下面所示字符:

+ +
Captcha image
+

+
+ +
- +
+
+ \ No newline at end of file diff --git a/html/captcha.old.html b/html/captcha.old.html new file mode 100644 index 0000000..9124bf2 --- /dev/null +++ b/html/captcha.old.html @@ -0,0 +1,24 @@ + + + + 请输入验证码 + + + +
+

很抱歉...

+

您的查询看起来类似于来自计算机软件的自动请求。为了保护我们的用户,请原谅我们现在暂时不能处理您的请求。

+

要继续访问网页,请输入下面所示字符:

+
+ Captcha image +
+
+ + \ No newline at end of file diff --git a/html/reCatchaPage.html b/html/reCatchaPage.old.html similarity index 100% rename from html/reCatchaPage.html rename to html/reCatchaPage.old.html diff --git a/logs/foo b/logs/foo deleted file mode 100644 index e69de29..0000000 From b35f757c68cd211aa0f5ef7a48cd719cfd1bf32c Mon Sep 17 00:00:00 2001 From: WenJun Date: Thu, 25 Sep 2014 10:52:21 +0800 Subject: [PATCH 14/19] update config --- config.lua | 2 +- html/captcha.html | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/config.lua b/config.lua index 692f31d..e5fa35a 100644 --- a/config.lua +++ b/config.lua @@ -71,7 +71,7 @@ local Config = { whiteTime = 600, -- 用于生成token密码的key过期时间 - keyExpire = 0, + keyExpire = 600, -- 匹配url模式,可选值requestUri,uri -- 值requestUri时,url-protect目录下的正则匹配的是浏览器最初请求的地址且没有被decode,带参数的链接 diff --git a/html/captcha.html b/html/captcha.html index ea255de..bd2a15b 100644 --- a/html/captcha.html +++ b/html/captcha.html @@ -146,10 +146,12 @@
-

很抱歉...

-

您的查询看起来类似于来自计算机软件的自动请求。

-

为了保护我们的用户,请原谅我们现在暂时不能处理您的请求。

-

要继续访问网页,请输入下面所示字符:

+ + +

本站为防止被恶意攻击已开启验证机制

+

此验证页面仅在被认为恶意攻击时出现

+

您正常浏览时也有可能触发防攻击程序

+

请输入验证码继续访问

Captcha image

From 60949d7b43f6d4bc34aa430989f60a03a76da3d6 Mon Sep 17 00:00:00 2001 From: WenJun Date: Sun, 28 Sep 2014 15:32:40 +0800 Subject: [PATCH 15/19] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=99=BD=E5=90=8D?= =?UTF-8?q?=E5=8D=95=E4=BB=A5=E5=8F=8A=E9=AA=8C=E8=AF=81=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- html/captcha.html | 21 +++-- html/reCatchaPage.html | 172 ++++++++++++++++++++++++++++++++++ url-protect/white_ip_list.txt | 30 +++++- 3 files changed, 213 insertions(+), 10 deletions(-) create mode 100644 html/reCatchaPage.html diff --git a/html/captcha.html b/html/captcha.html index bd2a15b..3a7dc4c 100644 --- a/html/captcha.html +++ b/html/captcha.html @@ -8,7 +8,7 @@ height: 100% } body { - font-family: Tahoma, Verdana, Arial, sans-serif; + font-family: "微软雅黑","宋体" Tahoma, Verdana, Arial, sans-serif; font: 12px/1.5 arial, \5b8b\4f53; background-color: #fff; margin: 0 auto @@ -140,18 +140,23 @@ } .btn:focus, .btn:active:focus, .btn.active:focus { outline: 0 - } + } +.red { + color: #ce2029 + } +
- - -

本站为防止被恶意攻击已开启验证机制

-

此验证页面仅在被认为恶意攻击时出现

-

您正常浏览时也有可能触发防攻击程序

-

请输入验证码继续访问

+


+
+

本站为防止被恶意攻击已开启验证机制

+

此验证页面仅在被认为恶意攻击时出现

+

您正常浏览时也有可能触发防攻击程序

+
+

请输入验证码继续访问!!!

Captcha image

diff --git a/html/reCatchaPage.html b/html/reCatchaPage.html new file mode 100644 index 0000000..516734c --- /dev/null +++ b/html/reCatchaPage.html @@ -0,0 +1,172 @@ + + + + + + 请输入验证码 + + + +
+
+
+


+
+

本站为防止被恶意攻击已开启验证机制

+

此验证页面仅在被认为恶意攻击时出现

+

您正常浏览时也有可能触发防攻击程序

+
+

请输入验证码继续访问!!!

+

验证码输入错误,请重新输入

+ +
Captcha image
+

+
+ +
+ +
+
+
+ + \ No newline at end of file diff --git a/url-protect/white_ip_list.txt b/url-protect/white_ip_list.txt index e27eed5..7d30de4 100644 --- a/url-protect/white_ip_list.txt +++ b/url-protect/white_ip_list.txt @@ -2,7 +2,7 @@ 61.155.149.* 61.182.137.* 117.27.149.* -117.34.28.1.* +117.34.28.* 119.188.132.* 119.188.14.* 119.63.193.* @@ -11,4 +11,30 @@ 180.76.6.* 183.60.235.* 220.181.108.* -222.216.190.* \ No newline at end of file +222.216.190.* +220.181.126.* +220.181.165.* +220.181.38.* +220.181.51.* +180.149.130.* +180.149.133.* +202.46.48.* +202.46.49.* +202.46.50.* +202.46.51.* +202.46.52.* +202.46.53.* +202.46.54.* +202.46.55.* +202.46.56.* +202.46.60.* +202.46.61.* +202.46.62.* +182.118.26.* +182.118.43.* +182.118.44.* +182.118.45.* +182.118.54.* +182.118.60.* +182.118.70.* +182.118.71.* \ No newline at end of file From a27370e8191a0df89e7d4d9b37acbf80a802b4a4 Mon Sep 17 00:00:00 2001 From: WenJun Date: Fri, 3 Oct 2014 10:41:07 +0800 Subject: [PATCH 16/19] no message --- guard.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/guard.lua b/guard.lua index 3e036dd..81410d3 100644 --- a/guard.lua +++ b/guard.lua @@ -79,7 +79,7 @@ end function Guard:blackListModules(ip, reqUri, headers) local blackKey = ip.."black" if _Conf.dict:get(blackKey) then --判断ip是否存在黑名单字典 - self:debug("[blackListModules] ip "..ip.." in blacklist",ip,reqUri) + self:debug("[IpblackListModules] ip "..ip.." in blacklist",ip,reqUri) self:takeAction(ip,reqUri) --存在则执行相应动作 end @@ -94,7 +94,7 @@ function Guard:blackListModules(ip, reqUri, headers) local uaMd5 = ngx.md5(userAgent) local blackUaKey = uaMd5 .. 'BlackUAKey' if _Conf.dict:get(blackUaKey) then --判断ua是否存在黑名单字典 - self:debug("[blackListModules] ip "..ip.." in ua blacklist".." "..userAgent, ip, reqUri) + self:debug("[UablackListModules] ip "..ip.." in ua blacklist".." "..userAgent, ip, reqUri) self:takeAction(ip,reqUri) --存在则执行相应动作 end end From b70bd4e09f89e3cbd1f2bf6cdee6cd29f06da661 Mon Sep 17 00:00:00 2001 From: WenJun Date: Fri, 3 Oct 2014 10:51:40 +0800 Subject: [PATCH 17/19] update read me --- README.md | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index bc35065..7bac5f0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,70 @@ -http-guard -========== +## http-guard -prevent cc attack +HttpGuard是基于openresty,以lua脚本语言开发的防cc攻击软件。而openresty是集成了高性能web服务器Nginx,以及一系列的Nginx模块,这其中最重要的,也是我们主要用到的nginx lua模块。HttpGuard基于nginx lua开发,继承了nginx高并发,高性能的特点,可以以非常小的性能损耗来防范大规模的cc攻击。 + +下面介绍HttpGuard防cc的一些特性: + +1.限制单个IP或者UA在一定时间内的请求次数 +2.向访客发送302转向响应头来识别恶意用户,并阻止其再次访问 +3.向访客发送带有跳转功能的js代码来识别恶意用户,并阻止其再次访问 +4.向访客发送cookie来识别恶意用户,并阻止其再次访问 +5.支持向访客发送带有验证码的页面,来进一步识别,以免误伤 +6.支持直接断开恶意访客的连接 +7.支持结合iptables来阻止恶意访客再次连接 +8.支持白名单/黑名单功能 +9.支持根据统计特定端口的连接数来自动开启或关闭防cc模式 + +## 部署HttpGuard +### 安装openresty或者nginx lua + +按照openresty官网手动安装[http://openresty.com](http://openresty.com) + +### 安装HttpGuard + +假设我们把HttpGuard安装到/data/www/waf/,当然你可以选择安装在任意目录。 + +``` +cd /data/www +wget --no-check-certificate https://github.com/wenjun1055/HttpGuard/archive/master.zip +unzip master.zip +mv HttpGuard-master waf +``` + +### 生成验证码图片 + +为了支持验证码识别用户,我们需要先生成验证码图片。生成验证码图片需要系统安装有php,以及php-gd模块。 +用以下命令执行getImg.php文件生成验证码 + +``` +cd /data/www/waf/captcha/ +/usr/local/php/bin/php getImg.php +``` + +大概要生成一万个图片,可能需要花几分钟的时间。 + +### 修改nginx.conf配置文件 + +向http区块输入如下代码: + +``` +lua_package_path "/data/www/waf/?.lua"; +lua_shared_dict guard_dict 100m; +lua_shared_dict dict_captcha 70m; +init_by_lua_file '/data/www/waf/init.lua'; +access_by_lua_file '/data/www/waf/runtime.lua'; +lua_max_running_timers 1; +``` + +### 配置HttpGuard + +1.HttpGuard安装目录,修改为实际安装到的目录。 + +``` +baseDir = '/data/www/waf/' +``` + +2.key是否动态生成,可选static,dynamic,如果选dynamic,下面所有的keySecret不需要更改,如果选static,修改手动修改下面的keySecret + +``` +keyDefine = "dynamic", +``` From 4e8576f1261cac53e2fe6d5e2665d3e0fd693a55 Mon Sep 17 00:00:00 2001 From: WenJun Date: Fri, 3 Oct 2014 10:55:27 +0800 Subject: [PATCH 18/19] update read me --- README.md | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 7bac5f0..ccd73f0 100644 --- a/README.md +++ b/README.md @@ -4,15 +4,15 @@ HttpGuard是基于openresty,以lua脚本语言开发的防cc攻击软件。而op 下面介绍HttpGuard防cc的一些特性: -1.限制单个IP或者UA在一定时间内的请求次数 -2.向访客发送302转向响应头来识别恶意用户,并阻止其再次访问 -3.向访客发送带有跳转功能的js代码来识别恶意用户,并阻止其再次访问 -4.向访客发送cookie来识别恶意用户,并阻止其再次访问 -5.支持向访客发送带有验证码的页面,来进一步识别,以免误伤 -6.支持直接断开恶意访客的连接 -7.支持结合iptables来阻止恶意访客再次连接 -8.支持白名单/黑名单功能 -9.支持根据统计特定端口的连接数来自动开启或关闭防cc模式 +1. 限制单个IP或者UA在一定时间内的请求次数 +2. 向访客发送302转向响应头来识别恶意用户,并阻止其再次访问 +3. 向访客发送带有跳转功能的js代码来识别恶意用户,并阻止其再次访问 +4. 向访客发送cookie来识别恶意用户,并阻止其再次访问 +5. 支持向访客发送带有验证码的页面,来进一步识别,以免误伤 +6. 支持直接断开恶意访客的连接 +7. 支持结合iptables来阻止恶意访客再次连接 +8. 支持白名单/黑名单功能 +9. 支持根据统计特定端口的连接数来自动开启或关闭防cc模式 ## 部署HttpGuard ### 安装openresty或者nginx lua @@ -57,14 +57,4 @@ lua_max_running_timers 1; ### 配置HttpGuard -1.HttpGuard安装目录,修改为实际安装到的目录。 - -``` -baseDir = '/data/www/waf/' -``` - -2.key是否动态生成,可选static,dynamic,如果选dynamic,下面所有的keySecret不需要更改,如果选static,修改手动修改下面的keySecret - -``` -keyDefine = "dynamic", -``` +详细配置说明在[config.lua](https://github.com/wenjun1055/HttpGuard/blob/master/guard.lua)中,请根据需求进行配置 \ No newline at end of file From c28a0f225551866d0d36c3fcbc987caaad33429c Mon Sep 17 00:00:00 2001 From: WenJun Date: Fri, 3 Oct 2014 10:56:00 +0800 Subject: [PATCH 19/19] no message --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ccd73f0..3110d01 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## http-guard +# http-guard HttpGuard是基于openresty,以lua脚本语言开发的防cc攻击软件。而openresty是集成了高性能web服务器Nginx,以及一系列的Nginx模块,这其中最重要的,也是我们主要用到的nginx lua模块。HttpGuard基于nginx lua开发,继承了nginx高并发,高性能的特点,可以以非常小的性能损耗来防范大规模的cc攻击。