使用Nginx+Lua实现的WAF网站防护功能
一.OpenResty安装和测试
官方网站:https://openresty.org/cn/
OpenResty®
OpenResty® 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。
OpenResty® 通过汇聚各种设计精良的 Nginx 模块(主要由 OpenResty 团队自主开发),从而将 Nginx 有效地变成一个强大的通用 Web 应用平台。这样,Web 开发人员和系统工程师可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,快速构造出足以胜任 10K 乃至 1000K 以上单机并发连接的高性能 Web 应用系统。
OpenResty® 的目标是让你的Web服务直接跑在 Nginx 服务内部,充分利用 Nginx 的非阻塞 I/O 模型,不仅仅对 HTTP 客户端请求,甚至于对远程后端诸如 MySQL、PostgreSQL、Memcached 以及 Redis 等都进行一致的高性能响应。
LUA学习:http://blog.jobbole.com/70480/
1.安装OpenResty:
# yum install -y readline-devel pcre-devel openssl-devel
# cd /usr/local/src
下载并编译安装openresty
# wget https://openresty.org/download/ngx_openresty-1.9.3.2.tar.gz
# tar zxf ngx_openresty-1.9.3.2.tar.gz
# cd ngx_openresty-1.9.3.2
# ./configure --prefix=/usr/local/ngx_openresty-1.9.3.2 \
--with-luajit --with-http_stub_status_module \
--with-pcre --with-pcre-jit
# gmake && gmake install
# ln -s /usr/local/openresty-1.9.3.2/ /usr/local/openresty
#报错提醒:
在./configure时的报错:
/usr/bin/env: perl: No such file or directory
出现这种错误可能是没有安装perl,解决yum install perl -y
[root@localhost ngx_openresty-1.9.3.2]# ./configure --prefix=/usr/local/openresty-1.9.3.2 \--with-luajit --with-http_stub_status_module \--with-pcre --with-pcre-jitplatform: linux (linux)cp -rp bundle/ buildcd buildcd LuaJIT-2.1-20151028Can't exec "cc": No such file or directory at ./configure line 588.gmake TARGET_STRIP=@: CCDEBUG=-g CC=cc PREFIX=/usr/local/openresty-1.9.3.2/luajit==== Building LuaJIT 2.1.0-beta1 ====gmake -C srcgmake[1]: cc: Command not foundgmake[1]: Entering directory `/usr/local/ngx_openresty-1.9.3.2/build/LuaJIT-2.1-20151028/src'gmake[1]: cc: Command not foundgmake[1]: cc: Command not foundgmake[1]: cc: Command not foundgmake[1]: cc: Command not foundgmake[1]: cc: Command not foundMakefile:237: *** Unsupported target architecture. Stop.gmake[1]: Leaving directory `/usr/local/ngx_openresty-1.9.3.2/build/LuaJIT-2.1-20151028/src'gmake: *** [default] Error 2ERROR: failed to run command: gmake TARGET_STRIP=@: CCDEBUG=-g CC=cc PREFIX=/usr/local/openresty-1.9.3.2/luajit
解决:
yum install *gcc* -y
2.测试openresty安装:
vim /usr/local/openresty/nginx/conf/nginx.conf
server { listen 80; server_name localhost; location / { root html; index index.html index.htm; } ......此处省略 }
在此处省略处,添加一行
location /hello { default_type text/html; content_by_lua_block { ngx.say("HelloWorld") }
3.启动openresty并测试:
/usr/local/openresty/nginx/sbin/nginx -t
/usr/local/openresty/nginx/sbin/nginx
[root@localhost ~]# curl http://10.0.0.50/helloHelloWorld
4. 性能测试
-- 1. 安装压力测试工具
[root@localhost ~]# yum install httpd-tools -y
-- 2. 测试
[root@localhost ~]# ab -c10 -n5000 http://10.0.0.50/helloThis is ApacheBench, Version 2.3 <$Revision: 1430300 $>Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/Licensed to The Apache Software Foundation, http://www.apache.org/Benchmarking 10.0.0.50 (be patient)Completed 500 requestsCompleted 1000 requestsCompleted 1500 requestsCompleted 2000 requestsCompleted 2500 requestsCompleted 3000 requestsCompleted 3500 requestsCompleted 4000 requestsCompleted 4500 requestsCompleted 5000 requestsFinished 5000 requestsServer Software: openresty/1.9.3.2Server Hostname: 10.0.0.50Server Port: 80Document Path: /helloDocument Length: 11 bytesConcurrency Level: 10Time taken for tests: 0.505 secondsComplete requests: 5000Failed requests: 0Write errors: 0Total transferred: 790000 bytesHTML transferred: 55000 bytesRequests per second: 9901.83 [#/sec] (mean)Time per request: 1.010 [ms] (mean)Time per request: 0.101 [ms] (mean, across all concurrent requests)Transfer rate: 1527.82 [Kbytes/sec] receivedConnection Times (ms) min mean[+/-sd] median maxConnect: 0 0 0.2 0 1Processing: 0 1 0.3 1 2Waiting: 0 0 0.2 0 2Total: 1 1 0.3 1 3Percentage of the requests served within a certain time (ms) 50% 1 66% 1 75% 1 80% 1 90% 1 95% 2 98% 2 99% 2 100% 3 (longest request)
...
需求产生 由于原生态的Nginx的一些安全防护功能有限,就研究能不能自己编写一个WAF,参考(照抄)Kindle大神的ngx_lua_waf,自己尝试写一个了,使用两天时间,边学Lua,边写。不过不是安全专业,只实现了一些比较简单的功能:
####功能列表:
支持IP白名单和黑名单功能,直接将黑名单的IP访问拒绝。
支持URL白名单,将不需要过滤的URL进行定义。
支持User-Agent的过滤,匹配自定义规则中的条目,然后进行处理(返回403)。
支持CC***防护,单个URL指定时间的访问次数,超过设定值,直接返回403。
支持Cookie过滤,匹配自定义规则中的条目,然后进行处理(返回403)。
支持URL过滤,匹配自定义规则中的条目,如果用户请求的URL包含这些,返回403。
支持URL参数过滤,原理同上。
支持日志记录,将所有拒绝的操作,记录到日志中去。
日志记录为JSON格式,便于日志分析,例如使用ELKStack进行***日志收集、存储、搜索和展示。
####WAF实现 WAF一句话描述,就是解析HTTP请求(协议解析模块),规则检测(规则模块),做不同的防御动作(动作模块),并将防御过程(日志模块)记录下来。所以本文中的WAF的实现由五个模块(配置模块、协议解析模块、规则模块、动作模块、错误处理模块)组成。