转自:http://www.tuicool.com/articles/FbQ3ymB

WAF的主要功能为:

  • ip黑白名单
  • url黑白名单
  • useragent黑白名单
  • referer黑白名单
  • 常见web漏洞防护,如xss,sql注入等
  • cc攻击防护
  • 扫描器简单防护
  • 其他你想要的功能

WAF的总体检测思路:

  • 当用户访问到nginx时,waf首先获取用户的ip,uri,referer,useragent,,cookie,args,post,method,header信息。
  • 将获取到的信息依次传给上述功能的函数,如ip规则,在ip规则中,循环到所有的ip规则,如果匹配到ip则根据规则的处理方式来进行处理,匹配到之后不继续匹配后续规则。
  • 需要开启的功能依次在主函数中调用即可,顺序也可根据实际场景来确定最合适的顺序。

config.lua

RulePath = "/data/mypro/ngx_lua/waf/wafconf/"
attacklog = "on"
logdir = "/usr/local/openresty/nginx/logs"
UrlDeny="on"
Redirect="on"
CookieMatch="on"
postMatch="on"
whiteModule="on"
ipWhitelist={}
ipBlocklist={"1.0.0.1"}
CCDeny="off"
CCrate="100/60"
html=[[Please go away~~ ]]

init.lua

require 'config'
local match = string.match
local ngxmatch=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"]
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,ruletag)
if attacklog then
local realIp = getClientIp()
local ua = ngx.var.http_user_agent
local servername=ngx.var.server_name
local time=ngx.localtime()
if ua then
line = realIp.." ["..time.."] \""..method.." "..servername..url.."\" \""..data.."\" \""..ua.."\" \""..ruletag.."\"\n"
else
line = realIp.." ["..time.."] \""..method.." "..servername..url.."\" \""..data.."\" - \""..ruletag.."\"\n"
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
return
end
t = {}
for line in file:lines() do
table.insert(t,line)
end
file:close()
return(t)
end

local urlrules=read_rule('url')
  local argsrules=read_rule('args')
  local uarules=read_rule('user-agent')
  local wturlrules=read_rule('whiteurl')
  local postrules=read_rule('post')
  local ckrules=read_rule('cookie')

function say_html()
if Redirect then
ngx.header.content_type = "text/html"
ngx.say(html)
ngx.exit()
end
end function whiteurl()
if WhiteCheck then
if wturlrules ~=nil then
for _,rule in pairs(wturlrules) do
if ngxmatch(ngx.var.request_uri,rule,"imjo") then
return true
end
end
end
end
return false
end function args()
for _,rule in pairs(argsrules) 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 ngxmatch(unescape(data),rule,"imjo") then
log('GET',ngx.var.request_uri,"-",rule)
say_html()
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,"imjo") 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,"imjo") 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,"imjo") 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,"imjo") 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)
if req then
if req > CCcount then
ngx.exit()
return true
else
limit:incr(token,)
end
else
limit:set(token,,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[]
end local m = match(header, ";%s*boundary=\"([^\"]+)\"")
if m then
return m
end return match(header, ";%s*boundary=([^\",;]+)")
end function whiteip()
if next(ipWhitelist) ~= nil then
for _,ip in pairs(ipWhitelist) do
if getClientIp()==ip then
return true
end
end
end
return false
end function blockip()
if next(ipBlocklist) ~= nil then
for _,ip in pairs(ipBlocklist) do
if getClientIp()==ip then
ngx.exit()
return true
end
end
end
return false
end

waf.lua

local content_length=tonumber(ngx.req.get_headers()['content-length'])
local method=ngx.req.get_method()
if whiteip() then
elseif blockip() then
elseif denycc() then
elseif ngx.var.http_Acunetix_Aspect then
ngx.exit()
elseif ngx.var.http_X_Scan_Memo then
ngx.exit()
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( * )
sock:settimeout()
local content_length = nil
content_length=tonumber(ngx.req.get_headers()['content-length'])
local chunk_size =
if content_length < chunk_size then
chunk_size = content_length
end
local size =
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 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" or val == false 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

在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;

重启nginx

部署完毕可以尝试如下命令:

curl http://xxxx/test.php?id=../etc/passwd
返回"Please go away~~"字样,说明规则生效。

ngx_lua模块学习示例之waf的更多相关文章

  1. Day5 - Python基础5 常用模块学习

    Python 之路 Day5 - 常用模块学习   本节大纲: 模块介绍 time &datetime模块 random os sys shutil json & picle shel ...

  2. 大数据下基于Tensorflow框架的深度学习示例教程

    近几年,信息时代的快速发展产生了海量数据,诞生了无数前沿的大数据技术与应用.在当今大数据时代的产业界,商业决策日益基于数据的分析作出.当数据膨胀到一定规模时,基于机器学习对海量复杂数据的分析更能产生较 ...

  3. python中confIgparser模块学习

    python中configparser模块学习 ConfigParser模块在python中用来读取配置文件,配置文件的格式跟windows下的ini配置文件相似,可以包含一个或多个节(section ...

  4. OpenResty之ngx_lua模块的加密接口

    原文: ngx_Lua模块中的加密api接口 ngx.crc32_short digest = ngx.crc32_short(str) 该方法主要是计算给定字符串 str 的循环校验码(Cyclic ...

  5. osg学习示例之遇到问题四骨骼动画编译osgCal

    osg学习示例之遇到问题四骨骼动画编译osgCal 转自:http://blog.csdn.net/wuwangrun/article/details/8239451 今天学到书<OpenSce ...

  6. 不学就吃亏的underscorejs类库学习示例 ——(集合篇)

    underscorejs是一个很不错的类库,我的很多项目都引用了这个类库,的确可以带来很多方便. 记得我当初学的时候,看underscorejs的api是看的一知半解的,甚至不明白api里的conte ...

  7. zigbee学习:示例程序SampleApp中按键工作流程

    zigbee学习:示例程序SampleApp中按键工作流程 本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明. 环境: 主机:WIN7 开发环境:IAR8. ...

  8. zigbee学习:示例程序SampleApp中通讯流程

    zigbee学习:示例程序SampleApp中通讯流程 本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明. 参考链接: http://wjf88223.bl ...

  9. # nodejs模块学习: express 解析

    # nodejs模块学习: express 解析 nodejs 发展很快,从 npm 上面的包托管数量就可以看出来.不过从另一方面来看,也是反映了 nodejs 的基础不稳固,需要开发者创造大量的轮子 ...

随机推荐

  1. CLS(公共语言规范)的CLSCompliant(跨语言调用)

    .net的一个很重要的特性就是跨语言的编程,用C#写的dll可以在VB.net里调用,例如:用C#写的一个类,编译到dll中,然后在VB.net中调用: using System;namespace  ...

  2. [Compose] 15. Applicative Functors for multiple arguments

    Working our way backwards from solution to problem, we define an applicative functor, then use it to ...

  3. Mysql导出逗号分隔的csv文件

    CleverCode在实际的工作中.常常须要将一些报表.或者日志数据等导出来,假设直接做页面,假设次数也不是非常多,需求也不同.所以直接导出csv文件,更加直观. 1 导出csv文件 1.1 语句格式 ...

  4. 在第一段ionic示例的基础上增加底部导航

    demo2.html <!DOCTYPE html> <html ng-app="app"> <head> <meta charset=& ...

  5. ios 推送app badge 数字累加操作

    ios 推送app badge 数字累加操作: 一:此数字需要后台配合: 二:大致原理: 后台发推送时,第一次 传badge 为1,往后,依次累加操作即可: 当用户打开app时,app向后台发送请求, ...

  6. studio快捷键

  7. android安装应用程序工具类

    /** * 安装APK文件 *@param APK文件 *Version: *author:YangQuanqing */ private void installAPK(File file){ // ...

  8. HttpClient 解说 (1) 基础

    前言 超文本传输协议(HTTP)或许是当今互联网上使用的最重要的协议了. Web服务,有网络功能的设备和网络计算的发展,都持续扩展了HTTP协议的角色,超越了用户使用的Web浏览器范畴.同一时候,也添 ...

  9. OJ帐号保存

    TOJ 614173971 HDU 宇智波佐助 POJ shiai ZOJ henyumen UVa henyumen Light OJ HENYUMEN bzoj henyumen ural 165 ...

  10. 如何下载flash离线安装包

      如何下载flash离线安装包 CreateTime--2018年4月14日16:02:13 Author:Marydon 1.下载地址 UpdateTime--2018年5月13日16点55分 p ...