在CentOS服务器上配置mod_security并进行规则定制,核心就是三步:安装模块、加载OWASP核心规则集、根据自身业务场景调整规则。这是目前Apache/Nginx环境下最成熟的WAF(Web应用防火墙)方案之一,能有效拦截SQL注入、XSS跨站脚本、文件包含等常见攻击。很多运维人员装完就不管了,默认规则一跑,要么误杀正常请求,要么放过高级攻击,真正的价值在于"定制"二字。
mod_security本质上是一个开源的Web应用防火墙引擎,它以模块形式嵌入Apache(也支持Nginx),通过规则匹配来实时检测和阻断恶意HTTP请求。在CentOS 7/8/9上部署它并不复杂,但要让它真正发挥作用,你必须理解规则的工作原理和调优逻辑。下面我会从安装、基础配置、规则定制、性能优化四个维度,把这件事讲透。
一、CentOS上安装mod_security的具体操作首先确认你的Apache版本,因为mod_security有v2和v3两个大版本,目前主流推荐v3。如果你用的是CentOS 7,系统自带的Apache是2.4.x,可以直接通过EPEL源或源码编译安装。CentOS 8/9则需要启用PowerTools或CodeReady源。
最简单的方式是通过yum安装(如果源里有):
yum install mod_security -y
如果源里没有或者版本太旧,就需要从源码编译。先安装依赖:
yum install gcc gcc-c++ make httpd-devel pcre-devel libxml2-devel -y
然后下载mod_security v3源码:
wget https://github.com/SpiderLabs/ModSecurity/archive/v3.0.12.tar.gz tar -xzf v3.0.12.tar.gz cd ModSecurity-3.0.12 git submodule init git submodule update ./build.sh ./configure make make install
编译完成后,需要在Apache配置中加载模块。找到httpd.conf或在conf.d目录下新建一个modsecurity.conf:
LoadModule security3_module modules/mod_security3.so
重启Apache验证:
systemctl restart httpd httpd -M | grep security
看到security3_module就说明加载成功了。
二、基础配置文件的核心参数解读mod_security的主配置文件通常放在/etc/modsecurity/modsecurity.conf,CentOS上默认路径可能是/etc/httpd/conf.d/modsecurity.conf。这个文件里有几个关键指令必须理解。
第一个是SecRuleEngine,它控制mod_security的运行模式:
SecRuleEngine On
On是拦截模式,检测到攻击直接阻断;DetectionOnly是只记录不阻断,适合初期调试;Off是关闭。强烈建议先用DetectionOnly跑一周,观察误报情况,再切到On。
第二个是SecRequestBodyAccess,控制是否检查请求体:
SecRequestBodyAccess On
如果你的网站有文件上传、表单提交,这个必须开,否则POST请求体里的恶意代码检测不到。
第三个是SecResponseBodyAccess,控制是否检查响应体:
SecResponseBodyAccess Off
一般建议关掉,因为检查响应体会严重影响性能,而且大多数场景下没必要。
第四个是SecAuditLog,指定审计日志路径:
SecAuditLog /var/log/httpd/modsec_audit.log
所有被检测到的请求都会记录在这里,是排查误报和分析攻击的核心依据。
第五个是SecDataDir,指定临时数据目录:
SecDataDir /var/lib/modsecurity
这个目录需要提前创建并设置正确权限:
mkdir -p /var/lib/modsecurity chown apache:apache /var/lib/modsecurity三、加载OWASP核心规则集(CRS)并理解其结构
mod_security本身只是引擎,真正干活的是规则。OWASP(开放Web应用安全项目)维护的Core Rule Set(CRS)是目前最权威、最全面的开源规则集,覆盖了OWASP Top 10的所有攻击类型。
下载CRS:
cd /etc/modsecurity git clone https://github.com/coreruleset/coreruleset.git cd coreruleset mv crs-setup.conf.example crs-setup.conf
然后在modsecurity.conf中引入:
Include /etc/modsecurity/coreruleset/crs-setup.conf Include /etc/modsecurity/coreruleset/rules/*.conf
CRS的规则文件按功能分块,比如REQUEST-901-INITIALIZATION.conf是初始化规则,REQUEST-920-PROTOCOL-ENFORCEMENT.conf是协议强制规则,REQUEST-941-APPLICATION-ATTACK-XSS.conf是XSS防护,REQUEST-942-APPLICATION-ATTACK-SQLI.conf是SQL注入防护。每一块都有独立的文件,方便你单独启用或禁用。
CRS默认使用"偏执级别"(Paranoia Level),从PL1到PL4,级别越高规则越严格,误报也越多。生产环境建议从PL1开始:
SecAction \ "id:900000,\ phase:1,\ nolog,\ pass,\ t:none,\ setvar:'tx.paranoia_level=1'"
这个设置放在crs-setup.conf里就行。PL1能拦截绝大多数攻击,同时误报率可控。如果你的业务比较特殊,比如大量使用富文本编辑器,可以先从PL1逐步往上调,每次调一级观察一周。
四、根据业务场景进行规则定制的实战方法默认规则再好,也不可能100%适配你的业务。规则定制才是mod_security真正的价值所在。定制主要分三个方向:放行特定请求、加强特定防护、编写自定义规则。
第一,放行特定URL或参数。比如你的网站有一个富文本编辑器接口,正常提交会触发XSS规则误报。你可以在modsecurity.conf末尾添加:
SecRule REQUEST_URI "@beginsWith /admin/editor/submit" \
"id:1000001,\
phase:1,\
pass,\
nolog,\
ctl:ruleRemoveById=941100"
这条规则的意思是:当请求URI以/admin/editor/submit开头时,跳过ID为941100的XSS规则,并且不记录日志。ctl:ruleRemoveById是非常实用的指令,可以精确移除某条规则对特定请求的影响。
第二,针对特定攻击加强防护。比如你的网站是电商平台,经常遭受CC攻击(高频请求),可以添加限速规则:
SecAction \
"id:1000002,\
phase:1,\
pass,\
nolog,\
setvar:'ip.cc_counter=+1'"
SecRule IP:CC_COUNTER "@gt 100" \
"id:1000003,\
phase:1,\
deny,\
status:429,\
log,\
msg:'Rate limit exceeded'"
这个简单的计数器规则,当同一个IP在短时间内请求超过100次就直接返回429状态码。当然这只是示例,生产环境需要配合更完善的IP追踪和时间窗口逻辑。
第三,编写自定义规则应对业务特有风险。比如你的网站允许用户上传文件,但只允许图片格式,可以写:
SecRule REQUEST_FILENAME "@endsWith .php" \
"id:1000004,\
phase:2,\
deny,\
status:403,\
log,\
msg:'PHP file upload blocked'"
这条规则在请求体阶段检查文件名后缀,发现.php直接拦截。注意phase的选择很重要:phase:1是请求头阶段,phase:2是请求体阶段,phase:3是响应头阶段,phase:4是响应体阶段。文件上传检查必须放在phase:2。
还有一个容易被忽视的点:规则的执行顺序。mod_security是按规则ID从小到大依次执行的,所以自定义规则的ID建议从1000000以上开始,避免和CRS的规则ID冲突。同时,使用ctl:ruleRemoveTargetById可以更精细地控制规则作用范围。
五、性能优化与误报处理的关键技巧mod_security是有性能开销的,尤其是开启了请求体检查之后。在高并发场景下,如果配置不当,可能导致响应延迟增加30%-50%。几个优化建议:
首先,限制请求体大小。如果你的业务不需要大文件上传,把上限设小:
SecRequestBodyLimit 1048576
这是1MB的限制,超过的请求直接拒绝,既省资源又防大文件攻击。
其次,合理使用SecRuleEngine。在调试阶段用DetectionOnly,稳定后切On。不要长期开着DetectionOnly,因为它会让你产生"一切正常"的错觉。
第三,定期分析审计日志。用以下命令快速统计被拦截最多的规则:
grep -oP 'id "\K[0-9]+' /var/log/httpd/modsec_audit.log | sort | uniq -c | sort -rn | head -20
排在前面的规则ID就是误报重灾区,针对性地做放行处理。不要一上来就大面积关闭规则,那等于把WAF拆了。
第四,考虑使用SecRuleUpdateTargetByTag或SecRuleUpdateTargetById来微调规则的检测目标,而不是直接禁用整条规则。比如CRS的SQL注入规则检测了所有参数,但你的某个接口参数确实需要包含SQL关键字(比如搜索功能),可以只对那个参数关闭检测:
SecRuleUpdateTargetById 942100 "!ARGS:search_keyword"
感叹号表示排除,这样只有search_keyword这个参数不受942100规则约束,其他参数仍然受保护。
六、CentOS不同版本的注意事项CentOS 7自带Apache 2.4.6,mod_security v2和v3都能用,但v2已经停止维护,强烈建议用v3。CentOS 8/9的Apache版本较新,编译v3时可能需要额外安装libcurl-devel和yajl-devel。
另外,CentOS 8/9默认使用dnf而非yum,包管理命令需要替换。如果你用的是Nginx而不是Apache,mod_security同样支持,但需要通过libmodsecurity库来加载,配置方式有所不同,不过规则文件是通用的。
还有一个容易踩的坑:SELinux。CentOS默认开启SELinux,mod_security的日志目录和数据目录如果权限不对,会被SELinux拦截。解决方法要么调整SELinux上下文,要么临时设为permissive模式测试:
setsebool -P httpd_modsecurity on chcon -R -t httpd_sys_rw_content_t /var/log/httpd/modsec_audit.log
最后提醒一点,mod_security不是银弹。它能挡住大部分自动化攻击和已知漏洞利用,但对于精心构造的高级持续性威胁(APT)和零日漏洞,它的防护能力有限。把它当作纵深防御体系中的一层,配合系统加固、最小权限原则、定期更新补丁,才是真正的安全策略。
总结一下:CentOS上部署mod_security,安装只是起点,加载CRS是基础,规则定制才是灵魂。从PL1开始跑,逐步根据审计日志调优,针对业务特点写自定义规则,同时注意性能和SELinux的坑。这套流程走下来,你的Web服务器就有了一层相当靠谱的应用层防护。
