关键是要设server_name_in_redirect off,使重定向Location头取自请求Host头而非server_name首个域名,再配合proxy_set_header Host $host透传Host、return 301 https://$host$request_uri保原始域名,并用port_in_redirect off防端口异常。

要让 Nginx 在 HTTPS 场景下重定向时的主机头行为既安全又合规,关键不是“加 HTTPS”,而是控制好重定向 URL 中的域名来源,并确保它与用户原始访问一致、与证书匹配、与 Cookie 域名兼容。核心抓手就是 server_name_in_redirect off,再配合几个必要协同项。
必须显式关闭 server_name_in_redirect
默认值在旧版本是 on,新版虽改为 off,但不写明就容易被继承或误判。只要你的 server 块服务多个域名(比如 example.com 和 www.example.com)、或走 CDN/反代、或支持本地调试,就必须加:
- server_name_in_redirect off; —— 放在 server 块内,不能放 http 块
- 它只影响 Nginx 自动补全的重定向(如目录补斜杠、rewrite permanent、try_files 触发跳转),不干扰你手动写的 return 301 "https://..."
- 设为 off 后,Location 头里的域名直接取自请求中的 Host 头,用户输什么域名,跳转就用什么域名
确保 Host 头真实可信且全程透传
如果前面有 CDN、负载均衡器或上游 Nginx 反代,Host 头很可能被覆盖或丢失,导致 server_name_in_redirect off 失效(退回到 IP 或错误域名)。必须做两件事:
- 上游代理需透传原始 Host:
proxy_set_header Host $host;或更稳妥的proxy_set_header Host $http_host; - 若 CDN 支持 X-Forwarded-Host,后端可改用
proxy_ssl_name $http_x_forwarded_host;配合proxy_set_header X-Forwarded-Host $host; - 避免在 proxy_pass 后漏掉 Host 设置——这是重定向出错最常见配置遗漏点
HTTPS 强制跳转时别硬编码域名
HTTP → HTTPS 跳转是最常触发重定向的场景。错误写法:return 301 https://example.com$request_uri;,这会强制固定域名,丢失 www、破坏证书、绕过 server_name_in_redirect 控制。
- 正确写法:
return 301 https://$host$request_uri;—— $host 来自原始 Host 头,天然兼容多域名 - 若需统一 www 化,不用依赖 server_name_in_redirect,而应单独判断:
if ($host != 'www.example.com') { return 301 https://www.example.com$request_uri; } - 末尾加 ?(如
https://$host$request_uri?)可防止 query 参数重复拼接
补充防御:防 Host 头注入与端口异常
仅靠 server_name_in_redirect off 不足以应对所有边界风险:
- 对非标准端口(如 8080、8443),加
port_in_redirect off;,避免 Nginx 错误补 :80/:443 或漏掉真实端口 - 若业务不允许任意 Host 访问(如防 Host 头攻击),应在 location 中校验 Host:
if ($host !~ ^(example\.com|www\.example\.com)$) { return 444; } - 后端应用返回的 Location(如 302 跳转)可能含 HTTP 协议,可用
proxy_redirect ~^http://[^/]+(.*)$ https://$host$1;强制升 HTTPS


















