1. 目标
为了保护Web服务安全稳定,部署Web应用防火墙(Web Application Firewall, WAF),通过对HTTP(S)请求举行检测,识别并阻断SQL注入、跨站脚本攻击(Cross Site Scripting, XSS)、网页木马上传、命令/代码注入、文件包罗、敏感文件访问、第三方应用毛病攻击、CC(寻衅黑洞)攻击、恶意爬虫扫描、跨站请求伪造等攻击。
2. 架构
(架构图)
3. 实现功能
- 支持IP白名单和黑名单功能,直接将黑名单的IP访问拒绝。
- 支持URL白名单,将不需要过滤的URL举行界说。
- 支持User-Agent的过滤,匹配自界说规则中的条目,然后举行处置处罚(返回403)。
- 支持CC攻击防护,单个URL指定时间的访问次数,超过设定值,直接返回403。
- 支持Cookie过滤,匹配自界说规则中的条目,然后举行处置处罚(返回403)。
- 支持URL过滤,匹配自界说规则中的条目,如果用户请求的URL包罗这些,返回403。
- 支持URL参数过滤,原理同上。
- 支持日志记录,将所有拒绝的操纵,记录到日志中去。
- 日志记录为JSON格式,便于日志分析,例如使用ELKStack举行攻击日志网络、存储、搜刮和展示。
4. 构建WAF的方案
- 开源框架openresty+nginx 实现web应用防火墙(WAF)
- 官网: https://openresty.org/cn/download.html
- nginx lua lua-nginx-module构建web应用防火墙(WAF)
- https://github.com/unixhot/waf
- 项目地址: https://github.com/SpiderLabs/ModSecurity
- 项目地址: https://github.com/qq4108863/hihttps
- 项目地址: https://github.com/titansec/OpenWAF
- FreeWAF
- ESAPI WAF
- Java WAF
- 项目地址: https://github.com/chengdedeng/waf
- 项目地址: https://github.com/nbs-system/naxsi
- 项目地址: https://github.com/xsec-lab/x-waf
- 项目地址: https://github.com/alexazhou/VeryNginx/
5. 安装openresty
5.1. 安装依赖
登录后复制 - yum install pcre-devel openssl-devel readline-devel gcc gcc-c++ curl wget -y
复制代码
5.2. 下载openresty
下载地址:
- https://github.com/openresty/openresty/releases
- https://openresty.org/download/
登录后复制 - wget https://github.com/openresty/openresty/releases/download/v1.15.8.2/openresty-1.15.8.2.tar.gz
复制代码
5.3. 解压openresty
登录后复制 - tar -zxvf openresty-1.15.8.2.tar.gz
- cd openresty-1.15.8.2
复制代码
5.4. 编译安装openresty
登录后复制 - ./configure --with-http_stub_status_module --with-http_ssl_module --with-pcre --with-pcre-jit --with-luajit
- gmake
- gmake install
复制代码
参数阐明:
- --with-http_stub_status_module nginx监控模块
- --with-http_ssl_module nginx ssl模块
6. 安装WAF
6.1. 下载WAF
登录后复制 - git clone https://github.com/unixhot/waf.git
- cp -a ./waf/waf/ /usr/local/nginx/conf/
复制代码
6.2. 设置WAF
登录后复制 - vi /usr/local/nginx/conf/nginx.conf
复制代码
在nginx.conf的http字段内添加以下内容:
登录后复制 - #WAF
- lua_shared_dict limit 50m; #防cc使用字典,大小50M
- lua_package_path "/usr/local/nginx/conf/waf/?.lua";
- init_by_lua_file "/usr/local/nginx/conf/waf/init.lua";
- access_by_lua_file "/usr/local/nginx/conf/waf/access.lua";
复制代码
根据日志记录位置,创建日志目录:
登录后复制 - mkdir /tmp/waf_logs
- chown -R nginx.nginx /tmp/waf_logs
复制代码
注意:日志目录权限与nginx启动权限相同
WAF上生产之前,发起不要直接上生产,而是先记录日志,不做任何动作。确定WAF不产生误杀。
登录后复制 - vi /usr/local/nginx/conf/waf/config.lua
复制代码
登录后复制 - config_log_dir = "/tmp/waf_logs" #日志记录地址
- --rule setting
- config_rule_dir = "/usr/local/nginx/conf/waf/rule-config"
复制代码
学习access.lua的设置
序次:先检查白名单,通过即不检测;再检查黑名单,不通过即拒绝,检查UA,UA不通过即拒绝;检查cookie;URL检查;URL参数检查,post检查;
6.3. 启动WAF
登录后复制 - /usr/local/openresty/nginx/sbin/nginx -t
- /usr/local/openresty/nginx/sbin/nginx -s reload
复制代码
6.4. 设置阐明
登录后复制 - --WAF config file,enable = "on",disable = "off" --waf status config_waf_enable = "on" #是否开启设置--log dir config_log_dir = "/tmp/waf_logs" #日志记录地址
- --rule setting
- config_rule_dir = "/usr/local/nginx/conf/waf/rule-config" #匹配规则缩放地址--enable/disable white url config_white_url_check = "on" #是否开启url检测--enable/disable white ip config_white_ip_check = "on" #是否开启IP白名单检测--enable/disable block ip config_black_ip_check = "on" #是否开启ip黑名单检测--enable/disable url filtering config_url_check = "on" #是否开启url过滤--enalbe/disable url args filtering config_url_args_check = "on" #是否开启参数检测--enable/disable user agent filtering config_user_agent_check = "on" #是否开启ua检测--enable/disable cookie deny filtering config_cookie_check = "on" #是否开启cookie检测--enable/disable cc filtering config_cc_check = "on" #是否开启防cc攻击--cc rate the xxx of xxx seconds config_cc_rate = "10/60" #允许一个ip60秒内只能--enable/disable post filtering config_post_check = "on" #是否开启post检测--config waf output redirect/html config_waf_output = "html" #action一个html页面,也可以选择跳转--if config_waf_output ,setting url config_waf_redirect_url = "http://www.baidu.com" config_output_html=[[ #下面是html的内容<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Language" content="zh-cn" /><title>网站防火墙</title> </head> <body> <h1 align="center"> 您的行为已违背本网站相干规定,注意操纵规范。</h1></body> </html>
复制代码
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
7. 安装包
- Luajit: http://luajit.org/
- Nginx: http://nginx.org/download/
- ngx_devel_kit: https://github.com/simpl/ngx_devel_kit/archive/v0.3.0.tar.gz
- lua-nginx-module: https://github.com/openresty/lua-nginx-module/releases
8. 安装依赖
登录后复制 - yum install -y readline-devel pcre-devel openssl-devel gcc gcc-c++ lua-devel wget
复制代码
9. 解压NDK和lua-nginx-module
登录后复制 - tar zxvf lua-nginx-module-0.10.10.tar.gz
- tar zxvf ngx_devel_kit-0.3.0.tar.gz
复制代码
10. 安装LuaJIT
10.1. 下载LuaJIT
登录后复制 - git clone https://github.com/openresty/luajit2
复制代码
10.2. 编译并安装LuaJIT
登录后复制
10.3. 设置环境变量
登录后复制 - cat >/etc/profile.d/luajit.sh<<EOF
- export LUAJIT_LIB=/usr/local/lib
- export LUAJIT_INC=/usr/local/include/luajit-2.1
- EOF
复制代码
10.4. 加载环境变量
登录后复制
11. 安装lua-cjson
11.1. 下载lua-cjson
https://www.kyne.com.au/~mark/software/download/lua-cjson-2.1.0.tar.gz
11.2. 解压
登录后复制 - tar zxvf lua-cjson-2.1.0.tar.gz
- cd lua-cjson-2.1.0
复制代码
11.3. 设置lua-cjson
登录后复制
选择其中一个修改Makefile文件
登录后复制 - ##### Build defaults #####
- LUA_VERSION = 5.1
- TARGET = cjson.so
- PREFIX = /usr/local
- #CFLAGS = -g -Wall -pedantic -fno-inline
- CFLAGS = -O3 -Wall -pedantic -DNDEBUG
- CJSON_CFLAGS = -fpic
- CJSON_LDFLAGS = -shared
- LUA_INCLUDE_DIR = /root/luajit2/src
- LUA_CMODULE_DIR = $(PREFIX)/lib/lua/$(LUA_VERSION)
- LUA_MODULE_DIR = $(PREFIX)/share/lua/$(LUA_VERSION)
- LUA_BIN_DIR = $(PREFIX)/bin
复制代码
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
11.4. 安装lua-cjson
登录后复制
报luaL_setfuncs错解决:
登录后复制
将static去掉static void luaL_setfuncs (lua_State *l, const luaL_Reg *reg, int nup)
登录后复制
12. 重新编译nginx
12.1. 升级或新安装
使用新版本升级
登录后复制 - wget http://nginx.org/download/nginx-1.16.1.tar.gz
- tar zxvf nginx-1.16.1.tar.gz
- cd nginx-1.16.1
复制代码
12.2. 编译nginx
登录后复制 - ./configure --user=nginx --group=nginx --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_sub_module --with-http_gzip_static_module --add-module=../ngx_devel_kit-0.3.0/ --add-module=../lua-nginx-module-0.10.15/
复制代码
编译完成了,执行make,记住,这里不要执行make install,不然会把以前安装的会覆盖的
登录后复制
参数阐明:
- --with-http_stub_status_module nginx监控模块
- --with-http_ssl_module nginx ssl模块
- --ngx_http_sub_module模块是一个过滤器,通过将一个指定的字符串更换为另一个字符串来修改相应
- --with-http_gzip_static_module 启动预压缩功能
12.3. 创建毗连
登录后复制 - ln -s /usr/local/lib/libluajit-5.1.so.2 /lib64/libluajit-5.1.so.2
复制代码
12.4. 验证nginx
编译完成后,会新生成一个nginx执行文件,在nginx-1.16.1/objs目录下,测试一下对应的依赖有没有装上
登录后复制 - cd nginx-1.16.1/objs
- ./nginx -V
复制代码
12.5. 备份nginx
复制nginx命令覆盖以前的nginx
复制前,最好把之前的nginx备份一下,以防不测
登录后复制 - cd /usr/local/nginx/sbin/
- cp nginx nginx.old
复制代码
12.6. 覆盖nginx
新的覆盖,覆盖之前,最好停掉nginx
登录后复制 - cd nginx-1.16.1/
- cp objs/nginx /usr/local/nginx/sbin/
复制代码
修改nginx设置在http块下设置
登录后复制
12.7. 测试nginx
先测试nginx有没有被玩坏,先检查一下
登录后复制 - cd /usr/local/nginx
- ./sbin/nginx -t
- ./sbin/nginx
复制代码
接下来部署WAF方法和上面一样
13. 测试WAF功能
13.1. 模拟sql注入即url攻击
登录后复制 - http://10.8.17.32/abc.sql
复制代码
登录后复制 - [root@localhost waf]# cat /tmp/waf_logs/2019-12-20_waf.log
复制代码
日志表现如下,记录了
登录后复制 - {"user_agent":"Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/71.0.3573.0 Safari\/537.36","rule_tag":"\\.(bak|inc|old|mdb|sql|backup|java|class|tgz|gz|tar|zip)$","req_url":"\/abc.sql","client_ip":"10.8.80.104","local_time":"2019-12-20 14:37:29","attack_method":"Deny_URL","req_data":"-","server_name":"localhost"}
复制代码
日志记录了UA、匹配规则、请求URL、客户端IP、当地时间、攻击方法、请求数据和服务器名称。
13.2. 使用ab压测工具模拟防cc攻击
登录后复制 - yum -y install httpd-tools
- ab -n 1000 -c 500 http://10.8.17.32/
复制代码
13.3. 模拟ip黑名单
将请求ip放入ip黑名单中
登录后复制 - echo "10.8.17.32" >>/usr/local/nginx/conf/waf/rule-config/blackip.rule
复制代码
13.4. 模拟ip白名单
将请求ip放入ip白名单中,此时将不对此ip举行任何防护措施,所以sql注入时应该返回404
登录后复制 - echo "10.8.17.32" >> /usr/local/nginx/conf/waf/rule-config/whiteip.rule
复制代码
13.5. 模拟URL参数检测
浏览器输入http://10.8.17.32/?id=select * from name where name="jack"
具体规定在arg.rule中有规定,对请求举行了规范
14. 防cc攻击利器之httpgrard
14.1. httpgrard介绍
HttpGuard是基于openresty,以lua脚本语言开发的防cc攻击软件。而openresty是集成了高性能web服务器Nginx,以及一系列的Nginx模块,这其中最紧张的,也是我们主要用到的nginx lua模块。HttpGuard基于nginx lua开发,继续了nginx高并发,高性能的特点,可以以非常小的性能消耗来防范大规模的cc攻击。
14.2. httpgrard防cc殊效
- 限制访客在肯定时间内的请求次数
- 向访客发送302转向相应头来识别恶意用户,并克制其再次访问
- 向访客发送带有跳转功能的js代码来识别恶意用户,并克制其再次访问
- 向访客发送cookie来识别恶意用户,并克制其再次访问
- 支持向访客发送带有验证码的页面,来进一步识别,以免误伤
- 支持直接断开恶意访客的毗连
- 支持结合iptables来克制恶意访客再次毗连
- 支持白名单功能
- 支持根据统计特定端口的毗连数来自动开启或关闭防cc模式
详见github地址 https://github.com/centos-bz/HttpGuard
15. WAF上线
初期上线只记录日志,不开启WAF,防止误杀。
WAF规则管理使用saltstack工具。
要知道并不是有了WAF就安全,安全在很大一部分是人为因素。
16. FAQ
16.1. FAQ1
运行报错:
登录后复制 - nginx: [error] lua_load_resty_core failed to load the resty.core module from https://github.com/openresty/lua-resty-core; ensure you are using an OpenResty release from https://openresty.org/en/download.html (rc: 2, reason: module 'resty.core' not found:
- no field package.preload['resty.core']
- no file '../lua-resty-core/lib/resty/core.lua'
- no file '../lua-resty-lrucache/lib/resty/core.lua'
- no file './resty/core.lua'
- no file '/usr/local/share/luajit-2.1.0-beta3/resty/core.lua'
- no file '/usr/local/share/lua/5.1/resty/core.lua'
- no file '/usr/local/share/lua/5.1/resty/core/init.lua'
- no file './resty/core.so'
- no file '/usr/local/lib/lua/5.1/resty/core.so'
- no file '/usr/local/lib/lua/5.1/loadall.so'
- no file './resty.so'
- no file '/usr/local/lib/lua/5.1/resty.so'
- no file '/usr/local/lib/lua/5.1/loadall.so')
复制代码
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
一旦使用了lua-nginx-module就表现使用了openresty,这个resty.core是openresty的核心模块,对其下的许多函数举行了优化等。之前的一些版本默认是不编译进去的,所以需要你手动安装
下面是解决该问题的完整步骤:
登录后复制 - git clone https://github.com/openresty/lua-resty-core.git
复制代码
登录后复制
登录后复制 - export LUAJIT_LIB=/path/to/luajit/lib
- export LUAJIT_INC=/path/to/luajit/include/luajit-2.1
- make install
复制代码
注意将/path/to/luajit/lib和/path/to/luajit/include/luajit-2.1更换为现实的luajit库和头文件路径。
登录后复制 - lua_package_path "/path/to/lua-resty-core/lib/?.lua;;";
- lua_package_cpath "/path/to/lua-resty-core/lib/?.lua;;";
复制代码
将/path/to/lua-resty-core/lib/更换为现实的lua-resty-core安装路径。
登录后复制
这样应该就可以解决lua_load_resty_core失败的问题了。如果还是不行,可以检查一下luajit的路径是否正确,lua-resty-core是否安装成功等。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |