nginx 无法透传 http 协议版本,因其属于请求行而非请求头;应通过 proxy_set_header x-forwarded-proto $scheme; 透传客户端原始协议(http/https),后端需主动信任并解析该头以正确生成 url、跳转及安全 cookie。

Nginx 无法透传 HTTP 协议版本(如 HTTP/1.1 或 HTTP/2),因为协议版本不属于请求头,而是请求行的一部分,由 TCP 连接协商决定,不能被 proxy_set_header 设置或转发。
真正需要透传的是客户端发起请求时使用的协议类型(HTTP 还是 HTTPS),这关系到后端生成跳转地址、判断安全上下文等逻辑。Nginx 通过标准请求头 X-Forwarded-Proto 实现这一目的。
X-Forwarded-Proto 是透传源协议的关键
这个头字段告诉后端:用户最初是用 HTTP 还是 HTTPS 访问的 Nginx。后端据此决定是否生成 https:// 链接、是否强制跳转、是否启用安全 Cookie 等。
-
$scheme变量会自动取值为http或https,取决于客户端连接方式 - 推荐写法:
proxy_set_header X-Forwarded-Proto $scheme; - 不推荐硬编码写死,例如
proxy_set_header X-Forwarded-Proto https;(会误判 HTTP 请求)
多层代理下要确保头不被覆盖或伪造
如果请求经过 CDN、WAF 或前置 LB,X-Forwarded-Proto 可能已被上游设置。此时需注意:
- Nginx 默认会覆盖已有
X-Forwarded-Proto,若信任上游,可加条件判断(需配合map指令或 Lua) - 更稳妥的做法是:只在最外层 Nginx 设置该头,内层代理不重复设置,避免污染
- 若必须保留上游值,可用
proxy_pass_request_headers off;+ 手动透传,但需谨慎校验来源
后端必须主动读取并信任该头
Nginx 只负责“发”,后端框架需明确启用对 X-Forwarded-Proto 的解析:
- Spring Boot:设
server.forward-headers-strategy=framework,并确认 Tomcat 使用RemoteIpValve - Flask:启用
ProxyFix中间件,指定x_for=1, x_proto=1 - Express:
app.set('trust proxy', true),并确保req.protocol返回正确值 - PHP:检查
$_SERVER['HTTP_X_FORWARDED_PROTO'],而非依赖$_SERVER['HTTPS']
其他相关协议信息补充(按需)
-
X-Forwarded-Host:透传原始 Host,防止后端拼错域名 -
X-Forwarded-Port:透传原始端口(如 443 或 80),尤其在非标端口部署时有用 -
X-Forwarded-For:配合set_real_ip_from使用,才能准确提取真实客户端 IP
不复杂但容易忽略











