关键配置是proxy_set_header X-Forwarded-Proto $scheme;,$scheme动态取值http或https,不可写死;需配合Host、X-Real-IP、X-Forwarded-For等头,并在后端框架中启用对应信任解析。

要在 Nginx 中正确透传客户端原始协议(HTTP 或 HTTPS),关键就是配置 X-Forwarded-Proto 请求头,且必须用动态变量,不能写死。
核心配置:用 $scheme 动态传递协议
在对应 location 块中添加这一行:
proxy_set_header X-Forwarded-Proto $scheme;
$scheme 是 Nginx 内置变量,值自动为 http 或 https,取决于客户端直连 Nginx 时使用的协议(由 listen 80 或 listen 443 ssl 决定)。
绝对不要写成 proxy_set_header X-Forwarded-Proto https;——这会导致所有请求(包括 HTTP 访问)都被标记为 HTTPS,后端可能因此误发 Secure Cookie、强制跳转 HTTPS,甚至引发重定向死循环。
多层代理时的稳妥处理
如果请求经过 CDN、WAF 或前置负载均衡,X-Forwarded-Proto 可能已被上游设置。Nginx 默认会覆盖它,带来风险。
推荐做法是只在最外层(直面客户端)的 Nginx 上设置该头,内层代理不再重复设置。
若必须兼容上游值,可在 http 块中定义兜底逻辑:
map $http_x_forwarded_proto $real_scheme { default $http_x_forwarded_proto; "" $scheme; }- 然后在
location中使用:proxy_set_header X-Forwarded-Proto $real_scheme;
配套必须转发的其他头部
单传 X-Forwarded-Proto 不够,后端还原完整请求上下文还需以下头:
-
proxy_set_header Host $host;—— 自动剥离端口,避免后端生成example.com:443这类错误跳转地址 -
proxy_set_header X-Real-IP $remote_addr;—— 提供直连场景下的真实客户端 IP -
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;—— 追加式记录 IP 链,兼容多级代理 -
proxy_set_header X-Forwarded-Host $host;—— 显式透传原始域名,比$http_host更干净
后端必须启用对该头的信任解析
Nginx 设置了头,后端不读取等于白配。不同框架需显式开启支持:
-
Django:设置
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https'),并启用USE_X_FORWARDED_HOST = True -
Flask:使用
ProxyFix中间件,如app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1) -
Express/Node.js:调用
app.set('trust proxy', true) -
Spring Boot:配置
server.forward-headers-strategy=framework,确保 Tomcat 的RemoteIpValve生效
改完配置后,务必在后端打印 req.headers['x-forwarded-proto'] 验证:HTTP 访问应输出 http,HTTPS 访问应输出 https。











