使用Nginx三方扩展ngx_waf快速实现一个高性能的Web应用防火墙

ngx_waf:方便且高性能的 nginx 防火墙模块
缓存策略为 lru,ip 检查和 cc 防御花费常数时间,其它的检查花费 o(nm) 的时间,其中 n 是相关规则的条数,m 为执行正则匹配的时间复杂度,但是每次检查过后会自动缓存本次检查的结果,下次检查相同的目标时就可以使用缓存而不是检查全部的规则。不会缓存 post 请求体的检查结果。
1工具特点
介绍了该工具的主要特点以及核心功能!
该 nginx 的第三方扩展工具,可以防御 cc 攻击(超出限制后自动拉黑对应 ip 一段时间或者使用验证码做人机识别),可以支持多种黑白名单(ip/post/url/ua等等),还可以提供防护 sql 注入和 xss 工具。
使用简单
配置文件和规则文件书写简单,可读性强
基础防护
如 ip 或 ip 网段的黑白名单、uri 黑白名单和请求体黑名单等
高性能
使用高效的 ip 检查算法和缓存机制,支持 ipv4 和 ipv6
高级防护
兼容 modsecurity 的规则,你可以使用 owasp 的核心规则库
友好爬虫验证
支持验证 google、bing、baidu 和 yandex 的爬虫并自动放行,避免错误拦截,主要是基于 user-agent 和 ip 的识别规则
验证码
支持三种验证码:hcaptcha、recaptchav2 和 recaptchav3
2模块安装
第三方模块我们应该怎么安装呢?
nginx 提供两种安装模块的方式,即「静态链接」和「动态加载」,通过两种方式安装的模块也分别称为「静态模块」和「动态模块」,可以通过运行脚本 assets/guide.sh 来选择使用静态模块还是动态模块。
# 执行如下命令$ sh assets/guide.sh# 如果输出下面这行,则建议使用动态模块# it is recommended that you use dynamic modules.# 如果输出下面这行,则建议使用静态模块# it is recommended that you use static modules.  
[1] 静态模块
编译安装一个新的模块需要知道当前的 nginx 的 configure 脚本的参数,您可以通过运行 nginx -v 来获取,务必记住 configure arguments: 后面的内容。安装静态模块需要重新编译整个 nginx,花费的时间相对于安装动态模块比较长。如果不想在替换二进制文件时,关闭 nginx 服务的话,可以参考官方文档的热部署方案。
# 下载对应的nginx版本# http://nginx.org/en/download.html$ cd /usr/local/src$ wget https://nginx.org/download/nginx-1.20.1.tar.gz$ tar -zxf nginx-1.20.1.tar.gz# 使用稳定版的源码$ cd /usr/local/src$ git clone -b lts https://github.com/add-sp/ngx_waf.git# 运行配置脚本$ cd /usr/local/src/nginx-1.20.1$ ./configure arg --add-module=/usr/local/src/ngx_waf$ sed -i 's/^(cflags.*)/1     -fstack-protector-strong -wno-sign-compare/'     objs/makefile# 编译(非并行/并行)$ make$ make -j$(nproc)# 替换nginx二进制文件(假设已经安装过)$ cp objs/nginx /usr/local/nginx/sbin/nginx  
[2] 动态模块 - 下载预构建的模块
通过执行脚本 assets/download.sh 来下载动态模块。
# 用于nginx-1.20.1的lts版的模块$ sh assets/download.sh 1.20.1 lts# 用于nginx-1.20.1的最新版的模块$ sh assets/download.sh 1.20.1 current# 执行成功后会有如下输出checking for command ... yeschecking for libc implementation ... yes + gnu c libarypulling remote image addsp/ngx_waf-prebuild:ngx-1.20.1-module-beta-glibc......download complete!  
如果看到 download complete! 的话,则说明下载成功,模块会被保存在当前目录下。你可以将其拷贝到一个目录下,然后在 nginx.conf 的顶部添加一行。然后关闭 nginx 服务并运行 nginx -t。如果没有出错则说明模块被正常加载,反之则说明您的 nginx 不支持预构建的模块,请编译安装模块。
load_module /path/to/ngx_http_waf_module.so;  
[3] 动态模块 - 编译动态模块
编译安装动态模块并不需要重新编译整个 nginx,只需要重新编译所有的模块,所以速度相对静态模块快一些,这也是本文档推荐的方式。
# 下载对应的nginx版本# http://nginx.org/en/download.html$ cd /usr/local/src$ wget https://nginx.org/download/nginx-1.20.1.tar.gz$ tar -zxf nginx-1.20.1.tar.gz# 使用稳定版的源码$ cd /usr/local/src$ git clone -b lts https://github.com/add-sp/ngx_waf.git# 运行配置脚本$ cd /usr/local/src/nginx-1.20.1$ ./configure --add-dynamic-module=/usr/local/src/ngx_waf --with-compat$ sed -i 's/^(cflags.*)/1     -fstack-protector-strong -wno-sign-compare/'     objs/makefile# 开始编译动态模块$ make modules# 将动态模块拷贝到模块目录(关闭服务)$ cp objs/*.so /usr/local/nginx/modules  
最后,在 nginx 的配置文件顶部添加一行,表示加载这个编译好的模块。
load_module /usr/local/nginx/modules/ngx_http_waf_module.so;  
3模块使用
第三方模块我们应该怎么使用呢?更多参数参考 配置语法
现在就可以在 nginx.conf 内的一个 server 块中添加配置来开启 ngx_waf 模块来配置服务的防火墙了,下面是一个例子。
[1] lts 版本
http {    ...    server {        ...        # on/off 表示启用和关闭        waf on;        # 规则文件所在目录的绝对路径,必须以/结尾        waf_rule_path /usr/local/src/ngx_waf/assets/rules/;        # 防火墙工作模式,std表示标准模式        waf_mode std;        # cc防御参数        # 1000表示每分钟请求次数上限,超出上限后封禁对应ip地址60分钟        waf_cc_deny rate=1000r/m duration=60m;        # 最多缓存50个检测目标的检测结果        # 对除了ip黑白名单检测、cc防护和post检测以外的所有检测生效        waf_cache capacity=50;        ...    }    ...}  
[2] current 版本
http {    # 声明一块共享内存    waf_zone name=waf size=20m;    ...    server {        ...        # on/off 表示启用和关闭        waf on;        # 规则文件所在目录的绝对路径,必须以/结尾        waf_rule_path /usr/local/src/ngx_waf/assets/rules/;        # 防火墙工作模式,std表示标准模式        waf_mode std;        # cc防御参数        # 1000表示每分钟请求次数上限,超出上限后封禁对应ip地址60分钟        waf_cc_deny on rate=1000r/m duration=60m zone=waf:cc;        # 对除了ip黑白名单检测、cc防护和post检测以外的所有检测生效        waf_cache on capacity=50;        ...    }    ...}  
4常用设置
列出一些 常用的设置,拿来直接就可以使用!
因为模块的配置比较复杂,为了降低使用难度,在这里列出了一些常见用法。
[1] 针对路径或文件限流
有时你可能想要限制不同的路径或文件的请求速率,比如静态资源和动态资源使用不同的速率限制。
# lts# 将静态资源的请求速率限制到10,000次/分钟location /static/ {    waf_cc_deny rate=10000r/m duration=1h;}# 将动态资源的请求速率限制到2,000次/分钟location /dynamic/ {    waf_cc_deny rate=2000r/m duration=1h;}# currenthttp {    waf_zone name=waf size=20m;    server {        # 将静态资源的请求速率限制到10,000次/分钟        location /static/ {            waf_cc_deny rate=10000r/m duration=1h zone=waf:cc_static;        }        # 将动态资源的请求速率限制到2,000次/分钟        location /dynamic/ {            waf_cc_deny rate=2000r/m duration=1h zone=waf:cc_dynamic;        }    }}  
[2] 开启验证码
hcaptcha
recaptchav2
recaptchav3
当你的站点受到 cc 攻击时开启验证码是不错的选择,因为验证码可以帮助你进行人机识别。本模块目前支持三种验证码,你应该选择一个并从其网站上申请到 sitekey 和 secret。配置完成之后,重启 nginx 服务。
# 整个站点开启验证码server {    waf_captcha on prov=hcaptcha secret=your_secret sitekey=your_sitekey;}# 为某个路径开启验证码location {    waf_captcha on prov=hcaptcha secret=your_secret sitekey=your_sitekey;}# 当访问频率过高时开启验证码http {    waf_zone name=waf size=20m;    server {        waf_cc_deny on rate=1000r/m duration=1h zone=waf:cc;        waf_captcha off prov=hcaptcha secret=your_secret sitekey=your_sitekey;        waf_action cc_deny=captcha zone=waf:action;    }}  
[3] 拦截请求时启用验证码
如今,许多攻击者都会使用自动工具攻击服务器,这些自动工具会尝试每一个漏洞,有的会被安全措施所拦截,有的则可以躲避检测。如果攻击者觉得你的价值比较高,可能会手动攻击你的服务。我们并不能完美地防御这些攻击,但却能很简单地提高攻击的成本。
当一个请求被拦截时,ngx_waf 会对该 ip 启用验证码,此时该 ip 想要继续访问就必须完成验证码。这基本可以废掉多数的自动攻击工具,因为这些工具会尝试每一个漏洞,而我们总能识别一些明显的攻击请求并启用验证码,而自动工具时难以通过验证的。对于手动攻击者,这也能提高他们的时间成本。
http {    waf_zone name=waf size=20m;    server {        waf_captcha off prov=xxx sitekey=xxx secret=xxx;        waf_action blacklist=captcha zone=waf:action;    }}  
[4] 被攻击时降低带宽占用
当你受到 cc 攻击时,攻击者的 ip 已经被 cc 防护拉黑,但是你的上下行带宽依然很高, 这是因为 cc 防护会返回一个 503 状态码,因此占用了你的带宽,你可以使用下面的配置来降低带宽占用。
444 状态码是 nginx定义的一个非标准的 http 状态码,其作用就是直接关闭连接,不再发送任何数据。如果你使用了 444 状态码,那么在用户看来你的网站就像是不存在一样。这是因为网站出错一般都会有 http 状态码用来提示错误, 如果访问一个网站连错误提示都没有,那么大概率是这个网站不存在。
# ltswaf_http_status cc_deny=444;# currentwaf_action cc_deny=444;  
[5] 抵御分布式 cc 攻击
cc 攻击(http 洪水)是指发送大量的 http 请求来耗尽服务器的资源。如果攻击者使用的 ip 较少则防御较为简单,因为只需要限制 ip 的请求频率,但是如果攻击者使用大量的 ip 进行攻击,仅仅限制 ip 的请求频率是无济于事的。这种使用大量 ip 进行 cc 攻击的方式称为分布式 cc 攻击或分布式 http 洪水。
本模块提供了一些缓解方式,第一种开启验证码来缓解,第二种使用降低带宽占用,第三种使用五秒盾来缓解。你可能听说过 cloudflare 的五秒盾,本模块的五秒盾和 cloudflare 的完全不同。它的功能是检测客户端是否能够正确地支持 cookie,比如发送 cookie 和正确地处理 set-cookie 响应头。你可以从本项目的 assets/ 目录下找到 under-attack.html 并将其拷贝到某个路径下,然后通过修改 nginx 的配置文件来开启五秒盾。
# lts# 为整个网站开启五秒盾server {    waf_under_attack on file=/path/to/under_attack.html;}# 为某个路径开启五秒盾location /path {    waf_under_attack on file=/path/to/under_attack.html;}# current# 为整个网站开启五秒盾server {    waf_under_attack on;}# 为某个路径开启五秒盾location /path {    waf_under_attack on;}  
5效果测试
如需更多帮助,可以参考 如何测试!
当我们部署和配置服务完成之后,需要测试下防火墙是否正常起作用了,可以通过如下方式进行简单的测试来判断规则是否正常运行。
# 测试时的配置master_process on;worker_processes  1;http {    server {        listen 80;        server_name  localhost;        access_log off;        waf on;        waf_mode dynamic !cc !post;        waf_rule_path /usr/local/src/ngx_waf/rules/;        waf_cache capacity=6000 interval=1h percent=50;        location / {            default_type text/html;            return 200 'hello';        }    }}  
[1] 简易测试
运行下列命令,如果输出 403 则表示模块正常工作
$ curl -i -o /dev/null --user-agent bench     -s -w %{http_code}\n https://example.com  
[2] 自动测试
项目附带了许多测试用例,你可以通过下面的指令来运行全部的用例
# 这行命令的执行时间比较长$ cpan test::nginx# 如果目录已经存在则会先删除再创建$ export module_test_path=/path/to/temp/dir# 如果你安装了动态模块则需要指定动态模块的绝对路径,反之则无需执行这行命令$ export module_path=/path/to/ngx_http_waf_module.so# 自动化测试$ cd ./test/test-nginx$ sh ./init.sh$ sh ./start.sh ./t/*.t# 可以使用wrk工具测试$ wrk -c 100 -d 30m -t 1 -s test/wrk/rand.lua --latency     http://localhost/ -- /path/to/rand-str.txt  
6注意事项
如需更多帮助,可以参考 常见问题与解答!
本模块只保证对 nginx-1.18.0 或更新的版本的兼容性,且不保证与 linux 以外的操作系统的兼容性。这里需要注意的是,模块与 ngx_http_rewrite_module 存在兼容性问题。
当 return 指令生效时,该模块不会生效
当 rewrite 指令造成了返回(如 302 重定向)时,该模块不会生效
所以可以使用 try_files 代替 rewrite 指令,避免上述问题的出现
# rewriteif (!-e $request_filename) {    rewrite (.*) /index.php}# try_filestry_files $uri $uri/ /index.php;  
7参考链接
github 代码仓库
黑白名单规则说明
检测项目规则优先级
模块的内置变量
日志相关的配置说明


单片机和手机通信的方法
对于铅酸蓄电池而言,我们该如何对它进行保养
氖泡发光是在特斯拉放电什么时刻产生的呢?
无人机蜂群在物流等诸多方面获得落地?
Adobe Flash Player获得最后一次更新
使用Nginx三方扩展ngx_waf快速实现一个高性能的Web应用防火墙
ANet-2E4SM模块化通信管理机概述及功能特点
霍尔元件损坏的原因
SLOT 2插槽
MiniGPT-4,开源了!
变速箱进水 变速箱进水怎么处理
取消了耳机接口的小米6你还会喜欢吗? 当然还有黑科技
微软正在开发Cloud PC:可访问远程Windows桌面和软件 Microsoft Office
工业互联网的发展需要哪些基本要素
【节能学院】高速公路配电室环境监控系统的应用探讨
图解小米上市 会成为港股的下一个“腾讯”吗?
影响远程访问性能的因素有哪些?远程访问性能优化建议介绍
AGV小车在3C电子行业具备什么优势
彩晶在今年正式打入大陆车载面板供应链
电子爱好者常备的工具和物品,Electronic amateurs tools and items