Nginx使用Lua模块实现WAF的原理解析


Posted in Servers onSeptember 04, 2021

前言:最近一段时间在写加密数据功能,对安全相关知识还是缺少积累,无意间接触到了WAF相关知识,刚好Nginx可以实现WAF功能,也简单学习了Lua这门语言,分享下

一、WAF产生的背景

过去企业通常会采用防火墙,作为安全保障的第一道防线;当时的防火墙只是在第三层(网络层)有效的阻断一些数据包;而随着web应用的功能越来越丰富的时候,Web服务器因为其强大的计算能力,处理性能,蕴含较高的价值,成为主要的被攻击目标(第七层应用层)。而传统防火墙在阻止利用应用程序漏洞进行的攻击方面,却没有办法;在此背景下,WAF(Web Application Firewall)应运而生。

二、什么是WAF

Web 应用防火墙 (WAF-Web Application Firewall) 旨在保护 Web 应用免受各类应用层攻击,例如跨站点脚本 (XSS)、SQL 注入,以及 cookie 中毒等。应用是您重要数据的网关,因此针对应用发起的攻击就成为了造成漏洞的主要原因。有了 WAF 就可以拦截一系列企图通过入侵系统来泄漏数据的攻击。

三、工作原理

Nginx使用Lua模块实现WAF的原理解析

1.用户通过浏览器向Web服务器发送网页请求。

2.用户的请求到达Web服务器之前,WAF对用户的请求进行过滤

3.WAF拿到用户的HTTP请求参数去跟配置文件定义的规则做比较(比如ip黑名单),如果匹配上就返回403拒绝,否则就放行。

4.WEB服务器响应用户请求,把页面数据返回给用户。

四、WAF作用

waf是通过执行一系列针对HTTP/HTTPS的安全策略来专门为Web应用提供保护的一款产品。

五、WAF和传统防火墙的区别

1.传统防火墙是工作在网络层(第三层)和传输层(第四层)

2.WAF是工作在应用层(第七层)

3.传统防火墙更多是对IP和端口进行过滤

4.WAF是对HTTP请求进行过滤,包括URL,IP,User-Agent等等

六、WAF和DDos

Nginx使用Lua模块实现WAF的原理解析

DDos的全称是Distributed Denial of service。主要依靠一组计算机来发起对一个单一的目标系统的请求,从而造成目标系统资源耗尽而拒绝正常的请求。

根据OSI网络模型,最常见的DDos有三类,第三层(网络层)DDos、第四层(传输层)DDos和第七层(应用层)DDos。

WAF主要处理第七层DDos攻击,它在处理第七层DDos攻击时会比其它防护手段更高效一些。WAF会对HTTP流量做详细的分析,这样WAF就能针对正常的访问请求进行建模,然后使用这些模型来区分正常的请求和攻击者使用机器人或者脚本触发的请求

七、Nginx WAF功能

  • 支持IP白名单和黑名单功能,直接将黑名单的IP访问拒绝(新增cdip功能支持ip段)
  • 支持URL白名单,将不需要过滤的URL进行定义
  • 支持User-Agent的过滤,匹配自定义规则中的条目,然后进行处理
  • 支持CC攻击防护,单个URL指定时间的访问次数,超过设定值(新增针对不同域名)
  • 支持Cookie过滤,匹配自定义规则中的条目,然后进行处理
  • 支持URL过滤,匹配自定义规则中的条目,如果用户请求的URL包含这些
  • 支持URL参数过滤,原理同上
  • 支持日志记录,将所有拒绝的操作,记录到日志中去
  • 新增支持拉黑缓存(默认600秒)

八、Nginx Waf防护流程

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

  • 检查IP白名单,通过就不检测;
  • 检查IP黑名单,不通过即拒绝;
  • 检查CC攻击,匹配即拒绝
  • 检查http_Acunetix_Aspect扫描是否开启
  • 检查http_X_Scan_Memo扫描是否开启
  • 检查白名单URL检查;
  • 检查UA,UA不通过即拒绝;
  • 检查URL参数检查;
  • 检查cookie;
  • 检查post;

九、基于Nginx实现的WAF

9.1安装依赖包

yum -y install gcc gcc-c++ autoconf automake make unzip
yum -y install zlib zlib-devel openssl openssl-devel pcre pcre-devel

9.2安装LuaJIT2.0

LuaJIT是Lua的即时编译器,简单来说,LuaJIT是一个高效的Lua虚拟机。

# 进入目录
cd /usr/local/src/
 
# 下载LuaJIT2.0
wget http://luajit.org/download/LuaJIT-2.0.5.tar.gz
 
# 解压
tar xf LuaJIT-2.0.5.tar.gz && cd LuaJIT-2.0.5
 
# 编译
make
 
# 安装
make install PREFIX=/usr/local/lj2
 
# 建立软连接
ln -s /usr/local/lj2/lib/libluajit-5.1.so.2 /lib64/
 
# 添加环境变量
export LUAJIT_LIB=/usr/local/lj2/lib/
export LUAJIT_INC=/usr/local/lj2/include/luajit-2.0/

9.3安装ngx_devel_kit

kit模块是一个拓展nginx服务器核心功能的模块,第三方模块开发可以基于它来快速实现。

# 进入目录
cd /user/local/src/
 
# 下载v0.3.0.tar.gz
wget  https://github.com/simplresty/ngx_devel_kit/archive/v0.3.0.tar.gz -O ngx_devel_kit.tar.gz
 
# 解压
tar xf ngx_devel_kit.tar.gz

9.4安装lua-nginx-module

ngx_lua_module 是一个nginx http模块,它把 lua 解析器内嵌到 nginx,用来解析并执行lua 语言编写的网页后台脚本。

ngx_lua模块的原理

1. 每个worker(工作进程)创建一个Lua VM,worker内所有协程共享VM;
2. 将Nginx I/O原语封装后注入 Lua VM,允许Lua代码直接访问;
3. 每个外部请求都由一个Lua协程处理,协程之间数据隔离;
4. Lua代码调用I/O操作等异步接口时,会挂起当前协程(并保护上下文数据),而不阻塞worker;
5. I/O等异步操作完成时还原相关协程上下文数据,并继续运行

安装

# 进入目录
cd /user/local/src/
 
# 下载v0.10.9rc7.tar.gz
wget https://github.com/openresty/lua-nginx-module/archive/v0.10.9rc7.tar.gz
 
# 解压
tar -xzvf v0.10.9rc7.tar.gz

9.5安装Nginx

# 进入目录
cd /user/local/src/
 
# 下载
wget http://nginx.org/download/nginx-1.21.0.tar.gz
 
# 解压
tar xf nginx-1.21.0.tar.gz
 
# 进入nginx目录
cd nginx-1.21.0
 
# 编译
./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_flv_module --with-http_stub_status_module --with-http_gzip_static_module --with-http_realip_module --with-pcre --add-module=/usr/local/src/lua-nginx-module-0.10.9rc7 --add-module=/usr/local/src/ngx_devel_kit-0.3.0 --with-stream
 
# 安装
make && make install
 
# 添加nginx配置,在server块里添加下面内容
[root@localhost_test_192.168.10.132 11:04:48 ~]# vim /usr/local/nginx/conf/nginx.conf
 
location /lua {
    default_type 'text/plain';
 
    content_by_lua 'ngx.say("hello, lua")';
}
 
# 检查语法
[root@localhost_test_192.168.10.132 09:59:33 /usr/local/src]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
 
# 启动
[root@localhost_test_192.168.10.132 11:08:35 ~]# nginx
 
# 测试
curl 127.0.0.1:80/lua

9.6安装ngx_lua_waf

# 进入目录
cd /user/local/src/
 
# 把ngx_lua_waf下载到conf目录下
wget https://github.com/loveshell/ngx_lua_waf/archive/master.zip
 
# 解压命名为waf
unzip master.zip -d /usr/local/nginx/conf/
 
# 更改目录名
mv /usr/local/nginx/conf/ngx_lua_waf-master /usr/local/nginx/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;
 
# 在nginx.conf最外层添加用户运行
user www;
 
# 创建日志目录
mkdir /usr/local/nginx/logs/hack
chown www /usr/local/nginx/logs/hack
 
# Lua_waf 配置
[root@localhost_test_192.168.10.132 11:33:53 /usr/local/nginx/conf/waf]# cat config.lua
# 规则存放路径
RulePath = "/usr/local/nginx/conf/waf/wafconf/"
# 是否开启攻击信息记录,需要配置logdir
attacklog = "on"
# log存储目录,该目录需要用户自己新建,切需要nginx用户的可写权限
logdir = "/usr/local/nginx/logs/hack/"
# 是否拦截url访问
UrlDeny="on"
# 是否拦截后重定向
Redirect="on"
# 是否拦截cookie攻击
CookieMatch="on"
# 是否拦截post攻击
postMatch="on"
# 是否开启URL白名单
whiteModule="on"
# 填写不允许上传文件后缀类型
black_fileExt={"php","jsp"}
# ip白名单,多个ip用逗号分隔
ipWhitelist={"127.0.0.1"}
# ip黑名单,多个ip用逗号分隔
ipBlocklist={"192.168.10.1"}
# 是否开启拦截cc攻击(需要nginx.conf的http段增加lua_shared_dict limit 10m;)
CCDeny="off"
# 设置cc攻击频率,单位为秒.
# 默认1分钟同一个IP只能请求同一个地址100次
CCrate="100/60"
# 告警内容
html= []
 
# 规则文件
[root@localhost_test_192.168.10.132 11:42:12 /usr/local/nginx/conf/waf]# ll wafconf/
total 24
-rw-r--r-- 1 root root 749 Apr  6  2016 args
-rw-r--r-- 1 root root 652 Apr  6  2016 cookie
-rw-r--r-- 1 root root 733 Apr  6  2016 post
-rw-r--r-- 1 root root 335 Apr  6  2016 url
-rw-r--r-- 1 root root 177 Apr  6  2016 user-agent
-rw-r--r-- 1 root root   8 Apr  6  2016 whiteurl
 
args里面的规则get参数进行过滤的
cookie是对请求过滤的cookie过滤
url是只在get请求url过滤的规则
post是只在post请求过滤的规则
whiteurl是白名单,里面的url匹配到不做过滤
user-agent是对user-agent的过滤规则
 
# 加载Nginx
[root@localhost_test_192.168.10.132 11:32:41]# nginx -s reload

9.7测试效果  

访问带有参数的URL

 

Servers 相关文章推荐
nginx 多个location转发任意请求或访问静态资源文件的实现
Mar 31 Servers
详解Apache SkyWalking 告警配置指南
Apr 22 Servers
nginx中proxy_pass各种用法详解
Nov 07 Servers
深入解析Apache Hudi内核文件标记机制
Mar 31 Servers
Nginx虚拟主机的配置步骤过程全解
Mar 31 Servers
nginx.conf配置文件结构小结
Apr 08 Servers
Linux中如何安装并部署Redis
Apr 18 Servers
Windows server 2012搭建FTP服务器
Apr 29 Servers
IIS服务器中设置HTTP重定向访问HTTPS
Apr 29 Servers
使用Nginx的访问日志统计PV与UV
May 06 Servers
Nginx 配置 HTTPS的详细过程
May 30 Servers
ssh服务器拒绝了密码 请再试一次已解决(亲测有效)
Aug 14 Servers
Nginx部署vue项目和配置代理的问题解析
centos8安装nginx1.9.1的详细过程
Aug 02 #Servers
Nginx反向代理至go-fastdfs案例讲解
Aug 02 #Servers
Nginx配置之实现多台服务器负载均衡
Aug 02 #Servers
nginx服务器的下载安装与使用详解
Aug 02 #Servers
nginx反向代理配置去除前缀案例教程
Jul 26 #Servers
nginx结合openssl实现https的方法
You might like
php preg_match_all结合str_replace替换内容中所有img
2008/10/11 PHP
PHP手机号码归属地查询代码(API接口/mysql)
2012/09/04 PHP
php函数间的参数传递(值传递/引用传递)
2013/09/23 PHP
php画图实例
2014/11/05 PHP
PHP实现添加购物车功能
2017/03/06 PHP
javascript下查找父节点的简单方法
2007/08/13 Javascript
js null undefined 空区别说明
2010/06/13 Javascript
flexigrid 参数说明
2010/11/23 Javascript
js实现点击注册按钮开始读秒倒计时的小例子
2013/05/11 Javascript
ajax读取数据后使用jqchart显示图表的方法
2015/06/10 Javascript
jQuery+css实现的切换图片功能代码
2016/01/27 Javascript
网页前端登录js按Enter回车键实现登陆的两种方法
2016/05/10 Javascript
javascript宿主对象之window.navigator详解
2016/09/07 Javascript
解决bootstrap中使用modal加载kindeditor时弹出层文本框不能输入的问题
2017/06/05 Javascript
JavaScript 对引擎、运行时、调用堆栈的概述理解
2018/10/22 Javascript
node.js的http.createServer过程深入解析
2019/06/06 Javascript
浅谈js中的attributes和Attribute的用法与区别
2020/07/16 Javascript
在vue中created、mounted等方法使用小结
2020/07/21 Javascript
vue 获取url参数、get参数返回数组的操作
2020/11/12 Javascript
Python实现的一个简单LRU cache
2014/09/26 Python
python实现分析apache和nginx日志文件并输出访客ip列表的方法
2015/04/04 Python
浅析PEP572: 海象运算符
2019/10/15 Python
Python如何使用argparse模块处理命令行参数
2019/12/11 Python
Python使用gluon/mxnet模块实现的mnist手写数字识别功能完整示例
2019/12/18 Python
Python实现银行账户资金交易管理系统
2020/01/03 Python
解决pycharm编辑区显示yaml文件层级结构遇中文乱码问题
2020/04/27 Python
Python常用库Numpy进行矩阵运算详解
2020/07/21 Python
css3发光搜索表单分享
2014/04/11 HTML / CSS
一句话工作感言
2014/03/01 职场文书
酒店管理专业自荐信
2014/05/23 职场文书
见习报告怎么写
2014/10/31 职场文书
本溪水洞导游词
2015/02/11 职场文书
2015年质量月活动总结报告
2015/03/27 职场文书
2015年端午节活动方案
2015/05/05 职场文书
教师岗位说明书
2015/09/30 职场文书
Oracle中update和select 关联操作
2022/01/18 Oracle