前言
v2ray搭的梯子,我用了一个web模板页面掩人耳目,但是开放的web给vps增加了安全风险。得想个办法,把这个开放的web防护起来。那就自制一个WAF咯,我的梯子本身是v2ray+ws+tls+web这个模式,已经安装了Nginx软件(用于反向代理,及搭建web服务)。自制WAF基于Nginx,再安装Modsecurity软件,配置一下就完事。
Nginx动态加载Modsecurity自制WAF
安装Modsecurity
安装依赖包
1 | root@vultr:~# apt install -y apt-utils autoconf automake build-essential git libcurl4-openssl-dev libgeoip-dev liblmdb-dev libpcre++-dev libtool libxml2-dev libyajl-dev pkgconf wget zlib1g-dev |
下载ModSecurity 3.0源码
1 | root@vultr:~# git clone --depth 1 -b v3/master --single-branch https://github.com/SpiderLabs/ModSecurity |
以下步骤是在编译libmodsecurity
。大约会花15分钟时间,取决于系统的处理能力。
1 | root@vultr:~/ModSecurity# git submodule init |
下载Modsecurity-Nginx连接器
1 | root@vultr:~# git clone --depth 1 https://github.com/SpiderLabs/ModSecurity-nginx.git |
Nginx动态加载Modsecurity模块
因为我本机是用apt直接安装的Nginx,需要用源码编译安装对应版本的Nginx,动态加载Modsecurity模块。
我的Nginx版本是Nginx/1.14.0:
1 | root@vultr:~# nginx -v |
下载Nginx/1.14.0源码,编译生成ngx_http_modsecurity_module.so
注意:以下的编译过程,将导致nginx配置文件检查失败,报错nginx: [emerg] module "/usr/share/nginx/modules/ngx_http_modsecurity_module.so" is not binary compatible in /etc/nginx/nginx.conf:4
以下操作将导致报错
1
2
3
4
5
6root@vultr:~# wget http://nginx.org/download/nginx-1.14.0.tar.gz
root@vultr:~# tar zxvf nginx-1.14.0.tar.gz
root@vultr:~# cd nginx-1.14.0/
root@vultr:~/nginx-1.14.0# ./configure --with-compat --add-dynamic-module=../ModSecurity-nginx
root@vultr:~/nginx-1.14.0# make modules
root@vultr:~/nginx-1.14.0/objs# cp ngx_http_modsecurity_module.so /usr/share/nginx/modules/
因为我的vps已经用apt方式安装了Nginx,所以在动态编译第三方模块时,要确保和我已安装的Nginx有相同的编译参数。这个方法参考了github的回答
第一步:nginx -t
查看已安装的Nginx有哪些编译参数
第二步:下载源码,重新编译一版Nginx,在已安装Nginx的编译参数基础上,加上动态编译参数--add-dynamic-module=../ModSecurity-nginx
第三步:生成模块ngx_http_modsecurity_module.so
第四步:将生成的模块ngx_http_modsecurity_module.so
复制到已安装Nginx的modules目录/usr/share/nginx/modules/
注意:由于我的ubuntu系统没有安装OpenSSL
和HTTP XSLT
这两个软件的依赖包,导致编译错误。所以,先安装这两款软件的依赖包。
OpenSSL:依赖包安装
HTTP XSLT:依赖包安装
1 | apt-get install openssl libssl-dev |
点击展开正确的操作步骤
1
2
3
4
5
6root@vultr:~# wget http://nginx.org/download/nginx-1.14.0.tar.gz
root@vultr:~# tar zxvf nginx-1.14.0.tar.gz
root@vultr:~# cd nginx-1.14.0/
root@vultr:~/nginx-1.14.0# ./configure --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-GkiujU/nginx-1.14.0=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_geoip_module=dynamic --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module --add-dynamic-module=../ModSecurity-nginx
root@vultr:~/nginx-1.14.0# make modules
root@vultr:~/nginx-1.14.0/objs# cp ngx_http_modsecurity_module.so /usr/share/nginx/modules/
Nginx配置文件加载动态模块
修改Nginx配置文件/etc/nginx/nginx.conf
,添加代码:
1 | load_module modules/ngx_http_modsecurity_module.so; |
如图:
开启Modsecurity的拦截模式
下载推荐配置文件:
1 | root@vultr:/etc/nginx# wget -P /etc/nginx/modsec/ https://raw.githubusercontent.com/SpiderLabs/ModSecurity/v3/master/modsecurity.conf-recommended |
修改配置文件modsecurity.conf
,将SecRuleEngine DetectionOnly
改为SecRuleEngine On
,意思是将Modesecurity的监控模式改为拦截模式。
创建一条测试用的规则
增加配置文件:/etc/nginx/modsec/main.conf
:
点击展开main.conf
1
2
3
4
5
6
7
8# From https://github.com/SpiderLabs/ModSecurity/blob/master/
# modsecurity.conf-recommended
#
# Edit to set SecRuleEngine On
Include "/etc/nginx/modsec/modsecurity.conf"
# Basic test rule
SecRule ARGS:testparam "@contains test" "id:1234,deny,status:403"
对Nginx的server开启Modsecurity防护
修改Nginx配置文件:/etc/nginx/sites-enabled/default
,添加以下代码:
1 | modsecurity on; |
nginx配置文件检查报错
可是现在nginx -t
遇到了报错。
报错信息
1
2
3root@vultr:/usr/share/nginx/modules# nginx -t
nginx: [emerg] "modsecurity_rules_file" directive Rules error. File: /etc/nginx/modsec/modsecurity.conf. Line: 236. Column: 17. Failed to locate the unicode map file from: unicode.mapping Looking at: 'unicode.mapping', 'unicode.mapping', '/etc/nginx/modsec/unicode.mapping', '/etc/nginx/modsec/unicode.mapping'. in /etc/nginx/sites-enabled/default:25
nginx: configuration file /etc/nginx/nginx.conf test failed
解决方法:
将/etc/nginx/conf.d/modsecurity.conf
和unicode.mapping
放到同一个目录。(报错信息就是说unicode.mapping
这个文件的位置放错了,所以我移把它移动到了正确位置)
1 | root@vultr:/usr/share/nginx/modules# find / -name unicode.mapping |
好的,现在nginx -t
终于显示成功了。
1 | root@vultr:/usr/share/nginx/modules# nginx -t |
重启Nginx服务,测试防护效果
重启Nginx:
1 | root@vultr:/usr/share/nginx/modules# nginx -s reload |
测试防护效果:curl我们的web服务,加上参数testparam=test
,如果返回403 Forbidden
,就说明防护规则已生效。
1 | root@vultr:/usr/share/nginx/modules# curl https://我的servername:我的serverport/?testparam=test |
总结
在Nginx动态加载第三方模块时,出现错误ngx_http_modsecurity_module.so is not binary compatible
,解决这个问题花了很多时间。因为第一次接触到Nginx动态加载模块,不懂原理。Nginx加载模块,分为了静态加载和动态加载。这两者的区别在网上可以查到。像我这种情况,Nginx本身在运行服务,要在线增加第三方模块,使用动态编译,就不会破坏已经配置的Nginx,只是增加一个功能模块,重载Nginx服务,就相当于新增一个功能,原有功能不受影响。
现在只是把WAF安装到了vps,简单测试了WAF的效果。具体的策略规则这些,还需要进一步研究并配置。主要是用modsecurity的配置文件main.conf
来控制防护策略。
参考
官方文档:主要是参考这个文档做的,不能完全照搬,按官方操作,编译ngx_http_modsecurity_module.so的时候会报错