关键在于 proxy_ssl_server_name on 必须与 proxy_ssl_name $host(或 $http_x_forwarded_host)配合使用,才能让 nginx 在反向代理 https 后端时正确传递 sni 信息,确保单 ip 多域名场景下后端选用匹配证书,避免 tls 握手失败。

要让 Nginx 在反向代理 HTTPS 后端时正确传递 SNI 信息,关键不是只打开 proxy_ssl_server_name,而是它必须和 proxy_ssl_name 配合使用,才能让后端从单个 IP 上准确选出对应域名的证书。
必须同时启用并动态设置 SNI 字段
默认情况下,Nginx 会用 proxy_pass 中写的地址(比如 https://10.0.0.100)作为 SNI 值,这在后端只服务一个域名时没问题;但当后端一个 IP 绑定多个域名、每个域名配了独立证书(如 CDN 回源、多租户网关),就必须显式告诉 Nginx:“这次请求用户要的是哪个域名”。否则 TLS 握手失败,连接直接中断。
- 在
location或upstream块中添加:proxy_ssl_server_name on; - 紧接着设置:
proxy_ssl_name $host;(推荐)或proxy_ssl_name $http_host; - 避免写死静态值,例如
proxy_ssl_name "api.example.com",除非所有请求都指向同一域名
应对 CDN 回源时 Host 被覆盖的情况
很多 CDN(如 Cloudflare、阿里云全站加速)回源时会强制改写 Host 头为源站配置域名,导致 $host 变成源站名而非用户原始域名,SNI 就会错配。
安全更新和维护 CLI Proxy API(CPA)部署与配置。用于 CPA 镜像升级、配置变更、认证目录兼容修复、上线验证与回滚。适用于用户提到“CPA 更新/升级/配置改了/容器重建/回滚”等场景。
- 在 CDN 控制台开启“透传原始 Host”功能,通常表现为传递
X-Forwarded-Host头 - Nginx 中改用:
proxy_ssl_name $http_x_forwarded_host; - 同时建议加一句:
proxy_set_header X-Forwarded-Host $host;,方便后端识别真实请求来源
验证 SNI 是否真正生效
光看配置是否写对不够,得确认 TLS 握手时发出的 SNI 值确实是预期域名。
- 在上游服务器开启 debug 日志:
error_log /var/log/nginx/error.log debug; - 触发一次请求后,搜索日志中类似
"client sent server name"的条目 - 更直接的方式:用命令模拟请求:
openssl s_client -connect 上游IP:443 -servername your-domain.com,观察返回的证书是否匹配该域名
补充说明:静态回源场景下的常见误区
所谓“静态回源”,通常指 Nginx 直接写死 proxy_pass https://10.0.0.100 这类不带域名的地址。这种写法本身就会让 SNI 缺失或错位——因为 Nginx 没有上下文判断该用哪个域名。
- 即使后端是静态 IP,只要它承载多个 HTTPS 域名,就必须通过
$host或$http_x_forwarded_host动态注入 SNI - 不要依赖“后端自己猜”,SNI 是客户端(这里是 Nginx)在 TLS 握手初始阶段主动发送的,后端不会反向推导
- 如果后端是自建 Nginx,还需确保其
server块中定义了对应server_name并加载了正确证书










