x-forwarded-port是解决多级代理中原始端口丢失的关键头,需与x-forwarded-proto、x-forwarded-for、host协同使用,确保后端生成正确url;nginx应优先信任上游已设的x-forwarded-port,若为第一层入口则设为$server_port,并配合proxy_redirect修正重定向地址。

关键在于让后端准确识别用户访问时使用的协议、域名和端口,尤其在多级代理或 CDN 缓存后,原始端口容易丢失,导致重定向生成错误 URL(比如跳转到 http://example.com:8080 而不是 https://example.com)。X-Forwarded-Port 是解决这个问题的核心头,但必须配合其他头协同使用。
必须透传的四个基础请求头
仅设 X-Forwarded-Port 不够,后端需综合判断真实访问上下文:
-
Host $host:传递用户实际访问的域名(不含端口),避免后端误用上游地址(如localhost:3000)生成跳转 -
X-Forwarded-For $proxy_add_x_forwarded_for:保留完整 IP 链,支持日志与限流 -
X-Forwarded-Proto $scheme:明确告知是http还是https,防止 HTTPS 入口却生成 HTTP 重定向 -
X-Forwarded-Port $server_port:显式传递 Nginx 监听的端口(如 443 或 80),这是多级代理中还原用户端口的关键
为什么不能用 $http_host 替代 $host
$http_host 会原样转发客户端带的 Host 头,如果用户访问的是 example.com:8443,后端可能据此生成含 :8443 的重定向地址——而公网通常只开放 443/80,导致跳转失败。用 $host 可剥离端口,更贴近真实服务暴露方式。
多级代理场景下的端口处理逻辑
当请求经过 CDN → Nginx → 应用时,CDN 通常已设置 X-Forwarded-Port(如 443),此时你的 Nginx 不应覆盖它,而应优先信任上游头:
- 若你确认上游(如 CDN)已正确设置
X-Forwarded-Port,可省略本层proxy_set_header X-Forwarded-Port - 若你是第一层入口(无 CDN),则必须加:
proxy_set_header X-Forwarded-Port $server_port - Spring Boot 等框架默认不读
X-Forwarded-Port,需额外配置,例如:server.forward-headers-strategy=framework+ 自定义RemoteIpValve或启用use-forward-headers
配合 proxy_redirect 修正绝对重定向
即使头传对了,后端仍可能返回类似 Location: http://127.0.0.1:3000/login 的绝对地址。这时需用 proxy_redirect 主动改写:
- 匹配并替换内网地址:
proxy_redirect ~^http://[^/]+(/.*)$ $scheme://$host$1; - 若后端还带错端口(如
Location: https://example.com:8443/admin),可追加:proxy_redirect ~:(\d+)(/.*|$) $2;(去掉端口部分) - 注意:所有
proxy_redirect必须写在proxy_pass之后,否则不生效











