疑难杂症 · 23 2 月, 2026 0

Nginx 301跳转泄露内部端口?理解Nginx重定向构造逻辑

🤔发生肾么事了

笔者在使用 Nginx 搭建站点test.henchat.net。架构如下:

  • 前端:Nginx stream,使用 ssl_preread 做 SNI 分流
  • 后端:Nginx 监听内部端口 10443,处理 HTTPS
  • 后端有目录补全逻辑(例如 /xxx/xxx/

然而搭建好后遇到了一个非常诡异的问题。当用户访问:

https://test.henchat.net/xxx

后端会返回:

301 → https://test.henchat.net:10443/xxx/

访问 https://test.henchat.net/xxx 时,后端返回的 301 跳转竟然变成了 https://test.henchat.net:10443/xxx/

看起来像是 Nginx“泄漏”了内部端口,但其实这是 Nginx 的默认行为导致的。本文将解释为什么会出现这种情况,以及如何用 port_in_redirect 设置完美解决。

😮根本原因

Nginx 在生成 301/302 跳转时,会自动使用以下变量:

  • $scheme(https)
  • $host(test.henchat.net)
  • $server_port(后端监听端口)

如果后端监听:

listen 10443 ssl;

那么 $server_port 就是 10443

于是 Nginx 构造出的跳转 URL 就变成:

https://test.henchat.net:10443/xxx/

这就是内部端口“泄漏”的根本原因。

🛠️解决方法

只需在后端 10443 的 server 块中加入 port_in_redirect off; 即可解决:

server {
    listen 10443 ssl;
    server_name test.henchat.net;

    port_in_redirect off; # <-加入

    ...
}

关于“port_in_redirect”的说明

port_in_redirect 控制 重定向 URL 是否包含端口号。默认值是:

port_in_redirect on;

表示:

重定向 URL 必须带上 $server_port

当你关闭它时,Nginx 构造跳转 URL 时就会忽略端口号。而这才是我们想要的行为。