0%

vps加固之通过Nginx动态加载modesucurity自制WAF

前言

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
2
3
4
5
6
7
root@vultr:~/ModSecurity# git submodule init
root@vultr:~/ModSecurity# git submodule update
root@vultr:~/ModSecurity# ./build.sh
#注意:这一步出现`fatal: No names found, cannot describe anything.`报错,不用管它。
root@vultr:~/ModSecurity# ./configure
root@vultr:~/ModSecurity# make
root@vultr:~/ModSecurity# make install

下载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
2
root@vultr:~# nginx -v
nginx version: nginx/1.14.0 (Ubuntu)

下载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
6
root@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系统没有安装OpenSSLHTTP XSLT这两个软件的依赖包,导致编译错误。所以,先安装这两款软件的依赖包。
OpenSSL:依赖包安装
HTTP XSLT:依赖包安装

1
2
3
4
apt-get install openssl libssl-dev
apt-get install libxslt-dev
apt-get install libgd-dev
apt-get install libgeoip-dev
点击展开正确的操作步骤

1
2
3
4
5
6
root@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;

如图:
image.png

开启Modsecurity的拦截模式

下载推荐配置文件:

1
2
3
root@vultr:/etc/nginx# wget -P /etc/nginx/modsec/ https://raw.githubusercontent.com/SpiderLabs/ModSecurity/v3/master/modsecurity.conf-recommended
root@vultr:/etc/nginx# cd modsec/
root@vultr:/etc/nginx/modsec# mv modsecurity.conf-recommended modsecurity.conf

修改配置文件modsecurity.conf,将SecRuleEngine DetectionOnly改为SecRuleEngine On,意思是将Modesecurity的监控模式改为拦截模式。
image.png

创建一条测试用的规则

增加配置文件:/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
2
modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/main.conf;

image.png

nginx配置文件检查报错

可是现在nginx -t遇到了报错。

报错信息

1
2
3
root@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.confunicode.mapping放到同一个目录。(报错信息就是说unicode.mapping这个文件的位置放错了,所以我移把它移动到了正确位置)

1
2
3
4
5
root@vultr:/usr/share/nginx/modules# find / -name unicode.mapping
/root/ModSecurity/unicode.mapping
root@vultr:/usr/share/nginx/modules# mv /root/ModSecurity/unicode.mapping /etc/nginx/modsec/
root@vultr:/usr/share/nginx/modules# ls /etc/nginx/modsec/unicode.mapping
/etc/nginx/modsec/unicode.mapping

好的,现在nginx -t终于显示成功了。

1
2
3
root@vultr:/usr/share/nginx/modules# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

重启Nginx服务,测试防护效果

重启Nginx:

1
2
root@vultr:/usr/share/nginx/modules# nginx -s reload
root@vultr:/usr/share/nginx/modules# service nginx restart

测试防护效果:curl我们的web服务,加上参数testparam=test,如果返回403 Forbidden,就说明防护规则已生效。

1
2
3
4
5
6
7
8
root@vultr:/usr/share/nginx/modules# curl https://我的servername:我的serverport/?testparam=test
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx</center>
</body>
</html>

总结

在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的时候会报错

-------------本文结束感谢您的阅读-------------