可行,但需启用mod_substitute与mod_filter模块,在VirtualHost中用AddOutputFilterByType和Substitute指令配置,仅作用于指定MIME类型且未压缩的响应体,正则需谨慎设计以避免性能与误匹配问题。
在虚拟主机层级使用 mod_substitute 对响应内容实时脱敏是可行的,但需满足前提条件并注意作用范围限制。该模块仅适用于由 apache 自身生成或代理后经 apache 输出的响应(如 php 输出、静态 html、反向代理后的响应),且必须启用并正确配置。
确认模块已启用并支持正则替换
mod_substitute 默认不启用,需手动加载。检查是否已启用:
- 运行
a2enmod substitute(Debian/Ubuntu)或在httpd.conf中取消注释LoadModule substitute_module modules/mod_substitute.so - 确保同时启用了
mod_filter(mod_substitute依赖它进行内容过滤链挂载) - 验证 Apache 配置语法:
apachectl configtest,重启服务生效
在 VirtualHost 中配置脱敏规则
将 Substitute 指令置于对应站点的 <virtualhost></virtualhost> 或 <directory></directory> 块内,配合 AddOutputFilterByType 激活过滤器。例如,对 HTML 响应中所有手机号(11位数字)替换为 [PHONE_HIDDEN]:
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/example
<pre class="brush:php;toolbar:false;"># 启用输出过滤(仅对 text/html 生效)
AddOutputFilterByType SUBSTITUTE text/html
# 执行正则替换:匹配连续11位数字(边界保护避免误伤)
Substitute "s/\b1[3-9]\d{9}\b/[PHONE_HIDDEN]/ni"
说明:
– s/// 是 substitute 语法;
– \b 确保匹配完整手机号,避免截取长数字中间段;
– n 表示不区分大小写(对数字无影响,但语法要求);i 为忽略大小写标志,n 实际应为 g(全局替换),正确写法是 sgni 中的 g;
– 若需多行匹配(如跨标签的敏感词),需加 s 标志(PCRE 的 dotall 模式),但需 Apache ≥ 2.4.12 且启用 PCRE2。
适配常见脱敏场景与注意事项
实际使用中需根据内容类型和敏感字段调整策略:
-
仅作用于指定 MIME 类型:HTML 脱敏需
AddOutputFilterByType SUBSTITUTE text/html;若要处理 JSON 接口响应,需额外添加text/json或application/json(前提是后端未设置Content-Type: application/json时 Apache 可识别) -
动态内容兼容性:PHP/Python 等脚本输出若已压缩(gzip),
mod_substitute无法处理 —— 必须确保响应未被压缩,或在压缩前插入过滤器(通过SetOutputFilter替代AddOutputFilterByType并控制过滤器顺序) -
性能与安全边界:正则过于复杂或响应体过大时可能增加延迟;避免在高并发接口上对整个响应做贪婪匹配;敏感字段建议结合后端逻辑脱敏,
mod_substitute更适合作为兜底或前端展示层补充 - HTTPS 下同样有效:只要 SSL 终止在 Apache(非透传),响应内容在解密后、加密前被处理,规则无需修改
验证与调试方法
启用日志辅助排查:
- 临时开启
Substitute调试日志:LogLevel alert substitute:trace5(Apache 2.4+),查看是否命中过滤、正则是否编译成功 - 用
curl -I检查响应头是否含Content-Encoding: gzip,如有需先禁用压缩测试 - 构造含目标敏感词的测试页面(如
<p>联系人:13812345678</p>),用curl http://example.com/test.html观察输出是否被替换

















