让我们部署自己的 WAF - ModSecurity

Preface#

一些宝塔一键 LNMP 的站长，多半用的第三方的 Nginx 防火墙，虽好，但是规则更新不及时，而且主要针对 PHP 站；如果是其他的站，例如你的站是使用 Halo 搭建的，使用这些规则就不太合适了。让我们使用 ModSecurity（V3）来架设 WAF，并借助 OWASP ModSecurity Core Rule Set (CRS) 来更新我们 WAF 的防护规则。当然 Apache 也可以，但是我很讨厌它

1

Start#

First#

本次环境基于 Debian 11

我们应该准备一下环境，如果你是编译安装的 Nginx，那工作量就减少了很多，当然我们也可以直接拉取源码开始编译。

Copy
wget https://nginx.org/download/nginx-1.18.0.tar.gz
tar zxvf nginx-1.18.0.tar.gz

安装编译依赖

Copy
sudo apt install g++ flex bison curl apache2-dev doxygen libyajl-dev ssdeep liblua5.2-dev libgeoip-dev libtool dh-autoreconf libcurl4-gnutls-dev libxml2 libpcre++-dev libxml2-dev git

如此，我们准备好了编译所需要的依赖包

Second#

安装 ModSecurity

克隆仓库 ModSecurity 仓库

Copy
git clone https://github.com/SpiderLabs/ModSecurity.git --depth=1

注：本文提到的 GitHub 地址，如果你的网络条件不好，可以使用以下镜像地址替代

Copy
https://github.hscsec.cn/

例如

Copy
git clone https://github.hscsec.cn/SpiderLabs/ModSecurity.git

编译安装

Copy
./build.sh
git submodule init
git submodule update
./configure --prefix=/usr/local/modsecurity
make
sudo make install

如此，我们便安装好了 ModSecurity；别急，我们还需要把连接器以模块的形式编译到 Nginx 上

Third#

如果你是宝塔编译安装，那么 /www/server/nginx/src 即你当前使用的 Nginx 编译安装源码

本文以宝塔编译安装的 Nginx 为例

如果你是其他安装，请准备好 Nginx 源码，本文不再赘述

首先查看当前 Nginx 使用的编译参数

Copy
nginx -V

例如，返回如下信息

Copy
configure arguments: --user=www --group=www --prefix=/www/server/nginx --add-module=/www/server/nginx/src/ngx_devel_kit --add-module=/www/server/nginx/src/lua_nginx_module --add-module=/www/server/nginx/src/ngx_cache_purge --add-module=/www/server/nginx/src/nginx-sticky-module --with-openssl=/www/server/nginx/src/openssl --with-pcre=pcre-8.43 --with-http_v2_module --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_stub_status_module --with-http_ssl_module --with-http_image_filter_module --with-http_gzip_static_module --with-http_gunzip_module --with-http_sub_module --with-http_flv_module --with-http_addition_module --with-http_realip_module --with-http_mp4_module --with-ld-opt=-Wl,-E --with-cc-opt=-Wno-error --with-ld-opt=-ljemalloc --with-http_dav_module --with-threads --with-file-aio --with-compat --add-module=/www/server/nginx/src/nginx-dav-ext-module

那么这串内容则是我们需要记录的内容

Copy
--user=www --group=www --prefix=/www/server/nginx --add-module=/www/server/nginx/src/ngx_devel_kit --add-module=/www/server/nginx/src/lua_nginx_module --add-module=/www/server/nginx/src/ngx_cache_purge --add-module=/www/server/nginx/src/nginx-sticky-module --with-openssl=/www/server/nginx/src/openssl --with-pcre=pcre-8.43 --with-http_v2_module --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_stub_status_module --with-http_ssl_module --with-http_image_filter_module --with-http_gzip_static_module --with-http_gunzip_module --with-http_sub_module --with-http_flv_module --with-http_addition_module --with-http_realip_module --with-http_mp4_module --with-ld-opt=-Wl,-E --with-cc-opt=-Wno-error --with-ld-opt=-ljemalloc --with-http_dav_module --with-threads --with-file-aio --with-compat --add-module=/www/server/nginx/src/nginx-dav-ext-module

进入 Nginx 源码

Copy
cd /www/server/nginx/src

克隆连接器仓库

Copy
git clone https://github.com/SpiderLabs/ModSecurity-nginx.git --depth=1

生成 Makefile

Copy
./configure --user=www --group=www --prefix=/www/server/nginx --add-module=/www/server/nginx/src/ngx_devel_kit --add-module=/www/server/nginx/src/lua_nginx_module --add-module=/www/server/nginx/src/ngx_cache_purge --add-module=/www/server/nginx/src/nginx-sticky-module --with-openssl=/www/server/nginx/src/openssl --with-pcre=pcre-8.43 --with-http_v2_module --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_stub_status_module --with-http_ssl_module --with-http_image_filter_module --with-http_gzip_static_module --with-http_gunzip_module --with-http_sub_module --with-http_flv_module --with-http_addition_module --with-http_realip_module --with-http_mp4_module --with-ld-opt=-Wl,-E --with-cc-opt=-Wno-error --with-ld-opt=-ljemalloc --with-http_dav_module --with-threads --with-file-aio --with-compat --add-module=/www/server/nginx/src/nginx-dav-ext-module --add-dynamic-module=/www/server/nginx/src/ModSecurity-nginx --with-compat

编译

Copy
make

#如果你的 CPU 核心数多于 2 个，建议多线程编译，示例如下

make -j 4

我们无需使用 make install ，将 objs 目录下的 Nginx 拷贝到 /www/server/nginx/sbin/ 即可，然后 objs 目录下的 ngx_http_modsecurity_module.so 我们拷贝到 /www/server/nginx/modules/ 如果没有就新建文件夹。部分情况下，该模块直接链接进了 nginx 的二进制文件，所以没有单独的 so 文件，此时默认 nginx 运行默认装载该模块，所以仅需 copy nginx 二进制文件即可。

Copy

# 复制 Nginx
cp -rf objs/nginx ../sbin/nginx
# 复制编译出的 So 模块
mkdir ../modules
cp objs/ngx_http_modsecurity_module.so ../modules/ngx_http_modsecurity_module.so

如此，我们完成了 ModSecurity 以及 Nginx 连接器的安装

Configure#

在 ModSecurity 源码目录下，有两个配置文件，我们可以复制过去，例如

Copy
cp modsecurity.conf-recommended /www/server/nginx/conf/modsecurity.conf

cp unicode.mapping /www/server/nginx/conf/unicode.mapping

克隆 OWASP ModSecurity Core Rule Set 仓库

Copy
cd /www/server/nginx/conf

git clone https://github.com/coreruleset/coreruleset.git --depth=1 wafconf

进入规则目录，编辑配置文件

Copy
cd wafconf

cp crs-setup.conf.example crs-setup.conf

编辑 crs-setup.conf，里面有如下内容

Copy
# 该区块内容表示，根据规则进行威胁评分，超过评分阈值才会采取行动，资源开销较大
97 SecDefaultAction "phase:1,log,auditlog,pass"
98 SecDefaultAction "phase:2,log,auditlog,pass"
# 该区块内容表示，根据规则进行直接拦截，并返回 403
117 SecDefaultAction "phase:1,log,auditlog,deny,status:403"
118 SecDefaultAction "phase:2,log,auditlog,deny,status:403"
# 该区块内容表示，根据规则进行拦截，并重定向到首页
127 SecDefaultAction "phase:1,log,auditlog,redirect:'http://%{request_headers.host}/',tag:'Host: %{request_headers.host}'"
128 SecDefaultAction "phase:2,log,auditlog,redirect:'http://%{request_headers.host}/',tag:'Host: %{request_headers.host}'"

这三种措施，使用其中一种就行，然后注释掉其他两种

我们编辑 modsecurity.conf 文件

里面有如下内容

Copy
SecRuleEngine DetectionOnly

我们需要修改为

Copy
SecRuleEngine On

在文件末尾添加如下内容

Copy
Include /www/server/nginx/conf/wafconf/crs-setup.conf
Include /www/server/nginx/conf/wafconf/rules/*.conf

如此，我们算是配置妥当了，接下来将启动 WAF

Use#

编辑 nginx.conf，位于 /www/server/nginx/conf

引入模块

Copy
load_module /www/server/nginx/modules/ngx_http_modsecurity_module.so;

例如

Copy
user www-data www-data;
worker_processes auto;
error_log /www/wwwlogs/nginx_error.log crit;
pid /www/server/nginx/logs/nginx.pid;
load_module /www/server/nginx/modules/ngx_http_modsecurity_module.so;

开启 ModSecurity

我们可以选择全局开启，例如，在 nginx.conf 的 http 区域块添加如下内容

Copy
modsecurity on;
modsecurity_rules_file /www/server/nginx/conf/modsecurity.conf;

当然，我们可以分别在部分网站开启

在宝塔设定的网站配置文件下进行添加

Copy
cd /www/server/panel/vhost/nginx

例如 test.cn.conf

我们在其 server 区块内添加即可

示例如下

Copy
modsecurity on;
modsecurity_rules_file /www/server/nginx/conf/modsecurity.conf;
access_log /www/wwwlogs/test.cn.log;
error_log /www/wwwlogs/test.cn.error.log;

重载 nginx

Copy
sudo nginx -t
sudo nginx -s reload

或者宝塔 Nginx 重载配置文件

Adjustment#

这样，我们就开启了 WAF；我们都知道最好的规则，未必适合自己，所以我们需要适当开启 / 关闭一些规则

进行网站的日常访问，如果发现异常的情况，请查看 log

WAF 的 log 在 /var/log/modsec_audit.log

这里面详细的记录了网站的请求参数，响应参数，拦截依据的规则，根据规则 id 或者文件名进行适当的关闭即可，例如 xxx.conf 修改为 xxx.conf.bak 直接关闭这一条规则，或者把对应的动作 id 的行动部分给注释掉，然后重载 Nginx

Upgrade#

module upgrade#

因为我们是克隆的仓库，所以我们仅需拉取最新的提交，然后重新编译即可

rules upgrade#

因为我们是克隆的仓库，所以我们仅需拉取最新的提交，然后重载 Nginx 即可

End#

愉快的使用 ModSecurity 来保护你的网站吧！

此文由 Mix Space 同步更新至 xLog
原始链接为 https://www.timochan.cn/posts/jc/waf_modsecurity_for_nginx

Footnotes#

https://www.timochan.cn/posts/study/upload-labs_Pass_10_for_Linux ↩