ngx_http_sub_module通过字节流替换实现代理响应体敏感词过滤,不改后端、不解析HTML,适用于轻量脱敏;需启用模块、显式声明sub_filter_types、禁用gzip或启用gunzip,并注意sub_filter_once和执行顺序。

用 ngx_http_sub_module 在网关层做静态源码的敏感词过滤,核心是“代理响应体中做字节流替换”,不改后端、不解析 HTML 结构,适合轻量脱敏和品牌统一。但必须注意它的能力边界——它不是正则引擎,也不解压缩,配置错一步就完全失效。
确认模块已启用并匹配响应类型
先验证 Nginx 是否带该模块:
- 运行
nginx -V 2>&1 | grep -o with-http_sub_module,有输出才表示编译时启用了 - 若无,需重新编译,加参数
--with-http_sub_module -
sub_filter默认只处理text/html响应,静态资源如.js、.css、.json必须显式声明 MIME 类型:
配置替换规则与执行逻辑
替换行为由三条关键指令控制:
-
sub_filter "张三" "***":精确字符串匹配,区分大小写,不支持正则 -
sub_filter_once off:默认只换第一个匹配项,设为off才能全局替换(比如页面中出现 5 次“张三”,全掩掉) - 多条
sub_filter按书写顺序执行,建议长词、高频词优先,避免被短词截断(例如先替“张三丰”,再替“张三”,否则后者会干扰前者)
绕过 gzip 和编码陷阱
这是最常踩的坑:上游返回 Content-Encoding: gzip 时,sub_filter 完全不生效。
- 方案一(推荐):让后端关闭 gzip,尤其对 HTML/JS/CSS 这类文本资源
- 方案二:Nginx 启用解压,需确认已编译
ngx_http_gunzip_module,并在 location 中加:
注意:gunzip on 仅对带 gzip 头的响应起作用,且会增加 CPU 开销;不建议对大文件或高并发接口启用。
结合 proxy_pass 实现网关级注入
典型场景:前端静态资源托管在对象存储或 CDN,通过 Nginx 反向代理统一出口,在此层过滤测试环境标识、内部域名、手机号等:
- 屏蔽测试水印:
sub_filter 'TEST' ''; - 替换内网地址:
sub_filter 'http://dev-api.internal/' 'https://api.example.com/'; - 简单手机号脱敏(假设原始格式为纯数字):
sub_filter '13812345678' '138****5678';
务必确保这些规则放在 proxy_pass 同一 location 块内,且 sub_filter_types 覆盖对应资源类型(如 JS 文件要含 application/javascript)。










