x-forwarded-proto 丢失本质是中间 nginx 未透传或覆盖该头,需逐级验证存在性与值、开启 underscores_in_headers、用 $http_x_forwarded_proto 透传并兜底 $scheme,后端须启用可信代理解析。

多级 HTTPS 代理下 X-Forwarded-Proto 丢失,本质是中间某一级 Nginx 没有透传或覆盖了该头部,导致后端应用误判协议,出现重定向降级(如 https→http)、资源链接错用 HTTP、安全头校验失败等问题。关键不在“加不加”,而在“怎么传、传什么、谁来读”。
确认问题是否真出在 X-Forwarded-Proto
不要凭现象直接改配置。先验证:
- 在最终后端服务中打印所有请求头(例如 Spring Boot 的
request.getHeaders()或 Node.js 的console.log(req.headers)),确认x-forwarded-proto字段是否存在、值是否为https - 逐级检查每台 Nginx 的 access 日志或用
curl -v+tcpdump抓包,看该头部是否在某一级被删掉、写空、或被硬编码覆盖 - 注意大小写:Nginx 默认忽略含下划线的 header(如
X-Forwarded-Proto),若上游用了小写x-forwarded-proto,下游 Nginx 需开启underscores_in_headers on;
统一使用 $http_x_forwarded_proto 透传(推荐)
当存在多级代理(如 HAProxy → Nginx → Spring Boot)时,最外层代理已设置 X-Forwarded-Proto: https,后续每一级都应继承而非覆盖:
- 中间层 Nginx 配置中,不要写死
proxy_set_header X-Forwarded-Proto https;—— 这会切断链路,无法兼容混合协议场景 - 应改用:
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;,它会读取上一级传来的原始值并原样转发 - 若上一级未设该头,
$http_x_forwarded_proto为空,此时可兜底:proxy_set_header X-Forwarded-Proto $scheme;放在后面(Nginx 会以最后一条生效)
后端必须启用可信代理配置
光传头部没用,后端框架默认不信任 X-Forwarded-* 头,需显式启用解析:
- Spring Boot(2.6+):在
application.yml中配置
server.forward-headers-strategy: framework
并确保spring.cloud.gateway.x-forwarded.*(如使用网关)或 WebMvc 配置允许信任代理 IP - Spring Boot(旧版)或手动处理:需设置
server.tomcat.remoteip.remote-ip-header=x-forwarded-for和server.tomcat.remoteip.protocol-header=x-forwarded-proto - Node.js(Express):启用
app.set('trust proxy', true)或指定可信代理网段
避免常见干扰项
这些细节常被忽略,却直接导致头部“消失”:
-
重复定义覆盖:检查是否在
http、server、location多个层级都写了proxy_set_header X-Forwarded-Proto,后者会覆盖前者 -
SSL 终止位置错误:如果 HTTPS 在第二层 Nginx 终止,但第一层(如 CDN 或 LB)没传
X-Forwarded-Proto,那么第二层拿到的是$scheme=http(因它只看到内部 HTTP 请求),此时必须由第一层补全 -
header 名拼写/格式错误:Nginx 中变量名严格区分大小写和连字符,
$http_x_forwarded_proto不能写成$http_x_forwarded_proto(少一个 o)或$http_X_Forwarded_Proto











