nginx未传递客户端真实端口导致后端获取失败,根本原因是proxy_set_header host默认使用$host(自动剥离端口),需改为$host:$server_port或$http_host,并补充proxy_set_header x-forwarded-port $server_port,同时配合x-forwarded-proto确保协议一致性。

后端拿不到真实端口,本质是 Nginx 没把客户端访问的端口信息正确传递过去。关键不在后端代码改不改,而在 Nginx 的 proxy_set_header 配置是否精准覆盖了端口场景。
确认 Host 头是否携带端口
HTTP 协议中,Host 请求头决定后端如何解析入口地址。Nginx 默认用 $host 变量,它**自动剥离端口号**(比如请求 https://example.com:8443,$host 只输出 example.com)。后端读 Host 就永远看不到 8443。
- 必须改成
proxy_set_header Host $host:$server_port;—— 显式拼接端口,让后端收到完整example.com:8443 - 若只走标准 HTTPS(443)且不暴露非标端口,可用
proxy_set_header Host $http_host;,它直接复用客户端原始 Host 头(含端口) - 绝对避免写死
proxy_set_header Host example.com;或用$proxy_host,这会彻底覆盖原始值
检查 X-Forwarded-Port 是否被后端依赖
有些框架(如 Spring、某些 Java Web 容器)不直接读 Host 头,而是靠 X-Forwarded-Port 判断端口。Nginx 默认不传这个头,需手动补全:
- 首层 Nginx(直连客户端)加:
proxy_set_header X-Forwarded-Port $server_port; - 如果中间还有代理(如 CDN → Nginx → 后端),下一层要继承:
proxy_set_header X-Forwarded-Port $http_x_forwarded_port; - 后端应用必须主动读取该头,不能只依赖
getServerPort()这类容器默认方法
验证 HTTPS 终止与协议一致性
当 Nginx 终止 HTTPS(监听 443),再以 HTTP 转发给后端(如 8080),后端可能误判为 HTTP 请求,导致生成的跳转链接用 http:// + 80 端口,而非 https:// + 443。
- 务必配置:
proxy_set_header X-Forwarded-Proto $scheme;(传https或http) - 配合
proxy_set_header X-Forwarded-Host $http_host;,确保后端能还原原始访问域名+端口组合 - 后端生成重定向或绝对 URL 时,必须基于
X-Forwarded-Proto和X-Forwarded-Host构造,而不是硬编码协议或读取内网地址
快速验证与日志定位
别猜,直接看实际转发的请求头:
- 在后端加临时日志,打印所有入参头:
X-Forwarded-Port、X-Forwarded-Proto、Host、X-Forwarded-For - 对比 Nginx access log 中的
$http_host和$server_port变量值,确认是否匹配客户端真实请求 - 用 curl 测试:
curl -H "Host: example.com:8443" https://your-nginx-domain/,观察后端收到的 Host 值











