关键在于正确配置 proxy_ssl_server_name on 和 proxy_ssl_name $host,否则 Nginx 默认以 IP 或固定域名发送 SNI,导致单 IP 多证书后端因 SNI 不匹配而 TLS 握手失败、返回默认证书或 502 错误。

要让 Nginx 在反向代理到单 IP 多证书后端(如多租户 SaaS、云存储网关、CDN 回源目标)时不出错,关键不是只打开 SNI,而是让 proxy_ssl_name 把客户端真正请求的域名准确传过去——proxy_ssl_server_name on 只是开关,proxy_ssl_name 才决定发什么。
为什么单 IP 多证书场景下默认会失败
后端用一个 IP 托管多个 HTTPS 域名(比如 shop-a.example.com 和 shop-b.example.com),每个域名配了独立证书。Nginx 默认用 proxy_pass https://10.0.0.100 中的 IP 或写死域名当 SNI 值,结果所有请求都发同一个 SNI,后端只能返回默认证书或直接拒绝,导致 TLS 握手失败、502 错误、登录跳转异常等。
必须同时配置的两个指令
缺一不可:
-
启用 SNI 扩展:在
location或upstream块中加proxy_ssl_server_name on; -
指定 SNI 内容:紧跟着写
proxy_ssl_name $host;(推荐)或proxy_ssl_name $http_host;;$host已标准化、不含端口,更稳妥
应对 Host 被覆盖的常见变体
前端有 CDN、WAF 或 API 网关时,它们常把 Host 头改写为源站名(如 origin.example.com),导致 $host 失真:
- 开启 CDN 的“透传原始 Host”功能,让它带上
X-Forwarded-Host头 - Nginx 中改用
proxy_ssl_name $http_x_forwarded_host; - 顺带加上
proxy_set_header X-Forwarded-Host $host;,方便后端日志溯源
验证是否真正生效
不能只看配置有没有写,得确认 TLS 握手时发出的 SNI 值就是用户访问的域名:
- 在上游服务(如另一台 Nginx)开启 debug 日志:
error_log /var/log/nginx/error.log debug;,搜索client sent server name看输出值 - 用 OpenSSL 手动模拟:
openssl s_client -connect 10.0.0.100:443 -servername shop-a.example.com,检查返回证书的 SAN 是否匹配 - 注意:若上游不支持 SNI,或 OpenSSL 版本低于 1.0.2h,仍会失败


















