Nginx在SNI环境下反向代理HTTPS后端需协同配置proxy_ssl_server_name on与proxy_ssl_name(值为域名而非IP),并确保proxy_pass使用域名、Host头与SNI严格一致,否则TLS握手失败导致502/403等路径异常。

要让 Nginx 在 SNI 环境下正确反向代理到后端 HTTPS 服务并避免路径相关报错(如 502、403、证书不匹配或重定向异常),关键不是单独配 proxy_ssl_name,而是把它和 proxy_ssl_server_name on、proxy_set_header Host 以及 proxy_pass 的写法协同配置。很多“路径报错”表面看是 location 或 rewrite 问题,实则是 TLS 握手阶段 SNI 不匹配,导致后端根本没收到请求,或返回了错误证书/默认路由。
必须成对启用:proxy_ssl_server_name + proxy_ssl_name
proxy_ssl_name 本身不会生效,除非先开启 proxy_ssl_server_name on。Nginx 默认用 proxy_pass 中的字面主机名(比如 https://192.168.1.10:443)作为 SNI 值;若该值与后端期望的域名不一致,就会在握手时失败——此时哪怕路径完全正确,也进不了后端逻辑。
- 静态场景(单域名固定回源):直接写死域名,加引号
proxy_ssl_name "api.example.com"; - 动态场景(多域名共用一套配置):优先用
$host,它已自动去除端口,且来自 Host 请求头proxy_ssl_name $host; - 经 CDN 或 WAF 中转时:若 Host 被改写(如 Cloudflare 改为
origin.example.com),需改用$http_x_forwarded_host,前提是 CDN 开启了透传原始 Host
proxy_pass 必须用域名,不能用 IP
如果 proxy_pass https://10.10.10.10/,即使开了 proxy_ssl_server_name on,Nginx 仍会把 10.10.10.10 当作 SNI 发送——而绝大多数云服务、CDN、微服务网关都不接受 IP 作为 SNI 值,直接拒绝握手。
- 正确写法:
proxy_pass https://api.example.com/;(结尾斜杠影响路径拼接,注意保持一致) - 使用 upstream 时,upstream 块里只写域名+端口:
server api.example.com:443;,SNI 配置仍放在 location 中 - 避免混合写法,例如
proxy_pass https://$host/—— 变量在 proxy_pass 中不支持 SSL SNI 解析,会导致 SNI 为空
Host 头必须与 SNI 严格一致
部分后端(尤其是云厂商 API 网关、OSS 存储、Istio Ingress)会同时校验 SNI 和 Host 头。两者不一致时,可能返回 403 或静默丢弃请求,尤其在签名验证类服务中(如预签名 URL)。
- 显式设置 Host 头:
proxy_set_header Host "api.example.com";(字符串形式,不带变量) - 不要用
$host或$http_host,它们可能含端口(如example.com:443)或客户端伪造内容,破坏签名或触发校验失败 - 若需保留原始 Host 供日志分析,可额外加:
proxy_set_header X-Original-Host $host;
路径转发常见连带问题补救
SNI 配置正确后,仍可能出现路径报错,往往因后端响应重定向(301/302)或内部跳转引发。这些不是 SNI 问题,但常被误判:
- 后端返回
Location: /new/path→ 客户端跳转到 Nginx 根路径,丢失前缀。用proxy_redirect修正:proxy_redirect / /admin/;(将后端返回的根路径重写为 /admin/ 下) - 后端返回绝对重定向(如
Location: https://backend.com/path)→ 客户端直连后端,绕过 Nginx。应设:proxy_redirect https://backend.com/ /admin/; - 路径末尾斜杠不一致导致 404:确保
proxy_pass和 location 的斜杠逻辑匹配,例如:
location /api/ { proxy_pass https://backend/api/; } → 会剥离 /api/ 并追加











