DEBUG.WIKI
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
雨云;给项目一台云服务器
RackNerd;$21.99/年 · 1GB KVM

经 Nginx 反代后 auth_token 请求头消失

Nginx默认过滤名称含下划线的请求头。通过后端接收结果确认丢失位置,调整字段命名或限定范围启用,并核对虚拟站点选择。

同一个接口,直连后端时能收到 auth_token,经过 Nginx 后却收不到;其他请求头和页面访问都正常。即使补上 proxy_pass_request_headers on;,结果也没有变化。此时应检查请求头名称中的下划线是否在 Nginx 接收阶段被过滤。

Nginx 默认 underscores_in_headers off,会把名称含下划线的客户端请求头标记为无效;默认开启的 ignore_invalid_headers 随后忽略这些字段。这里讨论普通 HTTP 反向代理,不能把所有认证失败或缺头都归到这条规则。

用无敏感信息的字段确认丢失位置

在受控测试接口上分别发送带下划线和连字符的字段,并从后端检查原始请求头名称和值。下面的 URL 是占位值,需要替换为自己有权访问的测试入口:

curl --header 'Debug_Test: probe-value' \
  --header 'Debug-Test: probe-value' \
  'https://api.example.com/header-check'

不要使用真实令牌做回显测试,也不要把显示所有请求头的诊断接口公开。前端发出的字段在后端缺失,且只有下划线名称受影响,才符合本问题的特征。还应以相同方法在允许访问的后端入口对照;若后端直连也缺失,先查应用框架或前一层代理。

诊断时不要只打印 Nginx 的 $http_debug_test 就认定两个名称等价:这类变量把字段名中的连字符转成下划线。后端也可能规范化头名称,认证协议应避免同时接受容易混淆的两种拼写。

优先统一字段名,兼容旧客户端时再调整接收规则

如果客户端和服务端都可修改,把约定的自定义字段统一为不含下划线的名称,例如 Auth-Token,同步修改发送端和读取端。它与 auth_token 是不同的字段名,仅修改客户端会使仍读取旧名称的应用继续失败。

已有客户端无法同步升级、必须保留 auth_token 时,在相应的 server 配置中添加:

server {
    # 保留已有 listen、server_name、TLS 和访问控制
    underscores_in_headers on;

    # 保留已有 location 和 proxy_pass 配置
}

这是合入原配置的片段,不是新建空站点。该指令允许放在 http 或 server,不能放进 location。无需为了这一个字段关闭 ignore_invalid_headers;让其他非法名称继续受检查。

proxy_pass_request_headers 控制的是已经收到的请求头是否传给上游,默认就是 on。它不能恢复在接收阶段已被忽略的字段。也不要写死一条真实认证值到 proxy_set_header 中,这会改变客户端身份语义。

同端口多个站点要核对实际生效范围

Nginx 建立连接时先处于默认站点上下文,随后可能根据 TLS SNI、请求行或 Host 选择站点。处理某个头字段时采用的 underscores_in_headers 配置,取决于当时已经选中的上下文。因此只改一个按名称匹配的站点,不代表所有请求顺序或访问方式都会使用该值。

先核对同一监听地址、端口的默认站点及实际加载的配置。用真实业务域名和正常 TLS 校验请求,不要改成 IP 再关闭证书校验来代替验收。只有当同一范围内的站点都确实允许下划线头时,才考虑统一配置;否则应调整入口隔离或客户端字段名,避免为了一个站点扩大其他站点的接收范围。

验收及恢复

备份本次涉及的配置,用对应部署的 Nginx 程序和配置路径执行 nginx -t,通过后按原部署方式重载。重新检查后端实际收到的头,以及认证成功和拒绝请求是否仍符合预期。若 Nginx 前面还有 CDN 或网关,各层都要确认,不能从最终缺头直接认定是哪一层删除。

配置未通过或接收范围扩大后影响其他服务时,恢复原配置并重新检查、重载。采用字段改名方案时,按客户端与服务端的兼容计划一起回退;不要在故障期间直接取消认证校验。