能,但必须手动隔离规则;需通过Web服务器注入SITE_NAME变量,PHP据此加载对应站点规则集,并校验HTTP_HOST白名单、分站记录日志。

PHPWAF 能不能跨站点统一防护?能,但必须手动隔离规则
PHPWAF(如开源的 phpwaf 或商业 WAF 的 PHP 插件)本身不自带“多站点自动识别”能力。它默认把所有请求当成同一个站处理,$_SERVER['HTTP_HOST'] 若未参与规则匹配,就可能让 site-a.com 的白名单误放行 site-b.net 的恶意 payload,或让一个站的误报规则影响全部站点。
- WAF 规则引擎通常只读取
$_SERVER基础变量,不主动解析域名上下文 - 若你用的是单入口(如所有站点共用
index.php),必须在 WAF 初始化前显式传入当前站点标识 - 硬编码规则(如
block_if_contains("admin.php"))对多站点极危险——site-a 允许的后台路径,可能是 site-b 的高危接口
怎么让 PHPWAF 按站点加载不同规则?靠 SITE_NAME 环境变量驱动
和多站点配置数据库、上传目录一样,WAF 规则也得“按站分家”。最稳妥的方式是 Web 服务器层注入站点身份,PHP 中据此加载对应规则集。
- Nginx 配置中为每个
server块加:fastcgi_param SITE_NAME "site-a"; - Apache 的
里加:SetEnv SITE_NAME site-b - PHP 启动时读取:
$site = $_SERVER['SITE_NAME'] ?? 'default'; - 再加载规则:
$rules = require "waf/rules/{$site}.php";(内容为数组,含 SQLi/XSS 检测逻辑)
别用 .env 文件自动加载——多站点共用一个 .env 就等于规则混用,失去隔离意义。
跨站点共用黑名单/白名单时,为什么 $_SERVER['HTTP_HOST'] 必须校验?
因为 WAF 的“来源判断”极易被绕过:攻击者直接构造 HTTP 请求头 Host: evil.com,就能骗过没校验的规则,让本该拦截的 payload 进入 site-a 的逻辑层。
立即学习“PHP免费学习笔记(深入)”;
- 必须在 WAF 加载规则前做白名单校验:
in_array(strtolower($host), ['site-a.com', 'site-b.net']) - 去掉端口:
preg_replace('/:\d+$/', '', $host),否则localhost:8080和localhost被视为不同站 - 绝对不用
$_SERVER['SERVER_NAME']——它是 Apache/Nginx 配置值,不是客户端真实 Host
WAF 日志和告警怎么区分站点?靠日志前缀 + 独立存储路径
如果所有站点日志写进同一个 waf.log,排查时根本分不清是 site-a 被扫还是 site-b 遭撞库。日志必须带上下文,且物理隔离。
- 记录时强制拼接站点名:
file_put_contents("logs/waf-{$site}.log", "[{$site}] {$ip} blocked ...\n", FILE_APPEND); - 告警邮件标题带上
[WAF-alert][site-b],避免运维看错目标 - 禁止用全局
error_log()记 WAF 事件——它不支持动态文件名,容易覆盖
真正麻烦的不是配置 WAF,而是当某站点临时需要放行某个 UA 或路径时,你得确保这个例外只生效于它自己,而不是顺手把所有站的防护都开了口子。











