WAF
waf
使用Nginx+Lua实现自定义WAF(Web application firewall)
功能列表:
- 支持IP白名单和黑名单功能,直接将黑名单的IP访问拒绝。
- 支持URL白名单,将不需要过滤的URL进行定义。
- 支持User-Agent的过滤,匹配自定义规则中的条目,然后进行处理(返回403)。
- 支持CC攻击防护,单个URL指定时间的访问次数,超过设定值,直接返回403。
- 支持Cookie过滤,匹配自定义规则中的条目,然后进行处理(返回403)。
- 支持URL过滤,匹配自定义规则中的条目,如果用户请求的URL包含这些,返回403。
- 支持URL参数过滤,原理同上。
- 支持日志记录,将所有拒绝的操作,记录到日志中去。
- 日志记录为JSON格式,便于日志分析,例如使用ELKStack进行攻击日志收集、存储、搜索和展示。
WAF实现 WAF一句话描述,就是解析HTTP请求(协议解析模块),规则检测(规则模块),做不同的防御动作(动作模块),并将防御过程(日志模块)记录下来。所以本文中的WAF的实现由五个模块(配置模块、协议解析模块、规则模块、动作模块、错误处理模块)组成。
安装nginx并配置禁止使用wget或者ab来访问web
安装nginx
# yum -y install nginx
配置nginx.conf文件
# vim /etc/nginx/nginx.conf
添加nginx.conf中的server段的内容如下
set $block_user_agent 0;
if ($http_user_agent ~ "Wget|ApacheBench" ) {
set $block_user_agent 1;
}
if ($block_user_agent = 1) {
return 403;
}
注:
添加的代码限制了wget和ab压力测试的使用,限制的用户浏览器的访问使用
检查nginx.conf的配置文件
# nginx -t
启动nginx的服务
# systemctl start nginx.service
使用wget或者ab来测试下配置文件中的对wget和ab的限制是否生效
# wget http://192.168.1.120/
--2017-05-27 21:37:13-- http://192.168.1.120/
Connecting to 192.168.1.120:80... connected.
HTTP request sent, awaiting response... 403 Forbidden
2017-05-27 21:37:13 ERROR 403: Forbidden.
修改nginx.conf配置文件,限制下载sql|bak|zip|tgz|tar.gz为后缀名的文件
server端中添加如下内容
location ~* ".(sql|bak|zip|tgz|tar.gz)$" {
return 404;
}
验证nginx配置文件是否正确,并重新加载nginx服务
# nginx -t
# stystemctl reload nginx
测试配置文件生效以后的效果
# touch /usr/share/nginx/html/1.sql
# curl -I http://192.168.1.120/1.sql
HTTP/1.1 404 Not Found
Server: nginx/1.10.2
Date: Sat, 27 May 2017 13:57:35 GMT
Content-Type: text/html
Content-Length: 3650
Connection: keep-alive
ETag: "58173aee-e42"
免费的开源WAF防护模块
WAF防护模块地址
http://www.modsecurity.org/
优点:开源界最好的
缺点:对并发影响特比大,性能下降
如何自己写一个WAF呢?
解析HTTP请求,然后规则匹配,做防御动作,并记录日志
协议解析模块
规则检测模块 规则库
防御动作,返回403 404..
日志记录模块,保存为json格式,用于ELK的分析绘图
部署OpenResty
官方地址
http://openresty.org/cn/
官方安装文档地址
http://openresty.org/cn/installation.html
软件包下载地址
http://openresty.org/cn/download.html
安装依赖包
# yum -y install readline-devel pcre-devel openssl-devel gcc
下载openresty
# cd /usr/local/src/ && wget -c https://openresty.org/download/ngx_openresty-1.9.7.2.tar.gz
解压openresty
# tar -zxvf ngx_openresty-1.9.7.2.tar.gz
源码编译安装openresty
# cd ngx_openresty-1.9.7.2/
# ./configure --prefix=/usr/local/openresty-1.9.7.2
--with-luajit
--with-http_stub_status_module
--with-pcre
--with-pcre-jit
# gmake && gmake install
创建软连接
# ln -sv /usr/local/openresty-1.9.7.2/ /usr/local/openresty
编辑nginx.conf的配置文件并在server段中添加如下内容,测试openresty
# vim /usr/local/openresty/nginx/conf/nginx.conf
location /demon {
default_type text/html;
content_by_lua_block {
ngx.say("hello,demon")
}
}
检测nginx.conf的配置文件
# nginx -t
关闭yum安装的nginx并启用openresty提供的nginx
# systemctl stop nginx
# /usr/local/openresty/nginx/sbin/nginx
测试请求
# curl http://192.168.1.120/demon
hello,demon
WAF部署
下载git上的WAF的资源
#git clone https://github.com/unixhot/waf.git
#cp -a ./waf/waf /usr/local/openresty/nginx/conf/
修改nginx.conf配置文件,并在http段添加如下内容
#WAF
lua_shared_dict limit 50m;
lua_package_path "/usr/local/openresty/nginx/conf/waf/?.lua";
init_by_lua_file "/usr/local/openresty/nginx/conf/waf/init.lua";
access_by_lua_file "/usr/local/openresty/nginx/conf/waf/access.lua";
测试nginx的配置文件
# /usr/local/openresty/nginx/sbin/nginx -t
启动nginx服务
# /usr/local/openresty/nginx/sbin/nginx -s reload
日志保存到/tmp/日期_waf.log