返回首页

ModSecurity免费替代方案:本地搭建企业级Web应用防火墙全指南

Business 年费 $2,400/域名,Imperva 年费 $5,000+。对于需要自建WAF的企业, + CRS 是完全免费的方案,防护能力不亚于商业WAF。本文讲解如何从零搭建生产级WAF。

为什么选ModSecurity

功能 Cloudflare Pro Imperva WAF ModSecurity + CRS
SQL注入防护 优秀 优秀 优秀
防护 优秀 优秀 优秀
Bot防护 优秀 优秀 基础
DDoS防护 优秀 优秀 需配合
自定义规则 有限 完整 完整
日志分析 仪表盘 仪表盘 自建
SSL卸载 内置 内置 /Apache
价格 $20/月/域名 $5,000+/年 免费

ModSecurity的核心优势是规则完全可控——你可以针对业务逻辑写精确的WAF规则,这是商业WAF做不到的。

架构方案

方案A: Nginx + ModSecurity(推荐)
[Client] → [Nginx+ModSecurity] → [Backend App]

方案B: Apache + ModSecurity
[Client] → [Apache+mod_security] → [Backend App]

方案C: 独立WAF网关
[Client] → [HAProxy] → [ModSecurity] → [Backend App]

安装Nginx + ModSecurity

方式一:编译安装(推荐,功能完整)

# 安装依赖
  && apt install -y \
  gcc make build-essential \
  libpcre3-dev libssl-dev zlib1g-dev \
  libxml2-dev libxslt1-dev libgd-dev \
  libgeoip-dev liblmdb-dev libyajl-dev \
  libcurl4-openssl-dev libpcre++-dev \
  git automake libtool autoconf \
  pkgconf libpcre2-dev

# 1. 克隆ModSecurity源码
cd /opt
git clone --depth 1 -b v3/master https://github.com/owasp-modsecurity/ModSecurity.git
cd ModSecurity
git submodule init
git submodule update

# 编译ModSecurity
./build.sh
./configure --with-pcre2
make -j$(nproc)
make install

# 2. 克隆Nginx ModSecurity连接器
cd /opt
git clone --depth 1 https://github.com/owasp-modsecurity/ModSecurity-nginx.git

# 3. 编译Nginx(添加ModSecurity模块)
NGINX_VERSION=1.26.1
wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz
tar xzf nginx-${NGINX_VERSION}.tar.gz
cd nginx-${NGINX_VERSION}

./configure \
  --prefix=/etc/nginx \
  --sbin-path=/usr/sbin/nginx \
  --modules-path=/usr/lib64/nginx/modules \
  --conf-path=/etc/nginx/nginx.conf \
  --error-log-path=/var/log/nginx/error.log \
  --http-log-path=/var/log/nginx/access.log \
  --pid-path=/var/run/nginx.pid \
  --with-http_ssl_module \
  --with-http_v2_module \
  --with-http_realip_module \
  --with-http_gzip_static_module \
  --with-http_secure_link_module \
  --add-dynamic-module=/opt/ModSecurity-nginx

make -j$(nproc)
make install

方式二:apt安装(Ubuntu)

apt install -y libmodsecurity3 libmodsecurity3-nginx nginx

方式三:Docker

docker pull owasp/modsecurity-crs:nginx
docker run -d --name waf \
  -p 80:80 -p 443:443 \
  -e BACKEND=http://192.168.1.100:8080 \
  -e PARANOIA=1 \
  -v /var/log/modsecurity:/var/log/modsecurity \
  owasp/modsecurity-crs:nginx

ModSecurity核心配置

/etc/nginx/modsecurity/modsecurity.conf

# 启用ModSecurity
SecRuleEngine On

# 请求体处理
SecRequestBodyAccess On
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 131072
SecRequestBodyLimitAction Reject

# 响应体处理
SecResponseBodyAccess On
SecResponseBodyMimeType text/plain text/html text/xml application/json
SecResponseBodyLimit 524288
SecResponseBodyLimitAction ProcessPartial

# 临时文件路径
SecTmpDir /tmp/modsecurity/tmp
SecDataDir /tmp/modsecurity/data
SecUploadDir /tmp/modsecurity/upload

# 日志配置
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogParts ABIJDEFHZ
SecAuditLogType Serial
SecAuditLog /var/log/modsecurity/modsec_audit.log

# 调试日志(生产环境关闭)
SecDebugLog /var/log/modsecurity/modsec_debug.log
SecDebugLogLevel 0

# 动作默认值
SecDefaultAction "phase:1,deny,log,status:403"

# PCRE调优
SecPcreMatchLimit 100000
SecPcreMatchLimitRecursion 100000

# Unicode映射
SecUnicodeMapFile /etc/nginx/modsecurity/unicode.mapping 20127

# 隐藏服务器标识
SecServerEngine On
SecServerTag "Server"

/etc/nginx/modsecurity/crs-setup.conf

# OWASP CRS配置

# 偏执级别(1-4,越高越严格,误报越多)
SecAction "id:900000,phase:1,nolog,pass,t:none,setvar:tx.paranoia_level=1"

# 执行异常评分(累计攻击分数触发阻断)
SecAction "id:900110,phase:1,nolog,pass,t:none,setvar:tx.blocking_paranoia_level=1"

# 检测SQL注入的阈值
SecAction "id:900200,phase:1,nolog,pass,t:none,setvar:'tx.sql_injection_score_threshold=5'"

# 检测XSS的阈值
SecAction "id:900210,phase:1,nolog,pass,t:none,setvar:'tx.xss_score_threshold=5'"

# 检测RFI/LFI的阈值
SecAction "id:900220,phase:1,nolog,pass,t:none,setvar:'tx.rfi_score_threshold=5'"
SecAction "id:900230,phase:1,nolog,pass,t:none,setvar:'tx.lfi_score_threshold=5'"

# 允许的HTTP方法
SecAction "id:900240,phase:1,nolog,pass,t:none,setvar:'tx.allowed_methods=GET HEAD POST OPTIONS PUT PATCH DELETE'"

# 允许的Content-Type
SecAction "id:900260,phase:1,nolog,pass,t:none,setvar:'tx.allowed_request_content_type=|application/x-www-form-urlencoded| |multipart/form-| |multipart/related| |text/xml| |application/xml| |application/soap+xml| |application/json| |application/cloudevents+json| |application/cloudevents-batch+json|'"

# 允许的文件扩展名(白名单)
SecAction "id:900270,phase:1,nolog,pass,t:none,setvar:'tx.allowed_request_content_type_charset=|utf-8| |iso-8859-1| |iso-8859-15| |-1252|'"

# 地理位置封禁(可选)
# SecAction "id:900600,phase:1,nolog,pass,t:none,setvar:'tx.high_risk_country_codes='"

# 禁用某些规则(针对业务误报处理)
# SecRuleRemoveById 941100
# SecRuleRemoveById 942100

Nginx配置集成ModSecurity

# /etc/nginx/nginx.conf
load_module modules/ngx_http_modsecurity_module.so;

http {
    modsecurity on;
    modsecurity_rules_file /etc/nginx/modsecurity/modsecurity.conf;

    upstream backend {
        server 192.168.1.100:8080;
    }

    server {
        listen 80;
        listen 443 ssl;
        server_name example.com;

        ssl_certificate /etc/nginx/ssl/cert.pem;
        ssl_certificate_key /etc/nginx/ssl/key.pem;

        # 针对特定路径调整规则
        location /api/ {
            modsecurity_rules '
                SecRuleEngine On
                SecRuleRemoveById 920170  # 允许无Accept头
                SecRuleRemoveById 942100  # 放宽SQL注入检测
            ';
            proxy_pass http://backend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }

        location / {
            proxy_pass http://backend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }

        # 静态资源不走WAF
        location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
            modsecurity off;
            proxy_pass http://backend;
        }
    }
}

自定义WAF规则

/etc/nginx/modsecurity/custom-rules.conf

# === 业务层防护规则 ===

# 封禁已知恶意IP(从威胁情报导入)
SecRule REMOTE_ADDR "@ipMatchFromFile /etc/nginx/modsecurity/bad_ips.txt" \
    "id:100001,phase:1,drop,log,msg:'Blocked malicious IP'"

# 防爬虫:限制请求频率
SecAction "id:100010,phase:1,pass,nolog,initcol:ip=%{REMOTE_ADDR}"
SecRule IP:REQUEST_COUNT "@gt 100" \
    "id:100011,phase:1,drop,log,msg:'Rate limit exceeded: %{REMOTE_ADDR}'"
SecRule REQUEST_URI ".*" \
    "id:100012,phase:5,pass,nolog,setvar:ip.request_count=+1"

# 防护路径遍历
SecRule REQUEST_URI "@rx /\.\./" \
    "id:100020,phase:1,drop,log,msg:'Path traversal attempt'"

# 防护命令注入
SecRule ARGS|ARGS_NAMES|REQUEST_HEADERS "@rx (?:;|\|`|&&|\$\(|\$\{)" \
    "id:100030,phase:2,drop,log,msg:'Command injection attempt'"

# 防护SSRF
SecRule ARGS "@rx (?:file|gopher|dict|php|data):" \
    "id:100040,phase:2,drop,log,msg:'SSRF attempt detected'"

# 防护反序列化攻击
SecRule ARGS|REQUEST_BODY "@rx (?:O:|a:|s:)\d+:" \
    "id:100050,phase:2,drop,log,msg:'PHP deserialization attempt'"

# 防护JWT篡改
SecRule REQUEST_HEADERS:Authorization "@rx ^Bearer\s+[A-Za-z0-9_-]+\.eyJ" \
    "id:100060,phase:1,pass,log,setvar:'tx.jwt_token=%{MATCHED_VAR}'"

# 防护文件上传(只允许指定类型)
SecRule FILES_TMPNAMES "@rx \.(?:php|phtml|php3|php4|php5|phps|asp|aspx|jsp|cgi|sh|bat|exe|dll)$" \
    "id:100070,phase:2,drop,log,msg:'Malicious file upload blocked'"

# 白名单:排除内部调用
SecRule REMOTE_ADDR "@ipMatch 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16" \
    "id:100080,phase:1,pass,nolog,ctl:ruleEngine=Off"

恶意IP列表文件

# /etc/nginx/modsecurity/bad_ips.txt
# 格式:每行一个IP或CIDR
203.0.113.0/24
198.51.100.0/24
192.0.2.1
# 从威胁情报源自动更新

日志分析

实时告警脚本

cat > /opt/waf-.sh << 'SCRIPT'
#!/bin/bash
tail -f /var/log/modsecurity/modsec_audit.log | while read line; do
    if echo "$line" | grep -q "\[id \"[0-9]"; then
        RULE_ID=$(echo "$line" | grep -oP '\[id "\K[0-9]+')
        SRC_IP=$(echo "$line" | grep -oP 'client "\K[^"]+')
        URI=$(echo "$line" | grep -oP 'uri "\K[^"]+')
        
        # 发送告警到企业微信
        curl -s -X POST "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY" \
          -H 'Content-Type: application/json' \
          -d "{\"msgtype\":\"markdown\",\"markdown\":{\"content\":\"## 🚨 WAF告警\n- **规则ID**: $RULE_ID\n- **来源IP**: $SRC_IP\n- **请求URI**: $URI\n- **时间**: $(date)\"}}"
    fi
done
SCRIPT
chmod +x /opt/waf-alert.sh

ELK集成

# Filebeat配置
filebeat.inputs:
  - type: log
    paths:
      - /var/log/modsecurity/modsec_audit.log
    multiline.pattern: '^--'
    multiline.negate: true
    multiline.match: after

output.elasticsearch:
  hosts: ["localhost:9200"]
  index: "modsecurity-%{+yyyy.MM.dd}"

性能优化

# 1. 只对动态请求开启WAF
location ~* \.(php|asp|aspx|jsp|cgi)$ {
    modsecurity on;
    modsecurity_rules_file /etc/nginx/modsecurity/modsecurity.conf;
    proxy_pass http://backend;
}

# 2. 关闭响应体检测(节省CPU)
# modsecurity.conf中设置
SecResponseBodyAccess Off

# 3. 减少审计日志记录
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"

# 4. 使用内存文件系统存储临时数据
SecTmpDir /dev/shm/modsecurity/tmp
SecDataDir /dev/shm/modsecurity/data

对比表

功能 Cloudflare Imperva ModSecurity+CRS
SQL注入防护 优秀 优秀 优秀
XSS防护 优秀 优秀 优秀
CSRF防护 基础 优秀 基础
Bot防护 优秀 优秀 需自定义
DDoS防护 优秀 优秀 需配合
自定义规则 有限 完整 完整
日志分析 仪表盘 仪表盘 自建
部署方式 云/本地 本地
价格 $20-200/月 $5K+/年 免费

ModSecurity + OWASP CRS 的组合是全球使用最广泛的开源WAF方案。规则库每周更新,覆盖OWASP Top 10所有攻击类型。配合自定义业务规则,防护效果不输任何商业WAF。

常见问题

为什么选ModSecurity

>为什么选ModSecurity 功能 Cloudflare Pro Imperva WAF ModSecurity + CRS SQL注入防护 优秀 优秀 优秀 XSS防护 优秀 优秀 优秀 Bot防护 优秀 优秀 基础 DDoS防护 优秀 优秀 需配合 自定义规则 有限 完整 完整 日志分析 仪表盘 仪表盘 自建 SSL卸载 内置 内置 Nginx/Apache 价格 $20/月/域名 $5,000+/年 免费 ModSecurity的核心优势是规则完全可控——你可以针对业务逻辑写精确的WAF规则,这是商业WAF做不到的。

评论