phpwaf防护强度由php_waf.mode、rule_path和规则action共同决定,非简单三档开关;mode仅控制是否中断请求,规则内容与动作配置才是关键。

防护等级不是开关,而是规则集+动作组合
PHPWAF 没有“高/中/低”三档按钮式防护等级,它的“强度”由三部分共同决定:php_waf.mode(检测模式)、php_waf.rule_path(加载哪些规则文件)、以及每条规则的 action(是记录、警告还是直接 deny)。很多人误以为改个 mode=strict 就万事大吉,结果发现拦截不准或漏报严重——问题往往出在规则没跟上,或动作没对齐。
php_waf.mode 的真实含义与误用风险
这个配置项只控制「是否立即终止请求」,不控制「检测多严」:
-
php_waf.mode = off:完全不运行 WAF 逻辑(等同于没启用) -
php_waf.mode = detection:匹配到规则时只写日志,不中断请求(适合灰度观察) -
php_waf.mode = strict:匹配即exit()并返回 403(生产环境常用,但需确保规则精准)
⚠️ 常见坑:把 mode=strict 当成“开最强防护”,却没清理掉测试用的宽松规则(比如只含 select from 的简单 sql 规则),反而因漏判导致攻击绕过。真正起作用的是你放进 /etc/php-waf/rules/ 里的那些 .rule 文件内容。
如何手动升级防护强度:增规则、调动作、分路径
想让防护更“高”,得主动管理规则集,而不是调一个参数:
立即学习“PHP免费学习笔记(深入)”;
- 追加规则文件:在
/etc/php-waf/rules/下新增sql_injection_strict.rule,内容包含更全的绕过变体:unions+alls+select|/*.**/|char(|concat(|information_schema - 为敏感路径单独加强:在入口
waf.php中,对$_POST和$_GET['id']等关键参数启用额外正则检查,不依赖全局规则 - 白名单慎用:用
$config['allow_ips'] = ['192.168.1.100'];放行运维 IP,避免调试时被自己拦住;但别把整个内网段都加进去 - 静态资源跳过:在 nginx/apache 配置里,对
/css/、/js/、/images/路径直接 bypass PHP-WAF,省 CPU
验证防护是否真生效?别只看日志
日志里一堆 SQL injection detected 不代表防住了,可能只是规则太松,把正常搜索词也打了。实测建议:
- 用真实攻击载荷验证:
?id=1%20UNION%20SELECT%201,2,3--应该 403;?q=select+from+products(普通搜索)不应拦截 - 检查响应头:触发拦截时必须看到
http/1.1 403 Forbidden,且无 PHP 错误堆栈泄露 - 翻
error_log:如果 WAF 报failed to open stream: Permission denied,说明rule_path目录权限不对,规则根本没加载
最常被忽略的一点:规则更新后,php-fpm 进程不会自动 reload 规则文件——你得重启 PHP-FPM 或清空 OPcache(opcache_reset()),否则改了等于没改。