启用 underscores_in_headers on 会绕过安全过滤,导致请求头注入、权限绕过或WAF失效;因RFC 7230禁止下划线,Nginx默认丢弃X_User_ID类头,开启后透传可能被用于冒充认证头、绕过WAF检测或引发环境变量污染。

启用 underscores_in_headers on 会绕过部分安全过滤,导致请求头注入、权限绕过或WAF失效等风险。
为什么 underscores_in_headers 有风险
Nginx 默认丢弃含下划线的请求头(如 X_User_ID),这是为兼容 RFC 7230 —— 该标准明确要求头部字段名只允许使用字母、数字、连字符(-),禁止下划线(_)。很多后端框架(如 Django、Flask)和中间件(如 WAF、API 网关)也默认忽略或不解析带下划线的头,将其视为非法输入。一旦开启 underscores_in_headers on,Nginx 就会保留并透传这些头,可能造成:
- 攻击者用
X_Auth_User冒充认证头,绕过后端的身份校验逻辑 - 某些 WAF 规则只检测标准命名(如
X-Forwarded-For),对X_Forwarded_For视而不见,导致 IP 伪造成功 - 后端将下划线头误解析为环境变量(如
HTTP_X_USER_ID→os.environ['HTTP_X_USER_ID']),引发变量污染
哪些场景容易误开这个配置
常见于开发调试或兼容旧系统时:
- 前端 SDK 或测试脚本习惯用下划线命名自定义头(如
trace_id),开发者直接在 Nginx 开启该选项“快速修复” - 迁移 Apache(支持下划线头)到 Nginx 后,未统一头命名规范,仅靠此配置“兼容”
- 使用 OpenResty 或 Lua 脚本动态读取头,误以为必须开启才能获取下划线字段
更安全的替代方案
应从源头规避,而非放宽 Nginx 的头解析策略:
- 统一约定:所有自定义请求头使用中划线(
-)分隔,如X-User-ID、X-Request-Trace - 前端/客户端改写:在发请求前将下划线转为中划线(多数 HTTP 客户端库支持拦截修改)
- 必要时用 map 指令做头映射:
map $http_x_user_id $safe_user_id {
default $http_x_user_id;
}
再通过proxy_set_header X-User-ID $safe_user_id转发标准格式
如果必须开启,请严格限制作用域
避免全局开启(http 块),仅在最小必要范围内启用:
- 只在特定
server或location块中设置,且该 location 有明确可信来源(如内网调用) - 配合
limit_except或 IP 白名单,限制可发送非标头的客户端范围 - 记录并监控含下划线的请求头访问日志,便于审计异常行为

















