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配置并兼容HTTP实现代码解析
Mar 31 Servers
Nginx 路由转发和反向代理location配置实现
Nov 11 Servers
Tomcat用户管理的优化配置详解
Mar 31 Servers
了解Kubernetes中的Service和Endpoint
Apr 01 Servers
nginx搭建NFS网络文件系统
Apr 14 Servers
阿里云 Windows server 2019 配置FTP
Apr 28 Servers
如何Tomcat中使用ipv6地址
May 06 Servers
Linux磁盘管理方法介绍
Jun 01 Servers
WinServer2012搭建DNS服务器的方法步骤
Jun 10 Servers
利用Apache Common将java对象池化的问题
Jun 16 Servers
搭建zabbix监控以及邮件报警的超级详细教学
Jul 15 Servers
Valheim服务器 Mod修改安装教程 【ValheimPlus】
Dec 24 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 file_exists 检查文件或目录是否存在的函数
2010/05/10 PHP
php.ini save_handler 修改不生效的解决办法
2014/07/22 PHP
php中使用gd库实现远程图片下载实例
2015/05/12 PHP
php使用gzip压缩传输js和css文件的方法
2015/07/29 PHP
PHP实现活动人选抽奖功能
2017/04/19 PHP
Laravel学习教程之本地化模块
2017/08/18 PHP
PHP PDOStatement::errorCode讲解
2019/01/31 PHP
AJAX使用了UpdatePanel后无法使用alert弹出脚本
2010/04/02 Javascript
jQuery Mobile页面跳转后未加载外部JS原因分析及解决
2013/03/18 Javascript
探讨javascript是不是面向对象的语言
2013/11/21 Javascript
js判断横竖屏及禁止浏览器滑动条示例
2014/04/29 Javascript
BOOTSTRAP时间控件显示在模态框下面的bug修复
2015/02/05 Javascript
常用jQuery代码分享
2015/07/14 Javascript
jQuery使用$.ajax进行即时验证的方法
2015/12/08 Javascript
详解Vue 动态添加模板的几种方法
2017/04/25 Javascript
初学者AngularJS的环境搭建过程
2017/10/27 Javascript
vue使用中的内存泄漏【推荐】
2018/07/10 Javascript
创建Vue项目以及引入Iview的方法示例
2018/12/03 Javascript
利用JS代码自动删除稿件的普通弹幕功能
2019/09/20 Javascript
如何使用 vue-cli 创建模板项目
2020/11/19 Vue.js
ESLint 是如何检查 .vue 文件的
2020/11/30 Vue.js
Vue 修改网站图标的方法
2020/12/31 Vue.js
JS数组索引检测中的数据类型问题详解
2021/01/11 Javascript
为Python的Tornado框架配置使用Jinja2模板引擎的方法
2016/06/30 Python
python调用java的jar包方法
2018/12/15 Python
pip指定python位置安装软件包的方法
2019/07/12 Python
Python异步编程之协程任务的调度操作实例分析
2020/02/01 Python
python如何导出微信公众号文章方法详解
2020/08/31 Python
全面解析HTML5中的标准属性与自定义属性
2016/02/18 HTML / CSS
HTML5拖拽API经典实例详解
2018/04/20 HTML / CSS
科研课题实施方案
2014/03/18 职场文书
旷课检讨书范文
2014/10/30 职场文书
会议开幕词
2015/01/28 职场文书
个人党性锻炼总结
2015/03/05 职场文书
幼儿园托班教育随笔
2015/08/14 职场文书
Redis命令处理过程源码解析
2022/02/12 Redis