DEBUG.WIKI
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS
IPPeak:从目标地区访问网页,住宅代理、SEO 监测、广告验证
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国

Nginx 反代应用重定向时丢失公开端口

定位上游 Location 中错误的公开地址,核对 Host 与公开 origin,必要时在单应用范围精确使用 proxy_redirect。

通过 https://app.example.com:8443/ 访问 Nginx 后面的应用,页面正常,应用一重定向却跳到不带 8443 的地址。浏览器随后连接默认端口,表现为连接失败、落到另一个站点,或者回到错误入口。

先检查这一次响应的 Location。如果它已经缺少公开端口,浏览器只是照着地址跳转。此时要区分上游应用生成的重定向与 Nginx 自己生成的重定向,不能只靠修改监听端口处理。

先保存第一跳的地址

用浏览器网络面板保留请求记录,或在测试环境对一个可重复读取的路由查看响应头。示例故意不加 --location,避免跟随跳转后看不见第一跳:

curl --silent --show-error --dump-header - --output /dev/null \
  'https://app.example.com:8443/start'

/start 是占位路由,替换成允许测试且会触发该跳转的实际入口。不要把含 Cookie 或认证令牌的响应头直接公开。

例如实际看到:

Location: http://app.example.com/login

就同时存在公开 scheme 和端口不一致。结合应用日志或受控环境下的上游响应,确认这一字段是否由应用发出。直接访问上游时必须保持相同路由、方法和应用需要的 Host 等条件;不等价的请求不能用于归因。

如果应用返回的 Location 正确,公开响应却不同,应检查代理已有的改写规则。如果请求没有进入应用,或是 Nginx 给缺少末尾斜杠的目录入口生成了跳转,则不属于本文的上游响应改写场景。

让应用知道固定的公开地址

后端在内部端口运行,并不意味着它能自行推断用户访问的公开端口。优先检查应用的 external URL、public origin 或受信任代理设置,让它生成完整的 https://app.example.com:8443 地址。具体配置名称和信任规则由应用决定。

若已经确认应用依据传入的 Host 构造跳转,而代理使用了 proxy_set_header Host $host,需注意这个主机名变量不能用来保留原始 Host 字段的完整端口信息。对只服务一个固定公开地址的虚拟主机,可以在原有代理块中明确设置:

proxy_set_header Host app.example.com:8443;

这是对现有 Host 设置的替换,不要在同一处重复添加。保留应用要求的其他代理头及其信任限制。特别是 proxy_set_header 只有在当前层没有任何该指令时才整体继承上一层配置;在原本依赖继承的 location 增加一条 Host,可能使其他头不再继承,应把所需设置一起核对。

Host 本身不携带 scheme。应用还必须通过自己的公开 URL 或正确且受信任的代理协议头确定 HTTPS。不要假设设置一个 Host 就能修复所有 HTTPS 跳转,也不要直接信任客户端任意提供的转发头。

公开端口可能与 Nginx 实际监听端口不同,例如前面还有端口映射或负载均衡器。因此不能一律拼接 $server_port。使用 $http_host 会保留收到的原始 Host 字段,但也会带入客户端输入;若选择这种动态方式,必须已有严格的允许主机和端口校验。固定地址的示例不需要放宽到任意 Host。

无法调整应用时,精确改写已确认的 Location

若上游只能返回前面的 http://app.example.com/...,可在该应用的现有代理 location 中使用明确的前缀替换:

proxy_redirect http://app.example.com/ https://app.example.com:8443/;

这会把已匹配的地址前缀换成指定公开地址,后面的 /login 等路径仍保留。必须按实际响应填写原前缀;上游若返回的是 http://127.0.0.1:3000/,上面这条不会匹配,不能把示例域名原样留在配置里。

proxy_redirect 处理代理响应的 Location 和 Refresh 字段,不改 HTML、JavaScript、Cookie,也不能为应用建立正确的 OAuth 回调注册。它不改变请求侧的 proxy_pass URI。登录流程还依赖这些内容时,应继续修应用的外部地址约定。

检查已有的 proxy_redirect off、默认规则和继承关系,在该应用范围内替换或整理,不能给整个站点套一个匹配所有域名的正则。同级多个规则能够匹配时,第一条生效。显式前缀适合这里已确认的单个错误地址;第三方身份提供商等合法外部跳转应保持原目标,不能统统拉回本站。

核对完整跳转链再结束

备份本次涉及的代理与应用设置,在本地对应配置中检查语法:

nginx -t -c /etc/nginx/nginx.conf

检查通过后按已有部署流程加载。直接管理的实例在确认配置路径、运行前缀和 master 一致后,可使用 nginx -s reload -c /etc/nginx/nginx.conf。不要仅凭语法通过认定应用生成地址已经改变。

再次观察第一跳和后续跳转,确认目标始终是允许的 scheme、主机和公开端口,路由、查询参数及必要的认证回调没有改变;再检查不需要跳转的请求和其他虚拟主机。不能只以最终某个页面返回 200 为通过标准。

出现新的循环、错误端口或认证问题时,恢复本次相关的 Host、应用公开 URL 或 proxy_redirect 改动,重新检查和加载,并核对跳转链。分清是哪一项生效后再调整,避免同时改多个入口而失去比较依据。