关键在于透传x-forwarded-proto、host、port头使后端生成正确location,proxy_redirect仅作兜底;需启用proxy_ssl_server_name并校准sni,最后逐层验证生效。

要让 Nginx 负载均衡层真正“兜住”后端重定向,关键不是强行改写所有 Location,而是让后端自己生成正确的跳转地址——Nginx 只负责把原始请求的协议、端口、Host 信息准确透传过去。一旦后端拿到真实上下文,它就能返回 HTTPS + 正确端口的 Location,自然就不用手动 patch 了。
透传协议与主机头是前提
后端判断跳转协议,依赖 X-Forwarded-Proto 和 X-Forwarded-Host(或 X-Forwarded-Port)。如果这些头缺失或错误,后端大概率会默认用 HTTP + 80 端口生成 Location。
- 在 server 或 location 块中必须显式设置:
proxy_set_header X-Forwarded-Proto $scheme;proxy_set_header X-Forwarded-Host $host;proxy_set_header X-Forwarded-Port $server_port; - 若前端是 HTTPS 但 Nginx 与后端走 HTTP,则 $scheme 是 https,$server_port 是 443 —— 这样后端就知道该拼
https://example.com:443/xxx - 避免只写
$http_x_forwarded_proto:这是读取客户端传来的值,不可信;应以 Nginx 自身收到的为准(即 $scheme)
proxy_redirect 不是补丁,而是兜底策略
当后端仍返回错误 Location(比如硬编码了 http://127.0.0.1:8080),就需要用 proxy_redirect 主动修正。它的作用不是替代透传,而是最后一道防线。
- 若后端返回
Location: /login(相对路径),且proxy_pass http://backend:8080/api/;(带尾斜杠),则配:proxy_redirect / /api/; - 若后端返回
Location: http://127.0.0.1:8080/dashboard(绝对 URL),且前端是 HTTPS,则配:proxy_redirect http://127.0.0.1:8080/ https://$host:$server_port/; - 注意:proxy_redirect 必须放在与 proxy_pass 同级的 location 块内,且匹配规则区分大小写、严格按字符串前缀匹配
多域名 + HTTPS 回源时 SNI 必须对齐
当 Nginx 负载均衡后端是 HTTPS 服务(如另一套 Nginx 或云 WAF),且托管多个域名时,后端需根据 SNI 选择对应证书。若 SNI 错误,连接可能直接失败,更别说重定向了。
- 启用 SNI:
proxy_ssl_server_name on; - 动态设置 SNI 值为客户端原始 Host:
proxy_ssl_name $host; - 若经 CDN 回源,CDN 往往会覆盖 Host 头,此时应开启 CDN 的“透传原始 Host”功能,并改用:
proxy_ssl_name $http_x_forwarded_host;
同时加proxy_set_header X-Forwarded-Host $host;确保下游可读
验证是否生效,别只看配置
配置写完不等于跑通。真实生效需要逐层验证:
- 用 curl 模拟请求,检查响应头:
curl -I https://your-domain.com/login
看返回的 Location 是否已是 https + 正确端口 - 查 Nginx error.log(开 debug 日志)确认 SNI 值是否发出正确:
搜索client sent server name行,比对是否等于用户访问的域名 - 抓包看后端响应的原始 Location 字段,再对比浏览器最终跳转地址,定位问题发生在哪一层(透传?proxy_redirect?还是后端逻辑?)











