ModSecurity 部署:为网站加一层开源 WAF 防护

ModSecurity 开源 WAF 防护封面

如果你的网站曾经被大量恶意扫描、SQL 注入尝试或撞库请求骚扰,你大概已经体会过「服务器明明负载不高,日志里却全是可疑请求」的无奈。这篇文章会讲解如何部署 ModSecurity(一款开源的 Web 应用防火墙,即 WAF),帮助你在网站前面加一道真正能拦截恶意流量的过滤层。我们会覆盖工作原理、环境准备、安装步骤、规则配置和上线调优的完整流程。

ModSecurity 是什么,为什么值得部署

ModSecurity 最初是 Apache 的一个模块,现在也支持 Nginx 与 IIS,本质上是运行在 Web 服务器内部的请求过滤器。它会在每个 HTTP 请求到达你的应用之前先检查一遍:URL、请求头、POST 正文、Cookie 都会被拿来和规则集比对,命中恶意特征的请求会被直接拦截或记录。

你可以这样理解它的价值边界:

  • 云防火墙和网络层安全组只看 IP 和端口,看不到 HTTP 正文里的攻击载荷,而 ModSecurity 能解析请求内容本身
  • 它是开源软件,遵循 Apache 2.0 协议,不需要按流量或域名支付订阅费,适合预算有限但需要基础 WAF 能力的站点
  • 配合 OWASP Core Rule Set(OWASP 官方维护的通用攻击特征规则集),默认即可覆盖 SQL 注入、XSS、路径穿越等高频攻击类型
  • 它工作在反代或 Web 服务器内部,不需要修改应用代码,WordPress、Discuz 等常见程序都可以直接受益

从拦截粒度看,ModSecurity 与 CDN(内容分发网络)厂商的商业 WAF 并不是互斥关系。商业 WAF 在边缘节点拦截大流量攻击,ModSecurity 在源站做最后一道内容级检查,两层配合的纵深防御效果更好。

部署前的环境准备

ModSecurity v3(libmodsecurity)是目前的主力版本,与旧版 v2 的 Apache 模块相比,它以独立库的形式存在,再由各 Web 服务器的连接器加载。准备环境时建议确认以下几点:

  • 操作系统使用仍在维护期内的主流发行版,例如 Ubuntu 22.04/24.04 或 Rocky Linux 9,避免因软件源缺失导致只能装到停止维护的旧版本
  • Web 服务器二选一:Nginx 需要 1.11.5 以上版本以支持动态模块,Apache 2.4 则可以直接使用 v2 模块
  • 规划好日志磁盘空间:开启审计日志后,被攻击站点的日志量可能达到日常的数倍,建议预留至少几个 GB 并配置 logrotate 轮转
  • 确认应用自身使用 HTTPS,配合 SSL(安全传输协议)证书部署,ModSecurity 只过滤内容,不负责加密传输

如果你打算把它装在一台独立服务器而非容器里,先确认内存余量:libmodsecurity 本身占用不大(通常几十 MB 级别),真正吃资源的是规则集加载与并发请求的实时解析。

安装:以 Nginx + Ubuntu 为例

Ubuntu 24.04 的官方源里已有 libmodsecurity3 与 nginx 的 modsecurity 模块包,安装路径比自行编译简单得多:

sudo apt update
sudo apt install libmodsecurity3 modsecurity-common libnginx-mod-http-modsecurity

安装完成后,模块文件位于 /usr/lib/nginx/modules/ngx_http_modsecurity_module.so,Ubuntu 打包的 nginx 已通过 /etc/nginx/modules-enabled/ 自动加载它。接下来把默认配置复制到位并启用:

sudo cp /etc/modsecurity/modsecurity.conf-recommended \
  /etc/modsecurity/modsecurity.conf

编辑复制出的 modsecurity.conf,找到 SecRuleEngine 一行。默认值是 DetectionOnly,即只记录不拦截,这是刻意为之的安全上线方式,后面调优章节会再回到它。然后在 nginx 的站点配置中启用模块:

server {
    listen 443 ssl;
    server_name example.com;
    modsecurity on;
    modsecurity_rules_file /etc/nginx/modsecurity.conf;
    # 其余站点配置保持不变
}

执行 sudo nginx -t 确认语法无误后 reload,模块就挂载成功了。此时它只启用了引擎,还没有攻击特征规则,下一步才是让它真正「长出牙齿」。

配置 OWASP 核心规则集

Coraza 风格的规则生态里,OWASP CRS(Core Rule Set)是最常用的通用规则集。安装方式是直接克隆官方仓库到 /etc/nginx 目录:

sudo git clone https://github.com/coreruleset/coreruleset.git \
  /etc/nginx/coreruleset
cd /etc/nginx/coreruleset
sudo cp crs-setup.conf.example crs-setup.conf

然后在 /etc/nginx/modsecurity.conf 末尾追加两行,把规则集挂进引擎:

Include /etc/nginx/coreruleset/crs-setup.conf
Include /etc/nginx/coreruleset/rules/*.conf

CRS 默认以「异常评分」模式运行:单个请求累积的可疑分值超过阈值(默认入站 5 分、出站 4 分)才判定为攻击并拦截。crs-setup.conf 里可以调整 paranoia level(偏执等级,1 到 4),等级越高检得越严、误杀也越多,新部署建议保持默认的 1。

重载之前,务必为网站后台、支付回调等关键路径做例外准备。例如 WordPress 的 xmlrpc.php 如果不使用,直接在规则里禁用比放行更安全;而 WooCommerce 之类程序的后台编辑器经常触发 XSS 规则误报,需要按官方文档添加白名单规则。这一步没有捷径,靠的是上线后逐条分析日志。

ModSecurity 请求检测流程示意

上线策略:先观察,再拦截

直接把 SecRuleEngine 设为 On 是新部署最常见的翻车原因。我们建议的做法是分两阶段上线:

# 第一阶段:仅检测,不拦截
SecRuleEngine DetectionOnly

# 观察一周,确认误报可控后切换
SecRuleEngine On

观察期内,每天检查 /var/log/modsec_audit.log,重点看两类条目:一是被标记的请求里有没有正常用户操作(误报),二是攻击类型分布。常见调优手段有三个:

  • 对确认的误报路径添加 SecRuleUpdateTargetById 例外,只放行特定参数,不要整站关闭某条规则
  • 对持续骚扰的单一 IP 段,配合 SecRule IP: 变量做临时封禁,比逐条规则打补丁更省事
  • 用 SecAuditLogRelevantStatus 收窄审计范围,只记录 4xx/5xx 相关事件,控制日志膨胀

检测模式与拦截模式对比

切换到拦截模式后,建议保留至少两周的每日巡检,观察 403 拦截量与业务转化数据是否异常。如果你的站点流量增长较快,也可以参考我们此前整理的服务器安全加固实践,把系统层与网络层的防护一并补齐。

性能影响与常见问题

规则数量直接影响每个请求的处理耗时。CRS 完整加载约三千余条规则,在普通 VPS(虚拟专用服务器)上单请求额外开销通常在毫秒级,但如果你的站点本身 TTFB 已经偏高,叠加规则解析后可能被放大。部署后建议对比前后的首字节耗时,如果劣化明显,可以只保留 CRS 的基础规则组。

两个高频问题提前说明。其一,开启拦截后突然大量 403:先查审计日志里命中的规则 ID 与请求参数,九成是误报,加例外而不是降级规则。其二,上传附件失败:CRS 默认限制请求体大小与内容类型,需要在 crs-setup.conf 里按业务调整请求体检查配置。若想从加速角度综合优化站点响应,可以结合网站 TTFB 优化指南一起做基线对比。

总结与下一步行动

ModSecurity 的部署门槛并不高:安装模块、挂载 OWASP CRS、先以检测模式观察、再切换拦截,四步就能让网站获得开源 WAF 的基础防护能力。真正的持续成本在于日志调优与例外维护,这部分投入换来的是对 SQL 注入、XSS 等高频攻击的内容级拦截。如果你的业务运行在 WordPress 之上,也可以看看我们的 Hostease WordPress 主机方案,配合本文的 WAF 部署思路构建更完整的防护链路。

建议本周就动手做一次测试环境演练:找一台 Hostease VPS 主机 按本文流程部署,用 curl 模拟一次带攻击特征的请求,亲眼看到 403 拦截与审计日志落盘,再考虑推广到生产站点。如果你需要更细的规则调优思路,推荐从 CRS 官方文档的误报处理章节读起,那是最接近实战的参考资料。

发表评论