From de95c77575a6d9c4610f74221fb7372053add55b Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 14 Sep 2015 15:18:26 +0800 Subject: [PATCH 01/31] =?UTF-8?q?=E6=B7=BB=E5=8A=A0block=20time?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 276 ++++++++++++++++++++++++++--------------------------- config.lua | 1 + init.lua | 23 ++++- waf.lua | 1 + 4 files changed, 160 insertions(+), 141 deletions(-) diff --git a/README.md b/README.md index 34e8907..69fbff3 100644 --- a/README.md +++ b/README.md @@ -1,138 +1,138 @@ -##ngx_lua_waf - -ngx_lua_waf是我刚入职趣游时候开发的一个基于ngx_lua的web应用防火墙。 - -代码很简单,开发初衷主要是使用简单,高性能和轻量级。 - -现在开源出来,遵从MIT许可协议。其中包含我们的过滤规则。如果大家有什么建议和想fa,欢迎和我一起完善。 - -###用途: - - 防止sql注入,本地包含,部分溢出,fuzzing测试,xss,SSRF等web攻击 - 防止svn/备份之类文件泄漏 - 防止ApacheBench之类压力测试工具的攻击 - 屏蔽常见的扫描黑客工具,扫描器 - 屏蔽异常的网络请求 - 屏蔽图片附件类目录php执行权限 - 防止webshell上传 - -###推荐安装: - -推荐使用lujit2.1做lua支持 - -ngx_lua如果是0.9.2以上版本,建议正则过滤函数改为ngx.re.find,匹配效率会提高三倍左右。 - - -###使用说明: - -nginx安装路径假设为:/usr/local/nginx/conf/ - -把ngx_lua_waf下载到conf目录下,解压命名为waf - -在nginx.conf的http段添加 - - lua_package_path "/usr/local/nginx/conf/waf/?.lua"; - lua_shared_dict limit 10m; - init_by_lua_file /usr/local/nginx/conf/waf/init.lua; - access_by_lua_file /usr/local/nginx/conf/waf/waf.lua; - -配置config.lua里的waf规则目录(一般在waf/conf/目录下) - - RulePath = "/usr/local/nginx/conf/waf/wafconf/" - -绝对路径如有变动,需对应修改 - -然后重启nginx即可 - - -###配置文件详细说明: - - RulePath = "/usr/local/nginx/conf/waf/wafconf/" - --规则存放目录 - attacklog = "off" - --是否开启攻击信息记录,需要配置logdir - logdir = "/usr/local/nginx/logs/hack/" - --log存储目录,该目录需要用户自己新建,切需要nginx用户的可写权限 - UrlDeny="on" - --是否拦截url访问 - Redirect="on" - --是否拦截后重定向 - CookieMatch = "on" - --是否拦截cookie攻击 - postMatch = "on" - --是否拦截post攻击 - whiteModule = "on" - --是否开启URL白名单 - black_fileExt={"php","jsp"} - --填写可上传文件后缀类型 - ipWhitelist={"127.0.0.1"} - --ip白名单,多个ip用逗号分隔 - ipBlocklist={"1.0.0.1"} - --ip黑名单,多个ip用逗号分隔 - CCDeny="on" - --是否开启拦截cc攻击(需要nginx.conf的http段增加lua_shared_dict limit 10m;) - CCrate = "100/60" - --设置cc攻击频率,单位为秒. - --默认1分钟同一个IP只能请求同一个地址100次 - html=[[Please go away~~]] - --警告内容,可在中括号内自定义 - 备注:不要乱动双引号,区分大小写 - -###检查规则是否生效 - -部署完毕可以尝试如下命令: - - curl http://xxxx/test.php?id=../etc/passwd - 返回"Please go away~~"字样,说明规则生效。 - -注意:默认,本机在白名单不过滤,可自行调整config.lua配置 - - -###效果图如下: - -![sec](http://i.imgur.com/wTgOcm2.png) - -![sec](http://i.imgur.com/DqU30au.png) - -###规则更新: - -考虑到正则的缓存问题,动态规则会影响性能,所以暂没用共享内存字典和redis之类东西做动态管理。 - -规则更新可以把规则文件放置到其他服务器,通过crontab任务定时下载来更新规则,nginx reload即可生效。以保障ngx lua waf的高性能。 - -只记录过滤日志,不开启过滤,在代码里在check前面加上--注释即可,如果需要过滤,反之 - -###一些说明: - - 过滤规则在wafconf下,可根据需求自行调整,每条规则需换行,或者用|分割 - - global是全局过滤文件,里面的规则对post和get都过滤 - get是只在get请求过滤的规则 - post是只在post请求过滤的规则 - whitelist是白名单,里面的url匹配到不做过滤 - user-agent是对user-agent的过滤规则 - - - 默认开启了get和post过滤,需要开启cookie过滤的,编辑waf.lua取消部分--注释即可 - - 日志文件名称格式如下:虚拟主机名_sec.log - - -## Copyright - - - - - - - - - - - - - - -
Weibo神奇的魔法师
Forumhttp://bbs.linuxtone.org/
CopyrightCopyright (c) 2013- loveshell
LicenseMIT License
- -感谢ngx_lua模块的开发者[@agentzh](https://github.com/agentzh/),春哥是我所接触过开源精神最好的人 +##ngx_lua_waf + +ngx_lua_waf是我刚入职趣游时候开发的一个基于ngx_lua的web应用防火墙。 + +代码很简单,开发初衷主要是使用简单,高性能和轻量级。 + +现在开源出来,遵从MIT许可协议。其中包含我们的过滤规则。如果大家有什么建议和想fa,欢迎和我一起完善。 + +###用途: + + 防止sql注入,本地包含,部分溢出,fuzzing测试,xss,SSRF等web攻击 + 防止svn/备份之类文件泄漏 + 防止ApacheBench之类压力测试工具的攻击 + 屏蔽常见的扫描黑客工具,扫描器 + 屏蔽异常的网络请求 + 屏蔽图片附件类目录php执行权限 + 防止webshell上传 + +###推荐安装: + +推荐使用lujit2.1做lua支持 + +ngx_lua如果是0.9.2以上版本,建议正则过滤函数改为ngx.re.find,匹配效率会提高三倍左右。 + + +###使用说明: + +nginx安装路径假设为:/usr/local/nginx/conf/ + +把ngx_lua_waf下载到conf目录下,解压命名为waf + +在nginx.conf的http段添加 + + lua_package_path "/usr/local/nginx/conf/waf/?.lua"; + lua_shared_dict limit 10m; + init_by_lua_file /usr/local/nginx/conf/waf/init.lua; + access_by_lua_file /usr/local/nginx/conf/waf/waf.lua; + +配置config.lua里的waf规则目录(一般在waf/conf/目录下) + + RulePath = "/usr/local/nginx/conf/waf/wafconf/" + +绝对路径如有变动,需对应修改 + +然后重启nginx即可 + + +###配置文件详细说明: + + RulePath = "/usr/local/nginx/conf/waf/wafconf/" + --规则存放目录 + attacklog = "off" + --是否开启攻击信息记录,需要配置logdir + logdir = "/usr/local/nginx/logs/hack/" + --log存储目录,该目录需要用户自己新建,切需要nginx用户的可写权限 + UrlDeny="on" + --是否拦截url访问 + Redirect="on" + --是否拦截后重定向 + CookieMatch = "on" + --是否拦截cookie攻击 + postMatch = "on" + --是否拦截post攻击 + whiteModule = "on" + --是否开启URL白名单 + black_fileExt={"php","jsp"} + --填写可上传文件后缀类型 + ipWhitelist={"127.0.0.1"} + --ip白名单,多个ip用逗号分隔 + ipBlocklist={"1.0.0.1"} + --ip黑名单,多个ip用逗号分隔 + CCDeny="on" + --是否开启拦截cc攻击(需要nginx.conf的http段增加lua_shared_dict limit 10m;) + CCrate = "100/60" + --设置cc攻击频率,单位为秒. + --默认1分钟同一个IP只能请求同一个地址100次 + html=[[Please go away~~]] + --警告内容,可在中括号内自定义 + 备注:不要乱动双引号,区分大小写 + +###检查规则是否生效 + +部署完毕可以尝试如下命令: + + curl http://xxxx/test.php?id=../etc/passwd + 返回"Please go away~~"字样,说明规则生效。 + +注意:默认,本机在白名单不过滤,可自行调整config.lua配置 + + +###效果图如下: + +![sec](http://i.imgur.com/wTgOcm2.png) + +![sec](http://i.imgur.com/DqU30au.png) + +###规则更新: + +考虑到正则的缓存问题,动态规则会影响性能,所以暂没用共享内存字典和redis之类东西做动态管理。 + +规则更新可以把规则文件放置到其他服务器,通过crontab任务定时下载来更新规则,nginx reload即可生效。以保障ngx lua waf的高性能。 + +只记录过滤日志,不开启过滤,在代码里在check前面加上--注释即可,如果需要过滤,反之 + +###一些说明: + + 过滤规则在wafconf下,可根据需求自行调整,每条规则需换行,或者用|分割 + + global是全局过滤文件,里面的规则对post和get都过滤 + get是只在get请求过滤的规则 + post是只在post请求过滤的规则 + whitelist是白名单,里面的url匹配到不做过滤 + user-agent是对user-agent的过滤规则 + + + 默认开启了get和post过滤,需要开启cookie过滤的,编辑waf.lua取消部分--注释即可 + + 日志文件名称格式如下:虚拟主机名_sec.log + + +## Copyright + + + + + + + + + + + + + + +
Weibo神奇的魔法师
Forumhttp://bbs.linuxtone.org/
CopyrightCopyright (c) 2013- loveshell
LicenseMIT License
+ +感谢ngx_lua模块的开发者[@agentzh](https://github.com/agentzh/),春哥是我所接触过开源精神最好的人 diff --git a/config.lua b/config.lua index 6e66ce6..f3b6b65 100644 --- a/config.lua +++ b/config.lua @@ -11,6 +11,7 @@ ipWhitelist={"127.0.0.1"} ipBlocklist={"1.0.0.1"} CCDeny="off" CCrate="100/60" +DenySeconds="600" html=[[ diff --git a/init.lua b/init.lua index eb44bf0..55f9902 100644 --- a/init.lua +++ b/init.lua @@ -14,6 +14,7 @@ PathInfoFix = optionIsOn(PathInfoFix) attacklog = optionIsOn(attacklog) CCDeny = optionIsOn(CCDeny) Redirect=optionIsOn(Redirect) + function getClientIp() IP = ngx.req.get_headers()["X-Real-IP"] if IP == nil then @@ -24,6 +25,7 @@ function getClientIp() end return IP end + function write(logfile,msg) local fd = io.open(logfile,"ab") if fd == nil then return end @@ -31,6 +33,7 @@ function write(logfile,msg) fd:flush() fd:close() end + function log(method,url,data,ruletag) if attacklog then local realIp = getClientIp() @@ -46,7 +49,8 @@ function log(method,url,data,ruletag) write(filename,line) end end -------------------------------------规则读取函数------------------------------------------------------------------- + +------------------------------------规则读取函数----------------------------------------- function read_rule(var) file = io.open(rulepath..'/'..var,"r") if file==nil then @@ -89,6 +93,7 @@ function whiteurl() end return false end + function fileExtCheck(ext) local items = Set(black_fileExt) ext=string.lower(ext) @@ -102,11 +107,13 @@ function fileExtCheck(ext) end return false end + function Set (list) local set = {} for _, l in ipairs(list) do set[l] = true end return set end + function args() for _,rule in pairs(argsrules) do local args = ngx.req.get_uri_args() @@ -155,6 +162,7 @@ function ua() end return false end + function body(data) for _,rule in pairs(postrules) do if rule ~="" and data~="" and ngxmatch(unescape(data),rule,"isjo") then @@ -165,6 +173,7 @@ function body(data) end return false end + function cookie() local ck = ngx.var.http_cookie if CookieCheck and ck then @@ -186,10 +195,18 @@ function denycc() CCseconds=tonumber(string.match(CCrate,'/(.*)')) local token = getClientIp()..uri local limit = ngx.shared.limit - local req,_=limit:get(token) + local req,_ = limit:get(token) + local ip = getClientIp + local block,_ = limit:get(ip) + + if block then + ngx.exit(503) + end + if req then if req > CCcount then - ngx.exit(503) + limit:set(ip,1,DenySeconds) + ngx.exit(503) return true else limit:incr(token,1) diff --git a/waf.lua b/waf.lua index bc9821c..f35e95e 100644 --- a/waf.lua +++ b/waf.lua @@ -1,6 +1,7 @@ local content_length=tonumber(ngx.req.get_headers()['content-length']) local method=ngx.req.get_method() local ngxmatch=ngx.re.match + if whiteip() then elseif blockip() then elseif denycc() then From c1148409c426c908e31ac7d71b3ea49d2f7a8b6a Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 14 Sep 2015 15:23:50 +0800 Subject: [PATCH 02/31] modify a bug --- init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/init.lua b/init.lua index 55f9902..a837aa2 100644 --- a/init.lua +++ b/init.lua @@ -196,7 +196,7 @@ function denycc() local token = getClientIp()..uri local limit = ngx.shared.limit local req,_ = limit:get(token) - local ip = getClientIp + local ip = getClientIp() local block,_ = limit:get(ip) if block then From b3278cd5eb4902e5b7c7d76063a7744a1ff75d80 Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 14 Sep 2015 19:36:25 +0800 Subject: [PATCH 03/31] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=A6=81=E6=AD=A2?= =?UTF-8?q?=E6=89=80=E6=9C=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- init.lua | 2 +- wafconf/url | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/init.lua b/init.lua index a837aa2..dbff0f7 100644 --- a/init.lua +++ b/init.lua @@ -250,7 +250,7 @@ end function blockip() if next(ipBlocklist) ~= nil then for _,ip in pairs(ipBlocklist) do - if getClientIp()==ip then + if getClientIp()==ip or ip=="0.0.0.0" then ngx.exit(403) return true end diff --git a/wafconf/url b/wafconf/url index 31130d3..67e621f 100644 --- a/wafconf/url +++ b/wafconf/url @@ -1,4 +1,4 @@ -\.(svn|htaccess|bash_history) +\.(svn|htaccess|bash_history|git) \.(bak|inc|old|mdb|sql|backup|java|class)$ (vhost|bbs|host|wwwroot|www|site|root|hytop|flashfxp).*\.rar (phpmyadmin|jmx-console|jmxinvokerservlet) From 790acc7a65473b1d607bac45220031ea1468bcee Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 16 Sep 2015 18:50:14 +0800 Subject: [PATCH 04/31] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=BD=91=E6=AE=B5?= =?UTF-8?q?=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- init.lua | 51 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/init.lua b/init.lua index dbff0f7..ea7261f 100644 --- a/init.lua +++ b/init.lua @@ -236,10 +236,52 @@ function get_boundary() return match(header, ";%s*boundary=([^\",;]+)") end +function string.split(str, delimiter) + if str==nil or str=='' or delimiter==nil then + return nil + end + + local result = {} + for match in (str..delimiter):gmatch("(.-)"..delimiter) do + table.insert(result, match) + end + return result +end + +function innet(ip, network) + local star = '' + for i in string.gmatch(network, '%*') do + star = star..i + end + + local ip = string.split(ip, '%.') + local network = string.split(network, '%.') + if ip == nil or network == nil then + return false + end + + local ip_prefix = {} + local network_prefix = {} + for i=1, 4-string.len(star) do + ip_prefix[i] = ip[i] + network_prefix[i] = network[i] + end + + ip_prefix = table.concat(ip_prefix, '.') + network_prefix = table.concat(network_prefix, '.') + + if ip_prefix == network_prefix then + return true + else + return false + end +end + function whiteip() if next(ipWhitelist) ~= nil then - for _,ip in pairs(ipWhitelist) do - if getClientIp()==ip then + ip = getClientIp() + for _,wip in pairs(ipWhitelist) do + if ip = wip or innet(ip, wip) then return true end end @@ -249,8 +291,9 @@ end function blockip() if next(ipBlocklist) ~= nil then - for _,ip in pairs(ipBlocklist) do - if getClientIp()==ip or ip=="0.0.0.0" then + ip = getClientIp() + for _,bip in pairs(ipBlocklist) do + if ip == bip or ip=="0.0.0.0" or innet(ip, bip) then ngx.exit(403) return true end From 2fb6dc226ef19ff4b99d15396e87f4c0adebb2f6 Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 16 Sep 2015 20:22:32 +0800 Subject: [PATCH 05/31] fix a bug --- init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/init.lua b/init.lua index ea7261f..ffa32aa 100644 --- a/init.lua +++ b/init.lua @@ -281,7 +281,7 @@ function whiteip() if next(ipWhitelist) ~= nil then ip = getClientIp() for _,wip in pairs(ipWhitelist) do - if ip = wip or innet(ip, wip) then + if ip == wip or innet(ip, wip) then return true end end From e679b8993d99a398a014e2ef4c44d8e8e11cc061 Mon Sep 17 00:00:00 2001 From: ibuler Date: Fri, 17 Jun 2016 16:37:17 +0800 Subject: [PATCH 06/31] Update --- config.lua | 66 +++++---------- init.lua | 126 ++++++++++++++--------------- wafconf/{user-agent => user_agent} | 0 wafconf/{whiteurl => white_url} | 0 4 files changed, 85 insertions(+), 107 deletions(-) rename wafconf/{user-agent => user_agent} (100%) rename wafconf/{whiteurl => white_url} (100%) diff --git a/config.lua b/config.lua index f3b6b65..6bf541c 100644 --- a/config.lua +++ b/config.lua @@ -1,46 +1,24 @@ -RulePath = "/usr/local/nginx/conf/waf/wafconf/" -attacklog = "on" -logdir = "/usr/local/nginx/logs/hack/" -UrlDeny="on" -Redirect="on" -CookieMatch="on" -postMatch="on" -whiteModule="on" -black_fileExt={"php","jsp"} -ipWhitelist={"127.0.0.1"} -ipBlocklist={"1.0.0.1"} -CCDeny="off" -CCrate="100/60" -DenySeconds="600" -html=[[ - - -网站防火墙 - - +debug = false +rule_path = "/usr/local/nginx/conf/waf/wafconf/" +url_check = false +url_write_check = false +args_check = false +ua_check = false +ua_write_check = false +cookie_check = false +post_check = false - +black_file_ext = {"php", "jsp"} +attack_log = false +attach_log_dir = "/usr/local/nginx/logs/hack/" -
- - -
-
网站防火墙
-
-

您的请求带有不合法参数,已被网站管理员设置拦截!

-

可能原因:您提交的内容包含危险的攻击请求

-

如何解决:

-
  • 1)检查提交内容;
  • -
  • 2)如网站托管,请联系空间提供商;
  • -
  • 3)普通网站访客,请联系网站管理员;
-
-
-
- -]] +redirect = false +redirect_url = "http://www.baidu.com" +ip_white_list = {"127.0.0.1", "172.16.1.*"} +ip_black_list = {"1.0.0.1", "172.16.1.*"} + +cc_deny = false +cc_rate = "100/60" +cc_deny_seconds = "600" +cc_redirect = false +cc_redirect_url = redirect_url diff --git a/init.lua b/init.lua index ffa32aa..ec235ca 100644 --- a/init.lua +++ b/init.lua @@ -1,133 +1,133 @@ -require 'config' +-- require 'config' local match = string.match -local ngxmatch=ngx.re.match -local unescape=ngx.unescape_uri +local ngx_match = ngx.re.match +local unescape = ngx.unescape_uri local get_headers = ngx.req.get_headers -local optionIsOn = function (options) return options == "on" and true or false end -logpath = logdir -rulepath = RulePath -UrlDeny = optionIsOn(UrlDeny) -PostCheck = optionIsOn(postMatch) -CookieCheck = optionIsOn(cookieMatch) -WhiteCheck = optionIsOn(whiteModule) -PathInfoFix = optionIsOn(PathInfoFix) -attacklog = optionIsOn(attacklog) -CCDeny = optionIsOn(CCDeny) -Redirect=optionIsOn(Redirect) function getClientIp() - IP = ngx.req.get_headers()["X-Real-IP"] + IP = get_headers()["X-Real-IP"] if IP == nil then - IP = ngx.var.remote_addr + IP = ngx.var.remote_addr end if IP == nil then - IP = "unknown" + IP = "unknown" end return IP end -function write(logfile,msg) - local fd = io.open(logfile,"ab") - if fd == nil then return end +function write(logfile, msg) + local fd = io.open(logfile, "ab") + if fd == nil then + return + end fd:write(msg) fd:flush() fd:close() end -function log(method,url,data,ruletag) - if attacklog then +function log(method, url, data, tag) + if attack_log 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" + line = realIp.." ["..time.."] \""..method.." "..servername..url.."\" \""..data.."\" \""..ua.."\" \""..tag.."\"\n" else - line = realIp.." ["..time.."] \""..method.." "..servername..url.."\" \""..data.."\" - \""..ruletag.."\"\n" + line = realIp.." ["..time.."] \""..method.." "..servername..url.."\" \""..data.."\" - \""..tag.."\"\n" end local filename = logpath..'/'..servername.."_"..ngx.today().."_sec.log" write(filename,line) end end -------------------------------------规则读取函数----------------------------------------- -function read_rule(var) - file = io.open(rulepath..'/'..var,"r") - if file==nil then +------------------------------------ 规则读取函数 ----------------------------------------- +function readRule(var) + file = io.open(rulepath..'/'..var, "r") + if file == nil then return end t = {} for line in file:lines() do - table.insert(t,line) + table.insert(t, line) end file:close() return(t) end -urlrules=read_rule('url') -argsrules=read_rule('args') -uarules=read_rule('user-agent') -wturlrules=read_rule('whiteurl') -postrules=read_rule('post') -ckrules=read_rule('cookie') +url_rules = read_rule('url') +white_url_rules = read_rule('white_url') +args_rules = read_rule('args') +ua_rules = read_rule('user_agent') +post_rules = read_rule('post') +cookie_rules = read_rule('cookie') -function say_html() - if Redirect then +function debugSay(msg) + if debug then ngx.header.content_type = "text/html" ngx.status = ngx.HTTP_FORBIDDEN - ngx.say(html) + ngx.say(msg) ngx.exit(ngx.status) end end -function whiteurl() - if WhiteCheck then - if wturlrules ~=nil then - for _,rule in pairs(wturlrules) do - if ngxmatch(ngx.var.uri,rule,"isjo") then - return true - end - end + +function whiteURLCheck() + if white_url_rules ~= nil then + for _, rule in pairs(white_url_rules) do + if ngx_match(ngx.var.uri, rule, "isjo") then + return true + end end end return false end -function fileExtCheck(ext) + +function fileExtCheck(ext, black_file_ext) local items = Set(black_fileExt) - ext=string.lower(ext) + 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) - say_html() + if ngx.re.match(ext, rule, "isjo") then + if attack_log then + log('POST',ngx.var.request_uri,"-","file attack with ext "..ext) + end + + if debug then + debugSay(ngx.var.request_uri.."-".."file attack with ext: "..ext) + end end end end return false end -function Set (list) - local set = {} - for _, l in ipairs(list) do set[l] = true end - return set + +function set(list) + local set = {} + for _, l in ipairs(list) do + set[l] = true + end + return set end -function args() - for _,rule in pairs(argsrules) do + +function checkArgs() + for _, rule in pairs(args_rules) do local args = ngx.req.get_uri_args() for key, val in pairs(args) do - if type(val)=='table' then + if type(val) == 'table' then if val ~= false then - data=table.concat(val, " ") + data = table.concat(val, " ") end else - data=val + data = val end - if data and type(data) ~= "boolean" and rule ~="" and ngxmatch(unescape(data),rule,"isjo") then - log('GET',ngx.var.request_uri,"-",rule) - say_html() + if data and type(data) ~= "boolean" and rule ~="" and ngx_match(unescape(data), rule, "isjo") then + log('GET', ngx.var.request_uri, "-", rule) + debugSay(ngx.var.request_uri.."-"..rule) return true end end diff --git a/wafconf/user-agent b/wafconf/user_agent similarity index 100% rename from wafconf/user-agent rename to wafconf/user_agent diff --git a/wafconf/whiteurl b/wafconf/white_url similarity index 100% rename from wafconf/whiteurl rename to wafconf/white_url From 0563938d964147a47139eb38e0a4b2a838d34d66 Mon Sep 17 00:00:00 2001 From: ibuler Date: Sat, 18 Jun 2016 09:55:27 +0800 Subject: [PATCH 07/31] modify readRule --- init.lua | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/init.lua b/init.lua index ec235ca..cb5e6c2 100644 --- a/init.lua +++ b/init.lua @@ -55,12 +55,12 @@ function readRule(var) return(t) end -url_rules = read_rule('url') -white_url_rules = read_rule('white_url') -args_rules = read_rule('args') -ua_rules = read_rule('user_agent') -post_rules = read_rule('post') -cookie_rules = read_rule('cookie') +url_rules = readRule('url') +white_url_rules = readRule('white_url') +args_rules = readRule('args') +ua_rules = readRule('user_agent') +post_rules = readRule('post') +cookie_rules = readRule('cookie') function debugSay(msg) From 14bff06b0f2556604a76ac97a1e8967ba46f74e3 Mon Sep 17 00:00:00 2001 From: ibuler Date: Sat, 18 Jun 2016 09:58:12 +0800 Subject: [PATCH 08/31] comment some line --- init.lua | 332 +++++++++++++++++++++++++++---------------------------- 1 file changed, 166 insertions(+), 166 deletions(-) diff --git a/init.lua b/init.lua index cb5e6c2..b73a3e6 100644 --- a/init.lua +++ b/init.lua @@ -43,7 +43,7 @@ end ------------------------------------ 规则读取函数 ----------------------------------------- function readRule(var) - file = io.open(rulepath..'/'..var, "r") + file = io.open(rule_path..'/'..var, "r") if file == nil then return end @@ -136,168 +136,168 @@ function checkArgs() end -function url() - if UrlDeny then - for _,rule in pairs(urlrules) do - if rule ~="" and ngxmatch(ngx.var.request_uri,rule,"isjo") then - log('GET',ngx.var.request_uri,"-",rule) - say_html() - return true - end - end - end - return false -end - -function ua() - local ua = ngx.var.http_user_agent - if ua ~= nil then - for _,rule in pairs(uarules) do - if rule ~="" and ngxmatch(ua,rule,"isjo") then - log('UA',ngx.var.request_uri,"-",rule) - say_html() - return true - end - end - end - return false -end - -function body(data) - for _,rule in pairs(postrules) do - if rule ~="" and data~="" and ngxmatch(unescape(data),rule,"isjo") then - log('POST',ngx.var.request_uri,data,rule) - say_html() - return true - end - end - return false -end - -function cookie() - local ck = ngx.var.http_cookie - if CookieCheck and ck then - for _,rule in pairs(ckrules) do - if rule ~="" and ngxmatch(ck,rule,"isjo") then - log('Cookie',ngx.var.request_uri,"-",rule) - say_html() - return true - end - end - end - return false -end - -function denycc() - if CCDeny then - local uri=ngx.var.uri - CCcount=tonumber(string.match(CCrate,'(.*)/')) - CCseconds=tonumber(string.match(CCrate,'/(.*)')) - local token = getClientIp()..uri - local limit = ngx.shared.limit - local req,_ = limit:get(token) - local ip = getClientIp() - local block,_ = limit:get(ip) - - if block then - ngx.exit(503) - end - - if req then - if req > CCcount then - limit:set(ip,1,DenySeconds) - ngx.exit(503) - return true - else - limit:incr(token,1) - end - else - limit:set(token,1,CCseconds) - end - end - return false -end - -function get_boundary() - local header = get_headers()["content-type"] - if not header then - return nil - end - - if type(header) == "table" then - header = header[1] - end - - local m = match(header, ";%s*boundary=\"([^\"]+)\"") - if m then - return m - end - - return match(header, ";%s*boundary=([^\",;]+)") -end - -function string.split(str, delimiter) - if str==nil or str=='' or delimiter==nil then - return nil - end - - local result = {} - for match in (str..delimiter):gmatch("(.-)"..delimiter) do - table.insert(result, match) - end - return result -end - -function innet(ip, network) - local star = '' - for i in string.gmatch(network, '%*') do - star = star..i - end - - local ip = string.split(ip, '%.') - local network = string.split(network, '%.') - if ip == nil or network == nil then - return false - end - - local ip_prefix = {} - local network_prefix = {} - for i=1, 4-string.len(star) do - ip_prefix[i] = ip[i] - network_prefix[i] = network[i] - end - - ip_prefix = table.concat(ip_prefix, '.') - network_prefix = table.concat(network_prefix, '.') - - if ip_prefix == network_prefix then - return true - else - return false - end -end - -function whiteip() - if next(ipWhitelist) ~= nil then - ip = getClientIp() - for _,wip in pairs(ipWhitelist) do - if ip == wip or innet(ip, wip) then - return true - end - end - end - return false -end - -function blockip() - if next(ipBlocklist) ~= nil then - ip = getClientIp() - for _,bip in pairs(ipBlocklist) do - if ip == bip or ip=="0.0.0.0" or innet(ip, bip) then - ngx.exit(403) - return true - end - end - end - return false -end +-- function url() +-- if UrlDeny then +-- for _,rule in pairs(urlrules) do +-- if rule ~="" and ngxmatch(ngx.var.request_uri,rule,"isjo") then +-- log('GET',ngx.var.request_uri,"-",rule) +-- say_html() +-- return true +-- end +-- end +-- end +-- return false +-- end + +-- function ua() +-- local ua = ngx.var.http_user_agent +-- if ua ~= nil then +-- for _,rule in pairs(uarules) do +-- if rule ~="" and ngxmatch(ua,rule,"isjo") then +-- log('UA',ngx.var.request_uri,"-",rule) +-- say_html() +-- return true +-- end +-- end +-- end +-- return false +-- end + +-- function body(data) +-- for _,rule in pairs(postrules) do +-- if rule ~="" and data~="" and ngxmatch(unescape(data),rule,"isjo") then +-- log('POST',ngx.var.request_uri,data,rule) +-- say_html() +-- return true +-- end +-- end +-- return false +-- end + +-- function cookie() +-- local ck = ngx.var.http_cookie +-- if CookieCheck and ck then +-- for _,rule in pairs(ckrules) do +-- if rule ~="" and ngxmatch(ck,rule,"isjo") then +-- log('Cookie',ngx.var.request_uri,"-",rule) +-- say_html() +-- return true +-- end +-- end +-- end +-- return false +-- end + +-- function denycc() +-- if CCDeny then +-- local uri=ngx.var.uri +-- CCcount=tonumber(string.match(CCrate,'(.*)/')) +-- CCseconds=tonumber(string.match(CCrate,'/(.*)')) +-- local token = getClientIp()..uri +-- local limit = ngx.shared.limit +-- local req,_ = limit:get(token) +-- local ip = getClientIp() +-- local block,_ = limit:get(ip) + +-- if block then +-- ngx.exit(503) +-- end + +-- if req then +-- if req > CCcount then +-- limit:set(ip,1,DenySeconds) +-- ngx.exit(503) +-- return true +-- else +-- limit:incr(token,1) +-- end +-- else +-- limit:set(token,1,CCseconds) +-- end +-- end +-- return false +-- end + +-- function get_boundary() +-- local header = get_headers()["content-type"] +-- if not header then +-- return nil +-- end + +-- if type(header) == "table" then +-- header = header[1] +-- end + +-- local m = match(header, ";%s*boundary=\"([^\"]+)\"") +-- if m then +-- return m +-- end + +-- return match(header, ";%s*boundary=([^\",;]+)") +-- end + +-- function string.split(str, delimiter) +-- if str==nil or str=='' or delimiter==nil then +-- return nil +-- end + +-- local result = {} +-- for match in (str..delimiter):gmatch("(.-)"..delimiter) do +-- table.insert(result, match) +-- end +-- return result +-- end + +-- function innet(ip, network) +-- local star = '' +-- for i in string.gmatch(network, '%*') do +-- star = star..i +-- end + +-- local ip = string.split(ip, '%.') +-- local network = string.split(network, '%.') +-- if ip == nil or network == nil then +-- return false +-- end + +-- local ip_prefix = {} +-- local network_prefix = {} +-- for i=1, 4-string.len(star) do +-- ip_prefix[i] = ip[i] +-- network_prefix[i] = network[i] +-- end + +-- ip_prefix = table.concat(ip_prefix, '.') +-- network_prefix = table.concat(network_prefix, '.') + +-- if ip_prefix == network_prefix then +-- return true +-- else +-- return false +-- end +-- end + +-- function whiteip() +-- if next(ipWhitelist) ~= nil then +-- ip = getClientIp() +-- for _,wip in pairs(ipWhitelist) do +-- if ip == wip or innet(ip, wip) then +-- return true +-- end +-- end +-- end +-- return false +-- end + +-- function blockip() +-- if next(ipBlocklist) ~= nil then +-- ip = getClientIp() +-- for _,bip in pairs(ipBlocklist) do +-- if ip == bip or ip=="0.0.0.0" or innet(ip, bip) then +-- ngx.exit(403) +-- return true +-- end +-- end +-- end +-- return false +-- end From d919acf558c200f693f51a8fd1a01f8b61206365 Mon Sep 17 00:00:00 2001 From: ibuler Date: Sat, 18 Jun 2016 11:08:29 +0800 Subject: [PATCH 09/31] fix --- config.lua | 2 +- init.lua | 200 ++++++++++++++++++++++++++--------------------------- 2 files changed, 100 insertions(+), 102 deletions(-) diff --git a/config.lua b/config.lua index 6bf541c..3a6b055 100644 --- a/config.lua +++ b/config.lua @@ -1,5 +1,5 @@ debug = false -rule_path = "/usr/local/nginx/conf/waf/wafconf/" +rule_path = "/data/server/nginx/conf/waf/wafconf/" url_check = false url_write_check = false args_check = false diff --git a/init.lua b/init.lua index b73a3e6..47e701b 100644 --- a/init.lua +++ b/init.lua @@ -42,25 +42,25 @@ function log(method, url, data, tag) end ------------------------------------ 规则读取函数 ----------------------------------------- -function readRule(var) - file = io.open(rule_path..'/'..var, "r") - if file == nil then - return - end - t = {} - for line in file:lines() do - table.insert(t, line) - end - file:close() - return(t) -end +-- function readRule(var) +-- file = io.open(rule_path..'/'..var, "r") +-- if file == nil then +-- return +-- end +-- t = {} +-- for line in file:lines() do +-- table.insert(t, line) +-- end +-- file:close() +-- return(t) +-- end -url_rules = readRule('url') -white_url_rules = readRule('white_url') -args_rules = readRule('args') -ua_rules = readRule('user_agent') -post_rules = readRule('post') -cookie_rules = readRule('cookie') +-- url_rules = readRule('url') +-- white_url_rules = readRule('white_url') +-- args_rules = readRule('args') +-- ua_rules = readRule('user_agent') +-- post_rules = readRule('post') +-- cookie_rules = readRule('cookie') function debugSay(msg) @@ -73,67 +73,67 @@ function debugSay(msg) end -function whiteURLCheck() - if white_url_rules ~= nil then - for _, rule in pairs(white_url_rules) do - if ngx_match(ngx.var.uri, rule, "isjo") then - return true - end - end - end - return false -end +-- function whiteURLCheck() +-- if white_url_rules ~= nil then +-- for _, rule in pairs(white_url_rules) do +-- if ngx_match(ngx.var.uri, rule, "isjo") then +-- return true +-- end +-- end +-- end +-- return false +-- end -function fileExtCheck(ext, black_file_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 - if attack_log then - log('POST',ngx.var.request_uri,"-","file attack with ext "..ext) - end - - if debug then - debugSay(ngx.var.request_uri.."-".."file attack with ext: "..ext) - end - end - end - end - return false -end +-- function fileExtCheck(ext, black_file_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 +-- if attack_log then +-- log('POST',ngx.var.request_uri,"-","file attack with ext "..ext) +-- end +-- if debug then +-- debugSay(ngx.var.request_uri.."-".."file attack with ext: "..ext) +-- end +-- end +-- end +-- end +-- return false +-- end -function set(list) - local set = {} - for _, l in ipairs(list) do - set[l] = true - end - return set -end +-- function set(list) +-- local set = {} +-- for _, l in ipairs(list) do +-- set[l] = true +-- end +-- return set +-- end -function checkArgs() - for _, rule in pairs(args_rules) do - local args = ngx.req.get_uri_args() - for key, val in pairs(args) do - if type(val) == 'table' then - if val ~= false then - data = table.concat(val, " ") - end - else - data = val - end - if data and type(data) ~= "boolean" and rule ~="" and ngx_match(unescape(data), rule, "isjo") then - log('GET', ngx.var.request_uri, "-", rule) - debugSay(ngx.var.request_uri.."-"..rule) - return true - end - end - end - return false -end + +-- function checkArgs() +-- for _, rule in pairs(args_rules) do +-- local args = ngx.req.get_uri_args() +-- for key, val in pairs(args) do +-- if type(val) == 'table' then +-- if val ~= false then +-- data = table.concat(val, " ") +-- end +-- else +-- data = val +-- end +-- if data and type(data) ~= "boolean" and rule ~="" and ngx_match(unescape(data), rule, "isjo") then +-- log('GET', ngx.var.request_uri, "-", rule) +-- debugSay(ngx.var.request_uri.."-"..rule) +-- return true +-- end +-- end +-- end +-- return false +-- end -- function url() @@ -188,35 +188,33 @@ end -- return false -- end --- function denycc() --- if CCDeny then --- local uri=ngx.var.uri --- CCcount=tonumber(string.match(CCrate,'(.*)/')) --- CCseconds=tonumber(string.match(CCrate,'/(.*)')) --- local token = getClientIp()..uri --- local limit = ngx.shared.limit --- local req,_ = limit:get(token) --- local ip = getClientIp() --- local block,_ = limit:get(ip) - --- if block then --- ngx.exit(503) --- end +function denyCC(cc_rate, cc_deny_seconds) + local uri = ngx.var.uri + cc_count = tonumber(string.match(cc_rate, '(.*)/')) + cc_seconds = tonumber(string.match(cc_rate, '/(.*)')) + local token = getClientIp()..uri + local limit = ngx.shared.limit + local req, _ = limit:get(token) + local ip = getClientIp() + local block, _ = limit:get(ip) + + if block then + ngx.exit(405) + end --- if req then --- if req > CCcount then --- limit:set(ip,1,DenySeconds) --- ngx.exit(503) --- return true --- else --- limit:incr(token,1) --- end --- else --- limit:set(token,1,CCseconds) --- end --- end --- return false --- end + if req then + if req > cc_count then + limit:set(ip, 1, cc_deny_seconds) + ngx.exit(405) + return false + else + limit:incr(token, 1) + end + else + limit:set(token, 1, cc_seconds) + end + return true +end -- function get_boundary() -- local header = get_headers()["content-type"] From db6eda926b8af16e117e1f0c939f531c735c5a51 Mon Sep 17 00:00:00 2001 From: ibuler Date: Sat, 18 Jun 2016 14:56:30 +0800 Subject: [PATCH 10/31] change --- config.lua | 2 +- init.lua | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/config.lua b/config.lua index 3a6b055..fc0749c 100644 --- a/config.lua +++ b/config.lua @@ -10,7 +10,7 @@ post_check = false black_file_ext = {"php", "jsp"} attack_log = false -attach_log_dir = "/usr/local/nginx/logs/hack/" +attach_log_dir = "/data/logs/waf/" redirect = false redirect_url = "http://www.baidu.com" diff --git a/init.lua b/init.lua index 47e701b..33ce253 100644 --- a/init.lua +++ b/init.lua @@ -1,4 +1,3 @@ --- require 'config' local match = string.match local ngx_match = ngx.re.match local unescape = ngx.unescape_uri @@ -199,13 +198,20 @@ function denyCC(cc_rate, cc_deny_seconds) local block, _ = limit:get(ip) if block then - ngx.exit(405) + if debug then + ngx.say('Deny by waf.') + return false + elseif cc_redirect then + ngx.redirect(cc_redirect_url) + else + ngx.exit(404) + end end if req then if req > cc_count then limit:set(ip, 1, cc_deny_seconds) - ngx.exit(405) + ngx.exit(404) return false else limit:incr(token, 1) From 4eb8d59b833773f86631be2a598e588fe2d913ed Mon Sep 17 00:00:00 2001 From: ibuler Date: Sat, 18 Jun 2016 15:03:28 +0800 Subject: [PATCH 11/31] =?UTF-8?q?=E6=8B=86=E5=88=86=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- access.lua | 5 +++++ entry.lua | 10 ++++++++++ 2 files changed, 15 insertions(+) create mode 100644 access.lua create mode 100644 entry.lua diff --git a/access.lua b/access.lua new file mode 100644 index 0000000..509701d --- /dev/null +++ b/access.lua @@ -0,0 +1,5 @@ +if cc_deny then + denyCC(cc_rate, cc_deny_seconds) +else + return +end diff --git a/entry.lua b/entry.lua new file mode 100644 index 0000000..1aedbd7 --- /dev/null +++ b/entry.lua @@ -0,0 +1,10 @@ +--------- Global default config ------- +require 'config' +--------- Local config setting -------- +cc_deny = false +cc_rate = '10/60' + +--------- Init project ---------------- +require 'init' +--------- Access control limit -------- +require '' From 4787ba906002fc34d7e746c6d0a4bbba8086053d Mon Sep 17 00:00:00 2001 From: ibuler Date: Sat, 18 Jun 2016 18:26:27 +0800 Subject: [PATCH 12/31] modify --- config.lua | 7 ++--- entry.lua | 7 +++-- init.lua | 91 +++++++++++++++++++++--------------------------------- 3 files changed, 43 insertions(+), 62 deletions(-) diff --git a/config.lua b/config.lua index fc0749c..bd3a652 100644 --- a/config.lua +++ b/config.lua @@ -14,11 +14,10 @@ attach_log_dir = "/data/logs/waf/" redirect = false redirect_url = "http://www.baidu.com" -ip_white_list = {"127.0.0.1", "172.16.1.*"} -ip_black_list = {"1.0.0.1", "172.16.1.*"} +ip_check = false +ip_white_list = {"127.0.0.1", "172.16.1"} +ip_black_list = {"1.0.0.1", "172.16.1"} cc_deny = false cc_rate = "100/60" cc_deny_seconds = "600" -cc_redirect = false -cc_redirect_url = redirect_url diff --git a/entry.lua b/entry.lua index 1aedbd7..7516e43 100644 --- a/entry.lua +++ b/entry.lua @@ -1,10 +1,13 @@ --------- Global default config ------- require 'config' --------- Local config setting -------- -cc_deny = false +cc_deny = true cc_rate = '10/60' --------- Init project ---------------- require 'init' --------- Access control limit -------- -require '' +if cc_deny and denyCC(cc_rate, cc_deny_seconds) then +elseif ip_check and (whiteIP() or blackIP()) then +else return +end diff --git a/init.lua b/init.lua index 33ce253..06b362b 100644 --- a/init.lua +++ b/init.lua @@ -193,16 +193,15 @@ function denyCC(cc_rate, cc_deny_seconds) cc_seconds = tonumber(string.match(cc_rate, '/(.*)')) local token = getClientIp()..uri local limit = ngx.shared.limit - local req, _ = limit:get(token) + local req, _ = limit:get(token) -- 127.0.0.1_/price/v1.0: 10 local ip = getClientIp() - local block, _ = limit:get(ip) + local block, _ = limit:get(ip) -- 127.0.0.1: 1 if block then if debug then ngx.say('Deny by waf.') + ngx.exit('200') return false - elseif cc_redirect then - ngx.redirect(cc_redirect_url) else ngx.exit(404) end @@ -219,7 +218,7 @@ function denyCC(cc_rate, cc_deny_seconds) else limit:set(token, 1, cc_seconds) end - return true + return false end -- function get_boundary() @@ -252,56 +251,36 @@ end -- return result -- end --- function innet(ip, network) --- local star = '' --- for i in string.gmatch(network, '%*') do --- star = star..i --- end - --- local ip = string.split(ip, '%.') --- local network = string.split(network, '%.') --- if ip == nil or network == nil then --- return false --- end - --- local ip_prefix = {} --- local network_prefix = {} --- for i=1, 4-string.len(star) do --- ip_prefix[i] = ip[i] --- network_prefix[i] = network[i] --- end - --- ip_prefix = table.concat(ip_prefix, '.') --- network_prefix = table.concat(network_prefix, '.') - --- if ip_prefix == network_prefix then --- return true --- else --- return false --- end --- end +function innet(ip, network) + matched = string.match(ip, network) + if match then + return true + else + return false + end +end --- function whiteip() --- if next(ipWhitelist) ~= nil then --- ip = getClientIp() --- for _,wip in pairs(ipWhitelist) do --- if ip == wip or innet(ip, wip) then --- return true --- end --- end --- end --- return false --- end +function whiteIP() + if next(ip_white_list) ~= nil then + ip = getClientIp() + for _, wip in pairs(ip_white_list) do + if ip == wip or innet(ip, wip) then + return true + end + end + end + return false +end --- function blockip() --- if next(ipBlocklist) ~= nil then --- ip = getClientIp() --- for _,bip in pairs(ipBlocklist) do --- if ip == bip or ip=="0.0.0.0" or innet(ip, bip) then --- ngx.exit(403) --- return true --- end --- end --- end --- return false --- end +function blackIP() + if next(ip_black_list) ~= nil then + ip = getClientIp() + for _, bip in pairs(ip_black_list) do + if ip == bip or ip == "0.0.0.0" or innet(ip, bip) then + ngx.exit(403) + return true + end + end + end + return false +end From 4d96926d19449a5ab424a3cfb839c95ec8bf5578 Mon Sep 17 00:00:00 2001 From: ibuler Date: Sat, 18 Jun 2016 19:09:10 +0800 Subject: [PATCH 13/31] sdf --- init.lua | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/init.lua b/init.lua index 06b362b..ea9ed3d 100644 --- a/init.lua +++ b/init.lua @@ -28,15 +28,15 @@ function log(method, url, data, tag) if attack_log then local realIp = getClientIp() local ua = ngx.var.http_user_agent - local servername=ngx.var.server_name - local time=ngx.localtime() - if ua then + local servername = ngx.var.server_name + local time = ngx.localtime() + if ua then line = realIp.." ["..time.."] \""..method.." "..servername..url.."\" \""..data.."\" \""..ua.."\" \""..tag.."\"\n" else line = realIp.." ["..time.."] \""..method.." "..servername..url.."\" \""..data.."\" - \""..tag.."\"\n" end local filename = logpath..'/'..servername.."_"..ngx.today().."_sec.log" - write(filename,line) + write(filename, line) end end @@ -201,7 +201,7 @@ function denyCC(cc_rate, cc_deny_seconds) if debug then ngx.say('Deny by waf.') ngx.exit('200') - return false + return true else ngx.exit(404) end @@ -211,7 +211,7 @@ function denyCC(cc_rate, cc_deny_seconds) if req > cc_count then limit:set(ip, 1, cc_deny_seconds) ngx.exit(404) - return false + return true else limit:incr(token, 1) end @@ -252,7 +252,7 @@ end -- end function innet(ip, network) - matched = string.match(ip, network) + matched = string.match(network, ip) if match then return true else From 7890ae1c44bee43e763136dc552be6e686df0aa8 Mon Sep 17 00:00:00 2001 From: ibuler Date: Sat, 18 Jun 2016 19:11:28 +0800 Subject: [PATCH 14/31] sdf --- init.lua | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/init.lua b/init.lua index ea9ed3d..b308f25 100644 --- a/init.lua +++ b/init.lua @@ -265,8 +265,11 @@ function whiteIP() ip = getClientIp() for _, wip in pairs(ip_white_list) do if ip == wip or innet(ip, wip) then - return true - end ++ if debug then ++ ngx.say(ip.."in white list
") ++ end + return true + end end end return false @@ -277,6 +280,9 @@ function blackIP() ip = getClientIp() for _, bip in pairs(ip_black_list) do if ip == bip or ip == "0.0.0.0" or innet(ip, bip) then + if debug then ++ ngx.say(ip.."in black list
") ++ end ngx.exit(403) return true end From 48335cb152e06ccbef8b24726f1553c242b952f6 Mon Sep 17 00:00:00 2001 From: ibuler Date: Sat, 18 Jun 2016 19:13:41 +0800 Subject: [PATCH 15/31] sdf --- init.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/init.lua b/init.lua index b308f25..c747509 100644 --- a/init.lua +++ b/init.lua @@ -265,9 +265,9 @@ function whiteIP() ip = getClientIp() for _, wip in pairs(ip_white_list) do if ip == wip or innet(ip, wip) then -+ if debug then -+ ngx.say(ip.."in white list
") -+ end + if debug then + ngx.say(ip.."in white list
") + end return true end end @@ -281,8 +281,8 @@ function blackIP() for _, bip in pairs(ip_black_list) do if ip == bip or ip == "0.0.0.0" or innet(ip, bip) then if debug then -+ ngx.say(ip.."in black list
") -+ end + ngx.say(ip.."in black list
") + end ngx.exit(403) return true end From 73dc10d82731233637ca85f4dc35b077abc1c871 Mon Sep 17 00:00:00 2001 From: ibuler Date: Sat, 18 Jun 2016 19:18:00 +0800 Subject: [PATCH 16/31] sdf --- entry.lua | 4 ++-- init.lua | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/entry.lua b/entry.lua index 7516e43..58d5392 100644 --- a/entry.lua +++ b/entry.lua @@ -7,7 +7,7 @@ cc_rate = '10/60' --------- Init project ---------------- require 'init' --------- Access control limit -------- -if cc_deny and denyCC(cc_rate, cc_deny_seconds) then -elseif ip_check and (whiteIP() or blackIP()) then +if ip_check and (whiteIP() or blackIP()) then +elseif cc_deny and denyCC() then else return end diff --git a/init.lua b/init.lua index c747509..dc85d9b 100644 --- a/init.lua +++ b/init.lua @@ -187,7 +187,7 @@ end -- return false -- end -function denyCC(cc_rate, cc_deny_seconds) +function denyCC() local uri = ngx.var.uri cc_count = tonumber(string.match(cc_rate, '(.*)/')) cc_seconds = tonumber(string.match(cc_rate, '/(.*)')) @@ -282,7 +282,7 @@ function blackIP() if ip == bip or ip == "0.0.0.0" or innet(ip, bip) then if debug then ngx.say(ip.."in black list
") - end + end ngx.exit(403) return true end From 6d24afc4c66e5ee674a9d293692267b4495ff633 Mon Sep 17 00:00:00 2001 From: ibuler Date: Sat, 18 Jun 2016 19:19:25 +0800 Subject: [PATCH 17/31] sdf --- entry.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/entry.lua b/entry.lua index 58d5392..9f96f5f 100644 --- a/entry.lua +++ b/entry.lua @@ -1,8 +1,13 @@ --------- Global default config ------- require 'config' --------- Local config setting -------- -cc_deny = true +debug = true + +cc_deny = false cc_rate = '10/60' +ip_check = true +ip_write_list = {} +ip_black_list = {} --------- Init project ---------------- require 'init' From 00a50e248dca6fd8e38e07f3fff2ed7c3b27e8e7 Mon Sep 17 00:00:00 2001 From: ibuler Date: Sat, 18 Jun 2016 19:30:09 +0800 Subject: [PATCH 18/31] sdf --- entry.lua | 2 +- init.lua | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/entry.lua b/entry.lua index 9f96f5f..9c4c026 100644 --- a/entry.lua +++ b/entry.lua @@ -6,7 +6,7 @@ debug = true cc_deny = false cc_rate = '10/60' ip_check = true -ip_write_list = {} +ip_white_list = {} ip_black_list = {} --------- Init project ---------------- diff --git a/init.lua b/init.lua index dc85d9b..a82ed81 100644 --- a/init.lua +++ b/init.lua @@ -266,7 +266,7 @@ function whiteIP() for _, wip in pairs(ip_white_list) do if ip == wip or innet(ip, wip) then if debug then - ngx.say(ip.."in white list
") + ngx.say(ip.." in white list
") end return true end @@ -281,7 +281,7 @@ function blackIP() for _, bip in pairs(ip_black_list) do if ip == bip or ip == "0.0.0.0" or innet(ip, bip) then if debug then - ngx.say(ip.."in black list
") + ngx.say(ip.." in black list
") end ngx.exit(403) return true From 3bd4970d3797836aefb6fcf486e18fb77af35bed Mon Sep 17 00:00:00 2001 From: ibuler Date: Sun, 19 Jun 2016 10:24:53 +0800 Subject: [PATCH 19/31] Modify innet function --- init.lua | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/init.lua b/init.lua index a82ed81..c8bbca0 100644 --- a/init.lua +++ b/init.lua @@ -252,8 +252,28 @@ end -- end function innet(ip, network) - matched = string.match(network, ip) - if match then + local star = '' + for i in string.gmatch(network, '%*') do + star = star..i + end + + local ip = string.split(ip, '%.') + local network = string.split(network, '%.') + if ip == nil or network == nil then + return false + end + + local ip_prefix = {} + local network_prefix = {} + for i=1, 4-string.len(star) do + ip_prefix[i] = ip[i] + network_prefix[i] = network[i] + end + + ip_prefix = table.concat(ip_prefix, '.') + network_prefix = table.concat(network_prefix, '.') + + if ip_prefix == network_prefix then return true else return false From 3331d86e988fdba8a71013d87823a76dd754214a Mon Sep 17 00:00:00 2001 From: ibuler Date: Sun, 19 Jun 2016 10:27:12 +0800 Subject: [PATCH 20/31] Modify config --- config.lua | 4 +-- waf.lua | 86 ------------------------------------------------------ 2 files changed, 2 insertions(+), 88 deletions(-) delete mode 100644 waf.lua diff --git a/config.lua b/config.lua index bd3a652..237a0fb 100644 --- a/config.lua +++ b/config.lua @@ -15,8 +15,8 @@ attach_log_dir = "/data/logs/waf/" redirect = false redirect_url = "http://www.baidu.com" ip_check = false -ip_white_list = {"127.0.0.1", "172.16.1"} -ip_black_list = {"1.0.0.1", "172.16.1"} +ip_white_list = {} -- {'192.168.1.*', '127.0.0.1'} +ip_black_list = {} -- {'0.0.0.0', '106.2.34.29'} cc_deny = false cc_rate = "100/60" diff --git a/waf.lua b/waf.lua deleted file mode 100644 index f35e95e..0000000 --- a/waf.lua +++ /dev/null @@ -1,86 +0,0 @@ -local content_length=tonumber(ngx.req.get_headers()['content-length']) -local method=ngx.req.get_method() -local ngxmatch=ngx.re.match - -if whiteip() then -elseif blockip() then -elseif denycc() then -elseif ngx.var.http_Acunetix_Aspect then - ngx.exit(444) -elseif ngx.var.http_X_Scan_Memo then - ngx.exit(444) -elseif whiteurl() then -elseif ua() then -elseif url() then -elseif args() then -elseif cookie() then -elseif PostCheck then - if method=="POST" then - local boundary = get_boundary() - if boundary then - local len = string.len - local sock, err = ngx.req.socket() - if not sock then - return - end - ngx.req.init_body(128 * 1024) - sock:settimeout(0) - local content_length = nil - content_length=tonumber(ngx.req.get_headers()['content-length']) - local chunk_size = 4096 - if content_length < chunk_size then - chunk_size = content_length - end - local size = 0 - while size < content_length do - local data, err, partial = sock:receive(chunk_size) - data = data or partial - if not data then - return - end - ngx.req.append_body(data) - if body(data) then - return true - end - size = size + len(data) - local m = ngxmatch(data,[[Content-Disposition: form-data;(.+)filename="(.+)\\.(.*)"]],'ijo') - if m then - fileExtCheck(m[3]) - filetranslate = true - else - if ngxmatch(data,"Content-Disposition:",'isjo') then - filetranslate = false - end - if filetranslate==false then - if body(data) then - return true - end - end - end - local less = content_length - size - if less < chunk_size then - chunk_size = less - end - end - ngx.req.finish_body() - else - ngx.req.read_body() - local args = ngx.req.get_post_args() - if not args then - return - end - for key, val in pairs(args) do - if type(val) == "table" then - data=table.concat(val, ", ") - else - data=val - end - if data and type(data) ~= "boolean" and body(data) then - return true - end - end - end - end -else - return -end From fb0f32b9ecdd79f4bd61e3894eaa21a7b8d8041a Mon Sep 17 00:00:00 2001 From: ibuler Date: Sun, 19 Jun 2016 10:50:49 +0800 Subject: [PATCH 21/31] add split --- init.lua | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/init.lua b/init.lua index c8bbca0..e216ecc 100644 --- a/init.lua +++ b/init.lua @@ -239,17 +239,18 @@ end -- return match(header, ";%s*boundary=([^\",;]+)") -- end --- function string.split(str, delimiter) --- if str==nil or str=='' or delimiter==nil then --- return nil --- end +function string.split(str, delimiter) + if str==nil or str=='' or delimiter==nil then + return nil + end + + local result = {} + for match in (str..delimiter):gmatch("(.-)"..delimiter) do + table.insert(result, match) + end + return result +end --- local result = {} --- for match in (str..delimiter):gmatch("(.-)"..delimiter) do --- table.insert(result, match) --- end --- return result --- end function innet(ip, network) local star = '' From 6c55cdb9439da43c1690333b80c011211447ead3 Mon Sep 17 00:00:00 2001 From: ibuler Date: Sun, 19 Jun 2016 10:57:31 +0800 Subject: [PATCH 22/31] comment some unuse conifg --- config.lua | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/config.lua b/config.lua index 237a0fb..67d330c 100644 --- a/config.lua +++ b/config.lua @@ -1,19 +1,19 @@ debug = false -rule_path = "/data/server/nginx/conf/waf/wafconf/" -url_check = false -url_write_check = false -args_check = false -ua_check = false -ua_write_check = false -cookie_check = false -post_check = false +-- rule_path = "/data/server/nginx/conf/waf/wafconf/" +-- url_check = false +-- url_write_check = false +-- args_check = false +-- ua_check = false +-- ua_write_check = false +-- cookie_check = false +-- post_check = false -black_file_ext = {"php", "jsp"} -attack_log = false -attach_log_dir = "/data/logs/waf/" +-- black_file_ext = {"php", "jsp"} +-- attack_log = false +-- attach_log_dir = "/data/logs/waf/" -redirect = false -redirect_url = "http://www.baidu.com" +-- redirect = false +-- redirect_url = "http://www.baidu.com" ip_check = false ip_white_list = {} -- {'192.168.1.*', '127.0.0.1'} ip_black_list = {} -- {'0.0.0.0', '106.2.34.29'} From 6ef88ea3987aaf28806e19a175fe0fef87fee192 Mon Sep 17 00:00:00 2001 From: ibuler Date: Sun, 19 Jun 2016 11:20:15 +0800 Subject: [PATCH 23/31] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=B2=A1=E7=94=A8?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 151 +++++++---------------------------------------------- access.lua | 5 -- install.sh | 47 ----------------- 3 files changed, 19 insertions(+), 184 deletions(-) delete mode 100644 access.lua delete mode 100644 install.sh diff --git a/README.md b/README.md index 69fbff3..a49a8a5 100644 --- a/README.md +++ b/README.md @@ -1,138 +1,25 @@ -##ngx_lua_waf +## ngx_lua_waf +基于 loveshell [nginx-lua-waf](https://github.com/loveshell/ngx_lua_waf)更改 -ngx_lua_waf是我刚入职趣游时候开发的一个基于ngx_lua的web应用防火墙。 +### 使用方法: +1. nginx安装lua模块,不再详述 +2. nginx.conf 添加参数 + lua_package_path /data/server/nginx/conf/waf/?.lua; # 模块位置 + lua_shared_dict limit 10m; # 设置lua使用内存, 根据访问量设置合适值 +3. location或server设置访问控制 + access_by_lua_file /data/server/nginx/conf/waf/entry.lua; # 可以copy一份到不同的配置中,单独修改其配置文件 -代码很简单,开发初衷主要是使用简单,高性能和轻量级。 +## 文件说明 +- config.lua 默认配置文件 +- entry.lua access控制入口样例文件 +- init.lua 函数所在文件,都会调用该文件 +- wafconf 暂时没有使用,将来开发继续完成 -现在开源出来,遵从MIT许可协议。其中包含我们的过滤规则。如果大家有什么建议和想fa,欢迎和我一起完善。 -###用途: - - 防止sql注入,本地包含,部分溢出,fuzzing测试,xss,SSRF等web攻击 - 防止svn/备份之类文件泄漏 - 防止ApacheBench之类压力测试工具的攻击 - 屏蔽常见的扫描黑客工具,扫描器 - 屏蔽异常的网络请求 - 屏蔽图片附件类目录php执行权限 - 防止webshell上传 +### 参数说明 +- debug: 调试阶段开始debug,显示debug信息 +- cc_deny: 开启cc_deny,控制访问量 +- cc_rate: 10/60 意思为 60s内访问10次,超过频率会被block掉 +- cc_deny_seconds: 达到阈值后,禁止访问的时间 -###推荐安装: -推荐使用lujit2.1做lua支持 - -ngx_lua如果是0.9.2以上版本,建议正则过滤函数改为ngx.re.find,匹配效率会提高三倍左右。 - - -###使用说明: - -nginx安装路径假设为:/usr/local/nginx/conf/ - -把ngx_lua_waf下载到conf目录下,解压命名为waf - -在nginx.conf的http段添加 - - lua_package_path "/usr/local/nginx/conf/waf/?.lua"; - lua_shared_dict limit 10m; - init_by_lua_file /usr/local/nginx/conf/waf/init.lua; - access_by_lua_file /usr/local/nginx/conf/waf/waf.lua; - -配置config.lua里的waf规则目录(一般在waf/conf/目录下) - - RulePath = "/usr/local/nginx/conf/waf/wafconf/" - -绝对路径如有变动,需对应修改 - -然后重启nginx即可 - - -###配置文件详细说明: - - RulePath = "/usr/local/nginx/conf/waf/wafconf/" - --规则存放目录 - attacklog = "off" - --是否开启攻击信息记录,需要配置logdir - logdir = "/usr/local/nginx/logs/hack/" - --log存储目录,该目录需要用户自己新建,切需要nginx用户的可写权限 - UrlDeny="on" - --是否拦截url访问 - Redirect="on" - --是否拦截后重定向 - CookieMatch = "on" - --是否拦截cookie攻击 - postMatch = "on" - --是否拦截post攻击 - whiteModule = "on" - --是否开启URL白名单 - black_fileExt={"php","jsp"} - --填写可上传文件后缀类型 - ipWhitelist={"127.0.0.1"} - --ip白名单,多个ip用逗号分隔 - ipBlocklist={"1.0.0.1"} - --ip黑名单,多个ip用逗号分隔 - CCDeny="on" - --是否开启拦截cc攻击(需要nginx.conf的http段增加lua_shared_dict limit 10m;) - CCrate = "100/60" - --设置cc攻击频率,单位为秒. - --默认1分钟同一个IP只能请求同一个地址100次 - html=[[Please go away~~]] - --警告内容,可在中括号内自定义 - 备注:不要乱动双引号,区分大小写 - -###检查规则是否生效 - -部署完毕可以尝试如下命令: - - curl http://xxxx/test.php?id=../etc/passwd - 返回"Please go away~~"字样,说明规则生效。 - -注意:默认,本机在白名单不过滤,可自行调整config.lua配置 - - -###效果图如下: - -![sec](http://i.imgur.com/wTgOcm2.png) - -![sec](http://i.imgur.com/DqU30au.png) - -###规则更新: - -考虑到正则的缓存问题,动态规则会影响性能,所以暂没用共享内存字典和redis之类东西做动态管理。 - -规则更新可以把规则文件放置到其他服务器,通过crontab任务定时下载来更新规则,nginx reload即可生效。以保障ngx lua waf的高性能。 - -只记录过滤日志,不开启过滤,在代码里在check前面加上--注释即可,如果需要过滤,反之 - -###一些说明: - - 过滤规则在wafconf下,可根据需求自行调整,每条规则需换行,或者用|分割 - - global是全局过滤文件,里面的规则对post和get都过滤 - get是只在get请求过滤的规则 - post是只在post请求过滤的规则 - whitelist是白名单,里面的url匹配到不做过滤 - user-agent是对user-agent的过滤规则 - - - 默认开启了get和post过滤,需要开启cookie过滤的,编辑waf.lua取消部分--注释即可 - - 日志文件名称格式如下:虚拟主机名_sec.log - - -## Copyright - - - - - - - - - - - - - - -
Weibo神奇的魔法师
Forumhttp://bbs.linuxtone.org/
CopyrightCopyright (c) 2013- loveshell
LicenseMIT License
- -感谢ngx_lua模块的开发者[@agentzh](https://github.com/agentzh/),春哥是我所接触过开源精神最好的人 diff --git a/access.lua b/access.lua deleted file mode 100644 index 509701d..0000000 --- a/access.lua +++ /dev/null @@ -1,5 +0,0 @@ -if cc_deny then - denyCC(cc_rate, cc_deny_seconds) -else - return -end diff --git a/install.sh b/install.sh deleted file mode 100644 index 40f187c..0000000 --- a/install.sh +++ /dev/null @@ -1,47 +0,0 @@ -mkdir -p /data/src -cd /data/src -if [ ! -x "LuaJIT-2.0.0.tar.gz" ]; then -wget http://luajit.org/download/LuaJIT-2.0.0.tar.gz -fi -tar zxvf LuaJIT-2.0.0.tar.gz -cd LuaJIT-2.0.0 -make -make install PREFIX=/usr/local/lj2 -ln -s /usr/local/lj2/lib/libluajit-5.1.so.2 /lib64/ -cd /data/src -if [ ! -x "v0.2.17rc2.zip" ]; then -wget https://github.com/simpl/ngx_devel_kit/archive/v0.2.17rc2.zip -fi -unzip v0.2.17rc2 -if [ ! -x "v0.7.4.zip" ]; then -wget https://github.com/chaoslawful/lua-nginx-module/archive/v0.7.4.zip -fi -unzip v0.7.4 -cd /data/src -if [ ! -x "pcre-8.10.tar.gz" ]; then -wget http://blog.s135.com/soft/linux/nginx_php/pcre/pcre-8.10.tar.gz -fi -tar zxvf pcre-8.10.tar.gz -cd pcre-8.10/ -./configure -make && make install -cd .. -if [ ! -x "nginx-1.2.4.tar.gz" ]; then -wget 'http://nginx.org/download/nginx-1.2.4.tar.gz' -fi -tar -xzvf nginx-1.2.4.tar.gz -cd nginx-1.2.4/ -export LUAJIT_LIB=/usr/local/lj2/lib/ -export LUAJIT_INC=/usr/local/lj2/include/luajit-2.0/ -./configure --user=daemon --group=daemon --prefix=/usr/local/nginx/ --with-http_stub_status_module --with-http_sub_module --with-http_gzip_static_module --without-mail_pop3_module --without-mail_imap_module --without-mail_smtp_module --add-module=../ngx_devel_kit-0.2.17rc2/ --add-module=../lua-nginx-module-0.7.4/ -make -j8 -make install -#rm -rf /data/src -cd /usr/local/nginx/conf/ -wget https://github.com/loveshell/ngx_lua_waf/archive/master.zip --no-check-certificate -unzip master.zip -mv ngx_lua_waf-master/* /usr/local/nginx/conf/ -rm -rf ngx_lua_waf-master -rm -rf /data/src -mkdir -p /data/logs/hack -chmod -R 775 /data/logs/hack From e083a1a7da9cadf85108b834ce7a97400387bc94 Mon Sep 17 00:00:00 2001 From: ibuler Date: Sun, 19 Jun 2016 11:21:59 +0800 Subject: [PATCH 24/31] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=B2=A1=E7=94=A8?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index a49a8a5..27bf878 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,9 @@ ### 使用方法: 1. nginx安装lua模块,不再详述 +2. 下载模块 + cd /data/server/nginx/conf + git clone https://github.com/ibuler/ngx_lua_waf.git waf 2. nginx.conf 添加参数 lua_package_path /data/server/nginx/conf/waf/?.lua; # 模块位置 lua_shared_dict limit 10m; # 设置lua使用内存, 根据访问量设置合适值 From 8e4fc1657fb7b396f3a7634199e2ede96d765d58 Mon Sep 17 00:00:00 2001 From: ibuler Date: Sun, 19 Jun 2016 11:49:13 +0800 Subject: [PATCH 25/31] =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- entry.lua | 4 ++-- init.lua | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/entry.lua b/entry.lua index 9c4c026..333f9d9 100644 --- a/entry.lua +++ b/entry.lua @@ -12,7 +12,7 @@ ip_black_list = {} --------- Init project ---------------- require 'init' --------- Access control limit -------- -if ip_check and (whiteIP() or blackIP()) then -elseif cc_deny and denyCC() then +if ip_check and (whiteIP(ip_white_list) or blackIP(ip_black_list)) then +elseif cc_deny and denyCC(cc_rate, cc_deny_seconds) then else return end diff --git a/init.lua b/init.lua index e216ecc..d5a400c 100644 --- a/init.lua +++ b/init.lua @@ -62,7 +62,7 @@ end -- cookie_rules = readRule('cookie') -function debugSay(msg) +function debugSay(msg, debug) if debug then ngx.header.content_type = "text/html" ngx.status = ngx.HTTP_FORBIDDEN @@ -187,7 +187,7 @@ end -- return false -- end -function denyCC() +function denyCC(cc_rate, cc_deny_seconds) local uri = ngx.var.uri cc_count = tonumber(string.match(cc_rate, '(.*)/')) cc_seconds = tonumber(string.match(cc_rate, '/(.*)')) @@ -281,7 +281,7 @@ function innet(ip, network) end end -function whiteIP() +function whiteIP(ip_white_list, debug) if next(ip_white_list) ~= nil then ip = getClientIp() for _, wip in pairs(ip_white_list) do @@ -296,7 +296,7 @@ function whiteIP() return false end -function blackIP() +function blackIP(ip_black_list, debug) if next(ip_black_list) ~= nil then ip = getClientIp() for _, bip in pairs(ip_black_list) do From 41a6d8cec91b89d06f3e24aad10d8156c9f0222f Mon Sep 17 00:00:00 2001 From: ibuler Date: Sun, 19 Jun 2016 11:50:57 +0800 Subject: [PATCH 26/31] =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- entry.lua | 4 ++-- init.lua | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/entry.lua b/entry.lua index 333f9d9..f4aaa4b 100644 --- a/entry.lua +++ b/entry.lua @@ -12,7 +12,7 @@ ip_black_list = {} --------- Init project ---------------- require 'init' --------- Access control limit -------- -if ip_check and (whiteIP(ip_white_list) or blackIP(ip_black_list)) then -elseif cc_deny and denyCC(cc_rate, cc_deny_seconds) then +if ip_check and (whiteIP(ip_white_list, debug) or blackIP(ip_black_list, debug)) then +elseif cc_deny and denyCC(cc_rate, cc_deny_seconds, debug) then else return end diff --git a/init.lua b/init.lua index d5a400c..7853b02 100644 --- a/init.lua +++ b/init.lua @@ -187,7 +187,7 @@ end -- return false -- end -function denyCC(cc_rate, cc_deny_seconds) +function denyCC(cc_rate, cc_deny_seconds, debug) local uri = ngx.var.uri cc_count = tonumber(string.match(cc_rate, '(.*)/')) cc_seconds = tonumber(string.match(cc_rate, '/(.*)')) From b56499f7e28f359f94c232216ca42d2f5f286980 Mon Sep 17 00:00:00 2001 From: ibuler Date: Sat, 24 Sep 2016 17:46:33 +0800 Subject: [PATCH 27/31] Finish ip block --- .idea/inspectionProfiles/Project_Default.xml | 14 ++ .../inspectionProfiles/profiles_settings.xml | 7 + .idea/misc.xml | 14 ++ .idea/modules.xml | 8 + .idea/ngx_lua_waf.iml | 11 + .idea/vcs.xml | 6 + .idea/workspace.xml | 183 ++++++++++++++++ config.lua | 43 ++-- core.lua | 95 ++++++++ iputils.lua | 207 ++++++++++++++++++ README.md => old/README.md | 0 old/config.lua | 23 ++ entry.lua => old/entry.lua | 2 - init.lua => old/init.lua | 0 old/logger.lua | 0 old/waf.lua | 0 {wafconf => old/wafconf}/args | 0 {wafconf => old/wafconf}/cookie | 0 {wafconf => old/wafconf}/post | 0 {wafconf => old/wafconf}/url | 0 {wafconf => old/wafconf}/user_agent | 0 {wafconf => old/wafconf}/white_url | 0 test.lua | 41 ++++ test2.lua | 31 +++ 24 files changed, 663 insertions(+), 22 deletions(-) create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/ngx_lua_waf.iml create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml create mode 100644 core.lua create mode 100644 iputils.lua rename README.md => old/README.md (100%) create mode 100644 old/config.lua rename entry.lua => old/entry.lua (88%) rename init.lua => old/init.lua (100%) create mode 100644 old/logger.lua create mode 100644 old/waf.lua rename {wafconf => old/wafconf}/args (100%) rename {wafconf => old/wafconf}/cookie (100%) rename {wafconf => old/wafconf}/post (100%) rename {wafconf => old/wafconf}/url (100%) rename {wafconf => old/wafconf}/user_agent (100%) rename {wafconf => old/wafconf}/white_url (100%) create mode 100644 test.lua create mode 100644 test2.lua diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..4dca92b --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,14 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..3b31283 --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..9e6e353 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..22f51ac --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/ngx_lua_waf.iml b/.idea/ngx_lua_waf.iml new file mode 100644 index 0000000..6711606 --- /dev/null +++ b/.idea/ngx_lua_waf.iml @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..7d4efb8 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,183 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + DEFINITION_ORDER + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1474616676553 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/config.lua b/config.lua index 67d330c..ee3056b 100644 --- a/config.lua +++ b/config.lua @@ -1,23 +1,26 @@ -debug = false --- rule_path = "/data/server/nginx/conf/waf/wafconf/" --- url_check = false --- url_write_check = false --- args_check = false --- ua_check = false --- ua_write_check = false --- cookie_check = false --- post_check = false +-- +-- Created by IntelliJ IDEA. +-- User: guang +-- Date: 16/9/23 +-- Time: 下午4:28 +-- To change this template use File | Settings | File Templates. +-- --- black_file_ext = {"php", "jsp"} --- attack_log = false --- attach_log_dir = "/data/logs/waf/" +local _M = {} +_M.version = '0.1.0' --- redirect = false --- redirect_url = "http://www.baidu.com" -ip_check = false -ip_white_list = {} -- {'192.168.1.*', '127.0.0.1'} -ip_black_list = {} -- {'0.0.0.0', '106.2.34.29'} -cc_deny = false -cc_rate = "100/60" -cc_deny_seconds = "600" +_M.defaults = { + debug = true, + active = false, + cc_deny = true, + cc_rate = "100/600", + cc_deny_seconds = 600, + cc_deny_code = 404, + log_path = "/tmp/nginx_waf.log", + ip_check= true, + ip_white_list = nil, + ip_black_list = nil, +} + +return _M diff --git a/core.lua b/core.lua new file mode 100644 index 0000000..590992d --- /dev/null +++ b/core.lua @@ -0,0 +1,95 @@ +-- +-- Created by IntelliJ IDEA. +-- User: guang +-- Date: 16/9/22 +-- Time: 下午7:13 +-- To change this template use File | Settings | File Templates. +-- + + +local _M = {} +_M.version = '0.1.0' +log_inited = {} + +local get_headers = ngx.req.get_headers +local config = require "config" +local mt = {__index=_M } + +local function get_client_ip() + local ip = get_headers()["X-Real-IP"] + if ip == nil then + ip = ngx.var.remote_addr + end + + if ip == nil then + ip = "unkown" + end + return ip +end + +function _M.table_copy(orig_table) + local copy = {} + + for k, v in pairs(orig_table) do + if type(v) ~= "table" then + copy[k] = v + else + copy[k] = _M.table_copy(v) + end + end + return copy +end + +function _M.new(self, name) + local t = {} + t["name"] = name + t["config"] = _M.table_copy(config.defaults) + return setmetatable(t, mt) +end + +function _M.set_option(self, key, value) + self["config"][key] = value +end + +function _M.deny_cc(self) + local uri = ngx.var.uri + local max_visit = tonumber(string.match(self.config.cc_rate, '(.*)/')) + local count_period = tonumber(string.match(self.config.cc_rate, '/(.*)')) + local ip = get_client_ip() + + local token = ip..":"..uri + local limit = ngx.shared.limit + local req, _ = limit:get(token) + + if req then + if req > max_visit then + ngx.exit(self.config.cc_deny_code) + return true + elseif req == max_visit then + self:log("[Block] " .. token) + limit:incr(token, 1) + else + limit:incr(token, 1) + end + else + limit:set(token, 1, count_period) + end +end + +function _M.log(self, msg) + if log_inited[self.config.log_path] == nil then + log_inited[self.config.log_path] = io.open(self.config.log_path, 'ab') + end + self.fd = log_inited[self.config.log_path] + + self.fd:write(msg .. '\n') + self.fd:flush() +end + +function _M.run(self) + ngx.log(ngx.WARN, 'Start running waf') + if self.config.cc_deny and self:deny_cc() then + end +end + +return _M diff --git a/iputils.lua b/iputils.lua new file mode 100644 index 0000000..e5d1dd2 --- /dev/null +++ b/iputils.lua @@ -0,0 +1,207 @@ +local ipairs, tonumber, tostring, type = ipairs, tonumber, tostring, type +local bit = require("bit") +local tobit = bit.tobit +local lshift = bit.lshift +local band = bit.band +local bor = bit.bor +local xor = bit.bxor +local byte = string.byte +local str_find = string.find +local str_sub = string.sub + +local lrucache = nil + +local _M = { + _VERSION = '0.02', +} + +local mt = { __index = _M } + + +-- Precompute binary subnet masks... +local bin_masks = {} +for i=1,32 do + bin_masks[tostring(i)] = lshift(tobit((2^i)-1), 32-i) +end +-- ... and their inverted counterparts +local bin_inverted_masks = {} +for i=1,32 do + local i = tostring(i) + bin_inverted_masks[i] = xor(bin_masks[i], bin_masks["32"]) +end + +local log_err +if ngx then + log_err = function(...) + ngx.log(ngx.ERR, ...) + end +else + log_err = function(...) + print(...) + end +end + + +local function enable_lrucache(size) + local size = size or 4000 -- Cache the last 4000 IPs (~1MB memory) by default + local lrucache_obj, err = require("resty.lrucache").new(4000) + if not lrucache_obj then + return nil, "failed to create the cache: " .. (err or "unknown") + end + lrucache = lrucache_obj + return true +end +_M.enable_lrucache = enable_lrucache + + +local function split_octets(input) + local pos = 0 + local prev = 0 + local octs = {} + + for i=1, 4 do + pos = str_find(input, ".", prev, true) + if pos then + if i == 4 then + -- Should not have a match after 4 octets + return nil, "Invalid IP" + end + octs[i] = str_sub(input, prev, pos-1) + elseif i == 4 then + -- Last octet, get everything to the end + octs[i] = str_sub(input, prev, -1) + break + else + return nil, "Invalid IP" + end + prev = pos +1 + end + + return octs +end + + +local function ip2bin(ip) + if lrucache then + local get = lrucache:get(ip) + if get then + return get[1], get[2] + end + end + + if type(ip) ~= "string" then + return nil, "IP must be a string" + end + + local octets = split_octets(ip) + if not octets or #octets ~= 4 then + return nil, "Invalid IP" + end + + -- Return the binary representation of an IP and a table of binary octets + local bin_octets = {} + local bin_ip = 0 + + for i,octet in ipairs(octets) do + local bin_octet = tonumber(octet) + if not bin_octet or bin_octet > 255 then + return nil, "Invalid octet: "..tostring(octet) + end + bin_octet = tobit(bin_octet) + bin_octets[i] = bin_octet + bin_ip = bor(lshift(bin_octet, 8*(4-i) ), bin_ip) + end + + if lrucache then + lrucache:set(ip, {bin_ip, bin_octets}) + end + return bin_ip, bin_octets +end +_M.ip2bin = ip2bin + + +local function split_cidr(input) + local pos = str_find(input, "/", 0, true) + if not pos then + return {input} + end + return {str_sub(input, 1, pos-1), str_sub(input, pos+1, -1)} +end + + +local function parse_cidr(cidr) + local mask_split = split_cidr(cidr, '/') + local net = mask_split[1] + local mask = mask_split[2] or "32" + local mask_num = tonumber(mask) + if not mask_num or (mask_num > 32 or mask_num < 1) then + return nil, "Invalid prefix: /"..tostring(mask) + end + + local bin_net, err = ip2bin(net) -- Convert IP to binary + if not bin_net then + return nil, err + end + local bin_mask = bin_masks[mask] -- Get masks + local bin_inv_mask = bin_inverted_masks[mask] + + local lower = band(bin_net, bin_mask) -- Network address + local upper = bor(lower, bin_inv_mask) -- Broadcast address + return lower, upper +end +_M.parse_cidr = parse_cidr + + +local function parse_cidrs(cidrs) + local out = {} + local i = 1 + for _,cidr in ipairs(cidrs) do + local lower, upper = parse_cidr(cidr) + if not lower then + log_err("Error parsing '", cidr, "': ", upper) + else + out[i] = {lower, upper} + i = i+1 + end + end + return out +end +_M.parse_cidrs = parse_cidrs + + +local function ip_in_cidrs(ip, cidrs) + local bin_ip, bin_octets = ip2bin(ip) + if not bin_ip then + return nil, bin_octets + end + + for _,cidr in ipairs(cidrs) do + if bin_ip >= cidr[1] and bin_ip <= cidr[2] then + return true + end + end + return false +end +_M.ip_in_cidrs = ip_in_cidrs + + +local function binip_in_cidrs(bin_ip_ngx, cidrs) + if 4 ~= #bin_ip_ngx then + return false, "invalid IP address" + end + + local bin_ip = 0 + for i=1,4 do + bin_ip = bor(lshift(bin_ip, 8), tobit(byte(bin_ip_ngx, i))) + end + + for _,cidr in ipairs(cidrs) do + if bin_ip >= cidr[1] and bin_ip <= cidr[2] then + return true + end + end + return false +end +_M.binip_in_cidrs = binip_in_cidrs + +return _M diff --git a/README.md b/old/README.md similarity index 100% rename from README.md rename to old/README.md diff --git a/old/config.lua b/old/config.lua new file mode 100644 index 0000000..67d330c --- /dev/null +++ b/old/config.lua @@ -0,0 +1,23 @@ +debug = false +-- rule_path = "/data/server/nginx/conf/waf/wafconf/" +-- url_check = false +-- url_write_check = false +-- args_check = false +-- ua_check = false +-- ua_write_check = false +-- cookie_check = false +-- post_check = false + +-- black_file_ext = {"php", "jsp"} +-- attack_log = false +-- attach_log_dir = "/data/logs/waf/" + +-- redirect = false +-- redirect_url = "http://www.baidu.com" +ip_check = false +ip_white_list = {} -- {'192.168.1.*', '127.0.0.1'} +ip_black_list = {} -- {'0.0.0.0', '106.2.34.29'} + +cc_deny = false +cc_rate = "100/60" +cc_deny_seconds = "600" diff --git a/entry.lua b/old/entry.lua similarity index 88% rename from entry.lua rename to old/entry.lua index f4aaa4b..7bcea95 100644 --- a/entry.lua +++ b/old/entry.lua @@ -9,8 +9,6 @@ ip_check = true ip_white_list = {} ip_black_list = {} ---------- Init project ---------------- -require 'init' --------- Access control limit -------- if ip_check and (whiteIP(ip_white_list, debug) or blackIP(ip_black_list, debug)) then elseif cc_deny and denyCC(cc_rate, cc_deny_seconds, debug) then diff --git a/init.lua b/old/init.lua similarity index 100% rename from init.lua rename to old/init.lua diff --git a/old/logger.lua b/old/logger.lua new file mode 100644 index 0000000..e69de29 diff --git a/old/waf.lua b/old/waf.lua new file mode 100644 index 0000000..e69de29 diff --git a/wafconf/args b/old/wafconf/args similarity index 100% rename from wafconf/args rename to old/wafconf/args diff --git a/wafconf/cookie b/old/wafconf/cookie similarity index 100% rename from wafconf/cookie rename to old/wafconf/cookie diff --git a/wafconf/post b/old/wafconf/post similarity index 100% rename from wafconf/post rename to old/wafconf/post diff --git a/wafconf/url b/old/wafconf/url similarity index 100% rename from wafconf/url rename to old/wafconf/url diff --git a/wafconf/user_agent b/old/wafconf/user_agent similarity index 100% rename from wafconf/user_agent rename to old/wafconf/user_agent diff --git a/wafconf/white_url b/old/wafconf/white_url similarity index 100% rename from wafconf/white_url rename to old/wafconf/white_url diff --git a/test.lua b/test.lua new file mode 100644 index 0000000..480f809 --- /dev/null +++ b/test.lua @@ -0,0 +1,41 @@ +-- +-- Created by IntelliJ IDEA. +-- User: guang +-- Date: 16/9/22 +-- Time: 下午5:59 +-- To change this template use File | Settings | File Templates. +-- + +local _M = {} +_M.version = '0.1.1' + +local util = require "resty.waf.util" + +local mt = {__index=_M} + +function hello() + print("hello world") +end + +local config = {'hello', 'world' } + +local _a = {} + + +function _M:new() + return setmetatable({}, mt) +end + +function _M:name() + local name = {'guang', 'hong', 'wei' } + name_new = util.table_copy(name) + print(table.concat(name_new, ',')) +end + +function _M.get_version() + local name = _M.name() + print(name) +end + +return _a + diff --git a/test2.lua b/test2.lua new file mode 100644 index 0000000..5cdd09d --- /dev/null +++ b/test2.lua @@ -0,0 +1,31 @@ +-- +-- Created by IntelliJ IDEA. +-- User: guang +-- Date: 16/9/22 +-- Time: 下午6:25 +-- To change this template use File | Settings | File Templates. +-- + + +local lua_waf = require "core" +local iputils = require "iputils" + +local waf = lua_waf:new("test") +local waf2 = lua_waf:new("jj") + +for k, v in pairs(waf["config"]) do + print(k, v) +end + +waf:set_option("active", true) + +for k, v in pairs(waf["config"]) do + print(k, v) +end +print(waf.config.active) + +-- waf:deny_cc() +-- waf2:deny_cc() +waf:log("hello world") +waf2:log("world") +print(iputils.ip2bin("192.168.1.1")) From 3db5c378fac75819fbc5f7f27fd19ae320595c40 Mon Sep 17 00:00:00 2001 From: ibuler Date: Sat, 24 Sep 2016 18:00:22 +0800 Subject: [PATCH 28/31] Add . --- .idea/workspace.xml | 91 +++++++++++++++++++++++++++++++++++++++------ config.lua | 8 ++-- core.lua | 20 +++++++--- 3 files changed, 97 insertions(+), 22 deletions(-) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 7d4efb8..7cb639e 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,16 +2,8 @@ - - - - - - - - - + @@ -32,7 +24,48 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -124,9 +159,9 @@ - + - + @@ -179,5 +214,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/config.lua b/config.lua index ee3056b..11327da 100644 --- a/config.lua +++ b/config.lua @@ -1,11 +1,11 @@ -- -- Created by IntelliJ IDEA. --- User: guang --- Date: 16/9/23 --- Time: 下午4:28 --- To change this template use File | Settings | File Templates. +-- User: ibuler +-- Date: 16/9/22 +-- Time: 下午7:13 -- + local _M = {} _M.version = '0.1.0' diff --git a/core.lua b/core.lua index 590992d..60006ae 100644 --- a/core.lua +++ b/core.lua @@ -1,9 +1,8 @@ -- -- Created by IntelliJ IDEA. --- User: guang +-- User: ibuler -- Date: 16/9/22 -- Time: 下午7:13 --- To change this template use File | Settings | File Templates. -- @@ -63,11 +62,21 @@ function _M.deny_cc(self) if req then if req > max_visit then - ngx.exit(self.config.cc_deny_code) - return true + if self.config.active then + ngx.exit(self.config.cc_deny_code) + return true + else + return false + end elseif req == max_visit then - self:log("[Block] " .. token) + if self.config.active then + self:log("[Deny_cc] Block " .. token) + ngx.exit(self.config.cc_deny_code) + else + self:log("[Deny_cc] FakeBlock " .. token) + end limit:incr(token, 1) + return true else limit:incr(token, 1) end @@ -81,7 +90,6 @@ function _M.log(self, msg) log_inited[self.config.log_path] = io.open(self.config.log_path, 'ab') end self.fd = log_inited[self.config.log_path] - self.fd:write(msg .. '\n') self.fd:flush() end From 8d08639a5c3623e0d8fa31e50f0397d438d85b1c Mon Sep 17 00:00:00 2001 From: ibuler Date: Sat, 24 Sep 2016 18:36:27 +0800 Subject: [PATCH 29/31] Add --- .idea/workspace.xml | 36 +++++++++++++++++----------------- config.lua | 6 +++--- core.lua | 48 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 68 insertions(+), 22 deletions(-) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 7cb639e..44ce7f5 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -25,21 +25,21 @@ - + - - + + - + - - + + @@ -48,8 +48,8 @@ - - + + @@ -74,8 +74,8 @@ @@ -222,26 +222,26 @@ - + - - + + - + - - + + - + - - + + diff --git a/config.lua b/config.lua index 11327da..00aaebf 100644 --- a/config.lua +++ b/config.lua @@ -18,9 +18,9 @@ _M.defaults = { cc_deny_seconds = 600, cc_deny_code = 404, log_path = "/tmp/nginx_waf.log", - ip_check= true, - ip_white_list = nil, - ip_black_list = nil, + ip_white_list = {}, + ip_black_list = {}, + ip_black_code = 403, } return _M diff --git a/core.lua b/core.lua index 60006ae..68607a0 100644 --- a/core.lua +++ b/core.lua @@ -12,6 +12,7 @@ log_inited = {} local get_headers = ngx.req.get_headers local config = require "config" +local iputils = require "iputils" local mt = {__index=_M } local function get_client_ip() @@ -94,9 +95,54 @@ function _M.log(self, msg) self.fd:flush() end +function _M.in_white_ip_list(self) + local ip = get_client_ip() + local is_white_token = ip.."white" + local is_white, _ = limit:get(is_white_token) + + if is_white then + return true + end + + if next(white_ip_list) ~= nil then + local white_ip_list = self.config.white_ip_list + for _, wip in paris(white_ip_list) do + if ip == wip or iputils.ip_in_cidrs(ip, wip) then + return true + end + end + end + return false +end + +function _M.in_black_ip_list(self) + local limit = ngx.shared.limit + local ip = get_client_ip() + local is_block_token = ip.."block" + local is_block, _ = limit:get(is_block_token) + if is_block then + ngx.exit(self.config.ip_black_code) + return true + end + if next(white_ip_list) ~= nil then + local black_ip_list = self.config.white_ip_list + for _, bip in paris(black_ip_list) do + if ip == bip or iputils.ip_in_cidrs(ip, bip) then + limit:set(is_block_token, true, 3600) + ngx.exit(self.config.ip_black_code) + return true + end + end + end + return false + +end + function _M.run(self) ngx.log(ngx.WARN, 'Start running waf') - if self.config.cc_deny and self:deny_cc() then + if self:in_black_ip_list() then + elseif self:in_white_ip_list() then + elseif self.config.cc_deny and self:deny_cc() then end end From 83c826247e3096ce8ec64a7fcb220fb073a551d2 Mon Sep 17 00:00:00 2001 From: ibuler Date: Thu, 29 Sep 2016 11:10:15 +0800 Subject: [PATCH 30/31] Basic finish --- .idea/workspace.xml | 311 ++++++++++++++++++++++++++++++++++++++++++-- config.lua | 6 +- core.lua | 51 +++++--- test.lua | 24 ++-- test2.lua | 35 +++-- 5 files changed, 360 insertions(+), 67 deletions(-) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 44ce7f5..3ce7fdb 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -4,6 +4,8 @@ + + @@ -27,9 +29,29 @@ + + + + + + + + + + + + + + + + + + + + - + @@ -38,8 +60,8 @@ - - + + @@ -75,6 +97,8 @@ @@ -86,8 +110,8 @@ DEFINITION_ORDER - @@ -144,9 +168,248 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -158,7 +421,7 @@ - + @@ -168,20 +431,28 @@ + + - - + + + + @@ -232,16 +503,32 @@ - - + + - + - + + + + + + + + + + + + + + + + + diff --git a/config.lua b/config.lua index 00aaebf..a3b4d48 100644 --- a/config.lua +++ b/config.lua @@ -18,9 +18,9 @@ _M.defaults = { cc_deny_seconds = 600, cc_deny_code = 404, log_path = "/tmp/nginx_waf.log", - ip_white_list = {}, - ip_black_list = {}, - ip_black_code = 403, + white_ip_list = {}, + black_ip_list = {}, + black_return_code = 403, } return _M diff --git a/core.lua b/core.lua index 68607a0..2a64bda 100644 --- a/core.lua +++ b/core.lua @@ -14,6 +14,7 @@ local get_headers = ngx.req.get_headers local config = require "config" local iputils = require "iputils" local mt = {__index=_M } +local limit = ngx.shared.limit local function get_client_ip() local ip = get_headers()["X-Real-IP"] @@ -42,6 +43,7 @@ end function _M.new(self, name) local t = {} + name = name or "" t["name"] = name t["config"] = _M.table_copy(config.defaults) return setmetatable(t, mt) @@ -58,7 +60,6 @@ function _M.deny_cc(self) local ip = get_client_ip() local token = ip..":"..uri - local limit = ngx.shared.limit local req, _ = limit:get(token) if req then @@ -71,11 +72,9 @@ function _M.deny_cc(self) end elseif req == max_visit then if self.config.active then - self:log("[Deny_cc] Block " .. token) ngx.exit(self.config.cc_deny_code) - else - self:log("[Deny_cc] FakeBlock " .. token) end + self:log("[Deny_cc] Block "..token) limit:incr(token, 1) return true else @@ -87,27 +86,34 @@ function _M.deny_cc(self) end function _M.log(self, msg) + ngx.log(ngx.WARN, self.config.log_path) if log_inited[self.config.log_path] == nil then - log_inited[self.config.log_path] = io.open(self.config.log_path, 'ab') + log_inited[self.config.log_path] = io.open(self.config.log_path, 'a') end self.fd = log_inited[self.config.log_path] - self.fd:write(msg .. '\n') + if self.config.active then + self.fd:write(ngx.localtime().." [ACTIVE] ".."["..self.name.."] "..msg..'\n') + else + self.fd:write(ngx.localtime().." [MONITOR] ".."["..self.name.."] "..msg..'\n') + end self.fd:flush() end function _M.in_white_ip_list(self) local ip = get_client_ip() - local is_white_token = ip.."white" - local is_white, _ = limit:get(is_white_token) + local white_ip_token = ip.."white" + local is_white, _ = limit:get(white_ip_token) if is_white then return true end + local white_ip_list = self.config.white_ip_list if next(white_ip_list) ~= nil then - local white_ip_list = self.config.white_ip_list - for _, wip in paris(white_ip_list) do + for _, wip in pairs(white_ip_list) do if ip == wip or iputils.ip_in_cidrs(ip, wip) then + limit:set(white_ip_token, true, 3600) + self:log("[White_ip] In white list passed: "..ip) return true end end @@ -116,20 +122,26 @@ function _M.in_white_ip_list(self) end function _M.in_black_ip_list(self) - local limit = ngx.shared.limit local ip = get_client_ip() - local is_block_token = ip.."block" - local is_block, _ = limit:get(is_block_token) + local block_ip_token = ip.."block" + local is_block, _ = limit:get(block_ip_token) + if is_block then - ngx.exit(self.config.ip_black_code) + if self.config.active then + ngx.exit(self.config.black_return_code) + end return true end - if next(white_ip_list) ~= nil then - local black_ip_list = self.config.white_ip_list - for _, bip in paris(black_ip_list) do + + local black_ip_list = self.config.black_ip_list + if next(black_ip_list) ~= nil then + for _, bip in pairs(black_ip_list) do if ip == bip or iputils.ip_in_cidrs(ip, bip) then - limit:set(is_block_token, true, 3600) - ngx.exit(self.config.ip_black_code) + limit:set(block_ip_token, true, 3600) + self:log("[Black_ip] In black list denied: "..ip) + if self.config.active then + ngx.exit(self.config.black_return_code) + end return true end end @@ -139,7 +151,6 @@ function _M.in_black_ip_list(self) end function _M.run(self) - ngx.log(ngx.WARN, 'Start running waf') if self:in_black_ip_list() then elseif self:in_white_ip_list() then elseif self.config.cc_deny and self:deny_cc() then diff --git a/test.lua b/test.lua index 480f809..aa42dd3 100644 --- a/test.lua +++ b/test.lua @@ -9,7 +9,6 @@ local _M = {} _M.version = '0.1.1' -local util = require "resty.waf.util" local mt = {__index=_M} @@ -19,23 +18,20 @@ end local config = {'hello', 'world' } -local _a = {} - -function _M:new() - return setmetatable({}, mt) +function _M.new(self, name) + name = name or 0 + return setmetatable({name=name}, mt) end -function _M:name() - local name = {'guang', 'hong', 'wei' } - name_new = util.table_copy(name) - print(table.concat(name_new, ',')) +function _M.get_name(self) + print(self.name) end -function _M.get_version() - local name = _M.name() - print(name) -end +--function _M.get_version() +-- local name = _M.name() +-- print(name) +--end -return _a +return _M diff --git a/test2.lua b/test2.lua index 5cdd09d..7514b3a 100644 --- a/test2.lua +++ b/test2.lua @@ -7,25 +7,24 @@ -- -local lua_waf = require "core" -local iputils = require "iputils" - +--local lua_waf = require "core" +local lua_waf = require "test" local waf = lua_waf:new("test") -local waf2 = lua_waf:new("jj") - -for k, v in pairs(waf["config"]) do - print(k, v) -end - -waf:set_option("active", true) - -for k, v in pairs(waf["config"]) do - print(k, v) -end -print(waf.config.active) +print(waf.name) +--for k, v in pairs(waf["config"]) do +-- print(k, v) +--end +-- +--waf:set_option("active", true) +-- +--for k, v in pairs(waf["config"]) do +-- pritt(k, v) +--end +--print(waf.config.active) +-- -- waf:deny_cc() -- waf2:deny_cc() -waf:log("hello world") -waf2:log("world") -print(iputils.ip2bin("192.168.1.1")) +--waf:log("hello world") +--waf2:log("world") +--waf:get_name() From d3cb774090fc8904c8d9e5deb5bbea3845ffde60 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 11 Oct 2016 12:28:17 +0800 Subject: [PATCH 31/31] Add readme --- .idea/workspace.xml | 262 ++++++++++++++++++++++++++++------ README.md | 56 ++++++++ config.lua | 1 - core.lua | 39 +++-- old/README.md | 28 ---- old/config.lua | 23 --- old/entry.lua | 16 --- old/init.lua | 313 ----------------------------------------- old/logger.lua | 0 old/waf.lua | 0 old/wafconf/args | 22 --- old/wafconf/cookie | 20 --- old/wafconf/post | 19 --- old/wafconf/url | 6 - old/wafconf/user_agent | 1 - old/wafconf/white_url | 1 - test2.lua | 36 +++++ 17 files changed, 340 insertions(+), 503 deletions(-) create mode 100644 README.md delete mode 100644 old/README.md delete mode 100644 old/config.lua delete mode 100644 old/entry.lua delete mode 100644 old/init.lua delete mode 100644 old/logger.lua delete mode 100644 old/waf.lua delete mode 100644 old/wafconf/args delete mode 100644 old/wafconf/cookie delete mode 100644 old/wafconf/post delete mode 100644 old/wafconf/url delete mode 100644 old/wafconf/user_agent delete mode 100644 old/wafconf/white_url diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 3ce7fdb..dbefb79 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,9 +2,21 @@ + + + + + + + + + + + + + - @@ -26,22 +38,38 @@ - - + + - - + + + + + + + + + + + + + + + + + + - - + + @@ -50,8 +78,8 @@ - - + + @@ -60,8 +88,8 @@ - - + + @@ -70,8 +98,8 @@ - - + + @@ -96,10 +124,11 @@ @@ -110,10 +139,10 @@ DEFINITION_ORDER - @@ -276,6 +305,12 @@ + project + + + + + @@ -421,27 +456,27 @@ - + - + - - - - - - + + + + + + - - + + - - + + @@ -461,7 +496,7 @@ - + @@ -469,18 +504,34 @@ - + - - + + - + - + + + + + + + + + + + + + + + + + @@ -493,45 +544,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..75a32bf --- /dev/null +++ b/README.md @@ -0,0 +1,56 @@ +### nginx lua waf + +##### 参考 +1. https://github.com/loveshell/ngx_lua_waf +2. https://github.com/p0pr0ck5/lua-resty-waf + + +#### 使用 +1. 安装Nginx和lua插件 或者直接安装 openresty +2. git clone +3. nginx.conf 配置文件 + http段 + ... + + lua_package_path "/data/server/nginx/conf/waf/?.lua"; + lua_shared_dict limit 10m; + ... + +4. 在location中使用 + + location / { + access_by_lua ' + local lua_waf = require "core" + local waf = lua_waf:new("default") + waf:set_option("cc_rate", "2/60") + waf:set_option("active", true) + waf:set_option("white_ip_list", {"192.168.128.0/24", "127.0.0.1"}) + waf:run() + '; + ... + } + +5. reload + +#### 说明 +— 默认配置文件 + + _M.defaults = { + active = false, + cc_deny = true, + cc_rate = "100/600", + cc_deny_seconds = 600, + cc_deny_code = 404, + log_path = "/tmp/nginx_waf.log", + white_ip_list = {}, + black_ip_list = {}, + black_return_code = 403, + } + +- 单独设置 + + waf:set_option("cc_rate", "2/60") + +- 问题排查 + nginx error日志 和 log_path + \ No newline at end of file diff --git a/config.lua b/config.lua index a3b4d48..333bd54 100644 --- a/config.lua +++ b/config.lua @@ -11,7 +11,6 @@ _M.version = '0.1.0' _M.defaults = { - debug = true, active = false, cc_deny = true, cc_rate = "100/600", diff --git a/core.lua b/core.lua index 2a64bda..b45b8b9 100644 --- a/core.lua +++ b/core.lua @@ -15,6 +15,7 @@ local config = require "config" local iputils = require "iputils" local mt = {__index=_M } local limit = ngx.shared.limit +local _cidr_cache = {} local function get_client_ip() local ip = get_headers()["X-Real-IP"] @@ -71,11 +72,11 @@ function _M.deny_cc(self) return false end elseif req == max_visit then + self:log("[Deny_cc] Block "..token) + limit:incr(token, 1) if self.config.active then ngx.exit(self.config.cc_deny_code) end - self:log("[Deny_cc] Block "..token) - limit:incr(token, 1) return true else limit:incr(token, 1) @@ -85,6 +86,32 @@ function _M.deny_cc(self) end end +function cidr_match(ip, cidr_pattern) + local t = {} + local n = 1 + + if (type(cidr_pattern) ~= "table") then + cidr_pattern = { cidr_pattern } + end + + for _, v in ipairs(cidr_pattern) do + -- try to grab the parsed cidr from out module cache + local cidr = _cidr_cache[v] + + -- if it wasn't there, compute and cache the value + if (not cidr) then + local lower, upper = iputils.parse_cidr(v) + cidr = { lower, upper } + _cidr_cache[v] = cidr + end + + t[n] = cidr + n = n + 1 + end + + return iputils.ip_in_cidrs(ip, t), ip +end + function _M.log(self, msg) ngx.log(ngx.WARN, self.config.log_path) if log_inited[self.config.log_path] == nil then @@ -110,12 +137,10 @@ function _M.in_white_ip_list(self) local white_ip_list = self.config.white_ip_list if next(white_ip_list) ~= nil then - for _, wip in pairs(white_ip_list) do - if ip == wip or iputils.ip_in_cidrs(ip, wip) then + if cidr_match(ip, white_ip_list) then limit:set(white_ip_token, true, 3600) self:log("[White_ip] In white list passed: "..ip) return true - end end end return false @@ -135,15 +160,13 @@ function _M.in_black_ip_list(self) local black_ip_list = self.config.black_ip_list if next(black_ip_list) ~= nil then - for _, bip in pairs(black_ip_list) do - if ip == bip or iputils.ip_in_cidrs(ip, bip) then + if cidr_match(ip, black_ip_list) then limit:set(block_ip_token, true, 3600) self:log("[Black_ip] In black list denied: "..ip) if self.config.active then ngx.exit(self.config.black_return_code) end return true - end end end return false diff --git a/old/README.md b/old/README.md deleted file mode 100644 index 27bf878..0000000 --- a/old/README.md +++ /dev/null @@ -1,28 +0,0 @@ -## ngx_lua_waf -基于 loveshell [nginx-lua-waf](https://github.com/loveshell/ngx_lua_waf)更改 - -### 使用方法: -1. nginx安装lua模块,不再详述 -2. 下载模块 - cd /data/server/nginx/conf - git clone https://github.com/ibuler/ngx_lua_waf.git waf -2. nginx.conf 添加参数 - lua_package_path /data/server/nginx/conf/waf/?.lua; # 模块位置 - lua_shared_dict limit 10m; # 设置lua使用内存, 根据访问量设置合适值 -3. location或server设置访问控制 - access_by_lua_file /data/server/nginx/conf/waf/entry.lua; # 可以copy一份到不同的配置中,单独修改其配置文件 - -## 文件说明 -- config.lua 默认配置文件 -- entry.lua access控制入口样例文件 -- init.lua 函数所在文件,都会调用该文件 -- wafconf 暂时没有使用,将来开发继续完成 - - -### 参数说明 -- debug: 调试阶段开始debug,显示debug信息 -- cc_deny: 开启cc_deny,控制访问量 -- cc_rate: 10/60 意思为 60s内访问10次,超过频率会被block掉 -- cc_deny_seconds: 达到阈值后,禁止访问的时间 - - diff --git a/old/config.lua b/old/config.lua deleted file mode 100644 index 67d330c..0000000 --- a/old/config.lua +++ /dev/null @@ -1,23 +0,0 @@ -debug = false --- rule_path = "/data/server/nginx/conf/waf/wafconf/" --- url_check = false --- url_write_check = false --- args_check = false --- ua_check = false --- ua_write_check = false --- cookie_check = false --- post_check = false - --- black_file_ext = {"php", "jsp"} --- attack_log = false --- attach_log_dir = "/data/logs/waf/" - --- redirect = false --- redirect_url = "http://www.baidu.com" -ip_check = false -ip_white_list = {} -- {'192.168.1.*', '127.0.0.1'} -ip_black_list = {} -- {'0.0.0.0', '106.2.34.29'} - -cc_deny = false -cc_rate = "100/60" -cc_deny_seconds = "600" diff --git a/old/entry.lua b/old/entry.lua deleted file mode 100644 index 7bcea95..0000000 --- a/old/entry.lua +++ /dev/null @@ -1,16 +0,0 @@ ---------- Global default config ------- -require 'config' ---------- Local config setting -------- -debug = true - -cc_deny = false -cc_rate = '10/60' -ip_check = true -ip_white_list = {} -ip_black_list = {} - ---------- Access control limit -------- -if ip_check and (whiteIP(ip_white_list, debug) or blackIP(ip_black_list, debug)) then -elseif cc_deny and denyCC(cc_rate, cc_deny_seconds, debug) then -else return -end diff --git a/old/init.lua b/old/init.lua deleted file mode 100644 index 7853b02..0000000 --- a/old/init.lua +++ /dev/null @@ -1,313 +0,0 @@ -local match = string.match -local ngx_match = ngx.re.match -local unescape = ngx.unescape_uri -local get_headers = ngx.req.get_headers - -function getClientIp() - IP = get_headers()["X-Real-IP"] - if IP == nil then - IP = ngx.var.remote_addr - end - if IP == nil then - IP = "unknown" - end - return IP -end - -function write(logfile, msg) - local fd = io.open(logfile, "ab") - if fd == nil then - return - end - fd:write(msg) - fd:flush() - fd:close() -end - -function log(method, url, data, tag) - if attack_log 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.."\" \""..tag.."\"\n" - else - line = realIp.." ["..time.."] \""..method.." "..servername..url.."\" \""..data.."\" - \""..tag.."\"\n" - end - local filename = logpath..'/'..servername.."_"..ngx.today().."_sec.log" - write(filename, line) - end -end - ------------------------------------- 规则读取函数 ----------------------------------------- --- function readRule(var) --- file = io.open(rule_path..'/'..var, "r") --- if file == nil then --- return --- end --- t = {} --- for line in file:lines() do --- table.insert(t, line) --- end --- file:close() --- return(t) --- end - --- url_rules = readRule('url') --- white_url_rules = readRule('white_url') --- args_rules = readRule('args') --- ua_rules = readRule('user_agent') --- post_rules = readRule('post') --- cookie_rules = readRule('cookie') - - -function debugSay(msg, debug) - if debug then - ngx.header.content_type = "text/html" - ngx.status = ngx.HTTP_FORBIDDEN - ngx.say(msg) - ngx.exit(ngx.status) - end -end - - --- function whiteURLCheck() --- if white_url_rules ~= nil then --- for _, rule in pairs(white_url_rules) do --- if ngx_match(ngx.var.uri, rule, "isjo") then --- return true --- end --- end --- end --- return false --- end - - --- function fileExtCheck(ext, black_file_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 --- if attack_log then --- log('POST',ngx.var.request_uri,"-","file attack with ext "..ext) --- end - --- if debug then --- debugSay(ngx.var.request_uri.."-".."file attack with ext: "..ext) --- end --- end --- end --- end --- return false --- end - - --- function set(list) --- local set = {} --- for _, l in ipairs(list) do --- set[l] = true --- end --- return set --- end - - --- function checkArgs() --- for _, rule in pairs(args_rules) do --- local args = ngx.req.get_uri_args() --- for key, val in pairs(args) do --- if type(val) == 'table' then --- if val ~= false then --- data = table.concat(val, " ") --- end --- else --- data = val --- end --- if data and type(data) ~= "boolean" and rule ~="" and ngx_match(unescape(data), rule, "isjo") then --- log('GET', ngx.var.request_uri, "-", rule) --- debugSay(ngx.var.request_uri.."-"..rule) --- return true --- end --- end --- end --- return false --- end - - --- function url() --- if UrlDeny then --- for _,rule in pairs(urlrules) do --- if rule ~="" and ngxmatch(ngx.var.request_uri,rule,"isjo") then --- log('GET',ngx.var.request_uri,"-",rule) --- say_html() --- return true --- end --- end --- end --- return false --- end - --- function ua() --- local ua = ngx.var.http_user_agent --- if ua ~= nil then --- for _,rule in pairs(uarules) do --- if rule ~="" and ngxmatch(ua,rule,"isjo") then --- log('UA',ngx.var.request_uri,"-",rule) --- say_html() --- return true --- end --- end --- end --- return false --- end - --- function body(data) --- for _,rule in pairs(postrules) do --- if rule ~="" and data~="" and ngxmatch(unescape(data),rule,"isjo") then --- log('POST',ngx.var.request_uri,data,rule) --- say_html() --- return true --- end --- end --- return false --- end - --- function cookie() --- local ck = ngx.var.http_cookie --- if CookieCheck and ck then --- for _,rule in pairs(ckrules) do --- if rule ~="" and ngxmatch(ck,rule,"isjo") then --- log('Cookie',ngx.var.request_uri,"-",rule) --- say_html() --- return true --- end --- end --- end --- return false --- end - -function denyCC(cc_rate, cc_deny_seconds, debug) - local uri = ngx.var.uri - cc_count = tonumber(string.match(cc_rate, '(.*)/')) - cc_seconds = tonumber(string.match(cc_rate, '/(.*)')) - local token = getClientIp()..uri - local limit = ngx.shared.limit - local req, _ = limit:get(token) -- 127.0.0.1_/price/v1.0: 10 - local ip = getClientIp() - local block, _ = limit:get(ip) -- 127.0.0.1: 1 - - if block then - if debug then - ngx.say('Deny by waf.') - ngx.exit('200') - return true - else - ngx.exit(404) - end - end - - if req then - if req > cc_count then - limit:set(ip, 1, cc_deny_seconds) - ngx.exit(404) - return true - else - limit:incr(token, 1) - end - else - limit:set(token, 1, cc_seconds) - end - return false -end - --- function get_boundary() --- local header = get_headers()["content-type"] --- if not header then --- return nil --- end - --- if type(header) == "table" then --- header = header[1] --- end - --- local m = match(header, ";%s*boundary=\"([^\"]+)\"") --- if m then --- return m --- end - --- return match(header, ";%s*boundary=([^\",;]+)") --- end - -function string.split(str, delimiter) - if str==nil or str=='' or delimiter==nil then - return nil - end - - local result = {} - for match in (str..delimiter):gmatch("(.-)"..delimiter) do - table.insert(result, match) - end - return result -end - - -function innet(ip, network) - local star = '' - for i in string.gmatch(network, '%*') do - star = star..i - end - - local ip = string.split(ip, '%.') - local network = string.split(network, '%.') - if ip == nil or network == nil then - return false - end - - local ip_prefix = {} - local network_prefix = {} - for i=1, 4-string.len(star) do - ip_prefix[i] = ip[i] - network_prefix[i] = network[i] - end - - ip_prefix = table.concat(ip_prefix, '.') - network_prefix = table.concat(network_prefix, '.') - - if ip_prefix == network_prefix then - return true - else - return false - end -end - -function whiteIP(ip_white_list, debug) - if next(ip_white_list) ~= nil then - ip = getClientIp() - for _, wip in pairs(ip_white_list) do - if ip == wip or innet(ip, wip) then - if debug then - ngx.say(ip.." in white list
") - end - return true - end - end - end - return false -end - -function blackIP(ip_black_list, debug) - if next(ip_black_list) ~= nil then - ip = getClientIp() - for _, bip in pairs(ip_black_list) do - if ip == bip or ip == "0.0.0.0" or innet(ip, bip) then - if debug then - ngx.say(ip.." in black list
") - end - ngx.exit(403) - return true - end - end - end - return false -end diff --git a/old/logger.lua b/old/logger.lua deleted file mode 100644 index e69de29..0000000 diff --git a/old/waf.lua b/old/waf.lua deleted file mode 100644 index e69de29..0000000 diff --git a/old/wafconf/args b/old/wafconf/args deleted file mode 100644 index d5bf8e8..0000000 --- a/old/wafconf/args +++ /dev/null @@ -1,22 +0,0 @@ -\.\./ -\:\$ -\$\{ -select.+(from|limit) -(?:(union(.*?)select)) -having|rongjitest -sleep\((\s*)(\d*)(\s*)\) -benchmark\((.*)\,(.*)\) -base64_decode\( -(?:from\W+information_schema\W) -(?:(?:current_)user|database|schema|connection_id)\s*\( -(?:etc\/\W*passwd) -into(\s+)+(?:dump|out)file\s* -group\s+by.+\( -xwork.MethodAccessor -(?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\( -xwork\.MethodAccessor -(gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\:\/ -java\.lang -\$_(GET|post|cookie|files|session|env|phplib|GLOBALS|SERVER)\[ -\<(iframe|script|body|img|layer|div|meta|style|base|object|input) -(onmouseover|onerror|onload)\= diff --git a/old/wafconf/cookie b/old/wafconf/cookie deleted file mode 100644 index 30554ca..0000000 --- a/old/wafconf/cookie +++ /dev/null @@ -1,20 +0,0 @@ -\.\./ -\:\$ -\$\{ -select.+(from|limit) -(?:(union(.*?)select)) -having|rongjitest -sleep\((\s*)(\d*)(\s*)\) -benchmark\((.*)\,(.*)\) -base64_decode\( -(?:from\W+information_schema\W) -(?:(?:current_)user|database|schema|connection_id)\s*\( -(?:etc\/\W*passwd) -into(\s+)+(?:dump|out)file\s* -group\s+by.+\( -xwork.MethodAccessor -(?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\( -xwork\.MethodAccessor -(gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\:\/ -java\.lang -\$_(GET|post|cookie|files|session|env|phplib|GLOBALS|SERVER)\[ diff --git a/old/wafconf/post b/old/wafconf/post deleted file mode 100644 index 87d0946..0000000 --- a/old/wafconf/post +++ /dev/null @@ -1,19 +0,0 @@ -select.+(from|limit) -(?:(union(.*?)select)) -having|rongjitest -sleep\((\s*)(\d*)(\s*)\) -benchmark\((.*)\,(.*)\) -base64_decode\( -(?:from\W+information_schema\W) -(?:(?:current_)user|database|schema|connection_id)\s*\( -(?:etc\/\W*passwd) -into(\s+)+(?:dump|out)file\s* -group\s+by.+\( -xwork.MethodAccessor -(?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\( -xwork\.MethodAccessor -(gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\:\/ -java\.lang -\$_(GET|post|cookie|files|session|env|phplib|GLOBALS|SERVER)\[ -\<(iframe|script|body|img|layer|div|meta|style|base|object|input) -(onmouseover|onerror|onload)\= diff --git a/old/wafconf/url b/old/wafconf/url deleted file mode 100644 index 67e621f..0000000 --- a/old/wafconf/url +++ /dev/null @@ -1,6 +0,0 @@ -\.(svn|htaccess|bash_history|git) -\.(bak|inc|old|mdb|sql|backup|java|class)$ -(vhost|bbs|host|wwwroot|www|site|root|hytop|flashfxp).*\.rar -(phpmyadmin|jmx-console|jmxinvokerservlet) -java\.lang -/(attachments|upimg|images|css|uploadfiles|html|uploads|templets|static|template|data|inc|forumdata|upload|includes|cache|avatar)/(\\w+).(php|jsp) diff --git a/old/wafconf/user_agent b/old/wafconf/user_agent deleted file mode 100644 index f929be2..0000000 --- a/old/wafconf/user_agent +++ /dev/null @@ -1 +0,0 @@ -(HTTrack|harvest|audit|dirbuster|pangolin|nmap|sqln|-scan|hydra|Parser|libwww|BBBike|sqlmap|w3af|owasp|Nikto|fimap|havij|PycURL|zmeu|BabyKrokodil|netsparker|httperf|bench| SF/) diff --git a/old/wafconf/white_url b/old/wafconf/white_url deleted file mode 100644 index 4e3c654..0000000 --- a/old/wafconf/white_url +++ /dev/null @@ -1 +0,0 @@ -^/123/$ diff --git a/test2.lua b/test2.lua index 7514b3a..c042e75 100644 --- a/test2.lua +++ b/test2.lua @@ -10,8 +10,44 @@ --local lua_waf = require "core" local lua_waf = require "test" local waf = lua_waf:new("test") +local _cidr_cache = {} print(waf.name) +local iputils = require "iputils" + +function cidr_match(ip, cidr_pattern) + local t = {} + local n = 1 + + if (type(cidr_pattern) ~= "table") then + cidr_pattern = { cidr_pattern } + end + + for _, v in ipairs(cidr_pattern) do + -- try to grab the parsed cidr from out module cache + local cidr = _cidr_cache[v] + + -- if it wasn't there, compute and cache the value + if (not cidr) then + local lower, upper = iputils.parse_cidr(v) + cidr = { lower, upper } + _cidr_cache[v] = cidr + end + + t[n] = cidr + n = n + 1 + end + + return iputils.ip_in_cidrs(ip, t), ip +end + +a = cidr_match('192.168.128.230', {'192.168.128.0/24', '127.0.0.1'}) + +print(a) + +a = cidr_match('172.16.1.1', {'172.16.1.2'}) +print(a) + --for k, v in pairs(waf["config"]) do -- print(k, v) --end