自建开源 WAF 全流程实践:ModSecurity 3 + OWASP CRS 4 + ECharts 攻击监控大屏

为什么自建 WAF,而不是买商业版?

商业 WAF(如雷池等)的大屏监控功能通常要付费,且对低配服务器不友好。对于学习者和个人站长,完全可以用开源组件自建一套「防护 + 可视化大屏」:功能足够、数据可控、思路可复现,踩坑过程本身就是最好的学习材料。

本站在 2 核 1.8G 内存的轻量服务器上完成了整套部署,以下是完整过程与踩坑记录。

整体架构

访客请求
   │
   ▼
nginx ──modsecurity 动态模块──► ModSecurity 3 + OWASP CRS 4.4(794 条规则)
   │  拦截(403)或放行
   │
   ▼
/var/log/nginx/acxltech-error.log(warn 级独立日志,ModSecurity 拦截行)
   │
   ▼
waf-attacks.py(cron 每 2 分钟)
   ├─ 解析拦截日志
   ├─ ip2region 离线库 GeoIP 定位(国家/城市/ISP)
   ├─ 启发式攻击类型分类(SQLi / XSS / 扫描 / 爆破 / 爬虫…)
   └─ 脱敏(IP 前两段 + *.*)──► attacks.json
                                │
                                ▼
                        ECharts 攻击监控大屏(waf.acxltech.xyz)

部署步骤

1. 编译 ModSecurity 3(源码,踩坑点最多)

Ubuntu 20.04 官方源里的 libmodsecurity 是 3.0.4,太旧,不支持 OWASP CRS 4,必须源码编译 3.0.12。

# 编译前务必拉取子模块,否则 configure 直接失败
git clone --recursive https://github.com/SpiderLabs/ModSecurity
cd ModSecurity
./build.sh && ./configure && make -j2 && make install

坑 1: 忘记 --recursive 会缺 others/libinjection,编译失败。
坑 2: 国内服务器拉 GitHub 慢/超时,建议走代理或镜像加速。

2. 下载 OWASP CRS 4.4.0

wget https://github.com/coreruleset/coreruleset/archive/refs/tags/v4.4.0.tar.gz
tar xzf v4.4.0.tar.gz -C /etc/nginx/modsecurity/
cd /etc/nginx/modsecurity/coreruleset-4.4.0
cp crs-setup.conf.example crs-setup.conf
cp rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf

3. nginx 动态模块挂载(拦截模式)

# nginx.conf 或站点配置
load_module modules/ngx_http_modsecurity_module.so;

# 站点 443 server 内
modsecurity on;
modsecurity_rules_file /etc/nginx/modsecurity/modsecurity.conf;

modsecurity.conf 中必须确认:

SecRuleEngine On          # 拦截模式(DetectionOnly 不产生拦截日志,踩过坑)
SecAuditEngine Off        # 关闭审计日志(nginx connector 的 partial 格式解析不了)
SecAuditLog /var/log/modsec_audit.log

坑 3: SecRuleEngine DetectionOnly 时日志里看不到拦截记录,排查半天。
坑 4: 审计日志走 nginx connector 是 partial 格式,无法直接解析,改为从 error_log warn 级独立日志解析 ModSecurity 拦截行,稳定可靠。

4. 数据管道:日志 → GeoIP → 脱敏 JSON

# /usr/local/bin/waf-attacks.py,由 cron 每 2 分钟执行
# 1) 解析 error.log 中的 "ModSecurity: Access denied" 行
# 2) ip2region.db(离线库,不依赖外网 API)定位:
#    格式 = 4字节城市ID + "国家|区域|省|市|ISP",先字节切片再 decode!
# 3) 按规则启发式分类攻击类型(SQLi/XSS/扫描/爆破…)
# 4) IP 脱敏:前两段保留,后两段置 *.*
# 5) 输出 /var/www/waf/data/attacks.json(含 类型/国家/城市/24h趋势/最近事件)

坑 5: ip2region.db 的字段是「4 字节城市 ID + 竖线分隔文本」,直接 decode 整串会乱码,必须先用字节切片去掉前 4 字节再解析。

5. ECharts 攻击大屏

  • 世界地图散点 + 飞线(攻击源 → 中国),攻击类型 / 国家 / 城市 / 24h 趋势面板
  • 访问控制:Basic Auth + 数据接口 token 校验 + noindex,避免被搜索引擎收录
  • 展示数据全部脱敏,合规对外

效果与数据

上线后每天都有真实拦截:恶意扫描、onvif 设备探测、.env 泄露尝试、SQL 注入与 XSS 探测等。攻击源以荷兰、美国、保加利亚等境外扫描器为主。拦截数据实时展示在首页 WAF 展示区与监控大屏。

踩坑记录汇总

  1. Ubuntu 源 ModSecurity 3.0.4 太旧 → 源码编译 3.0.12
  2. 漏拉 libinjection 子模块 → 编译失败
  3. DetectionOnly 模式不写拦截日志 → 改 SecRuleEngine On
  4. nginx 审计日志 partial 格式无法解析 → 改用 error_log warn 级日志
  5. ip2region 未先切片直接 decode → 乱码
  6. 1.8G 内存跑不动重型容器方案 → 精简为源码部署 + 静态文件大屏

部署清单(免费资源)

  • ModSecurity 3.0.12(GPL)
  • OWASP CRS 4.4.0(794 条规则,Apache 2.0)
  • ip2region 离线 IP 库(Apache 2.0)
  • ECharts(Apache 2.0)

⚠️ 合规声明: 本文及本站内容仅用于网络安全合规学习、科研与授权测试用途,严禁用于未授权检测、入侵、破坏等违法行为。自建 WAF 的目的是防御,请勿将相关技术用于攻击未授权目标。

⚠️ 合规声明: 本文内容仅用于网络安全合规学习、科研与授权测试用途。严禁用于任何未授权行为,违者自行承担全部法律责任。
滚动至顶部