关键是要同时启用 proxy_ssl_server_name on 并设置 proxy_ssl_name $host(或 $http_x_forwarded_host),才能让 Nginx 在反向代理多证书 HTTPS 后端时正确传递 SNI 域名,避免 TLS 握手失败。

要让 Nginx 在反向代理到后端多站点 HTTPS 服务时正确匹配 SNI,关键不是只写 proxy_ssl_name,而是让它和请求意图一致——即告诉上游“用户真正想访问哪个域名”。默认情况下,Nginx 会用 proxy_pass 中写的域名(或 IP)作为 SNI 值,这在多证书环境下极易错配。
必须开启 SNI 并动态传入真实域名
proxy_ssl_server_name on 是前提,它启用 TLS 握手时发送 SNI 扩展的能力。但光开这个不够,SNI 字段内容必须反映客户端原始请求:
- 添加
proxy_ssl_server_name on;到location或upstream对应的配置块中 - 设置
proxy_ssl_name $host;—— 这是最常用且推荐的方式,$host来自请求头 Host 字段,已标准化、不含端口 - 避免写死如
proxy_ssl_name "api.example.com";,除非所有流量都指向同一后端域名
应对 CDN 回源时 Host 被覆盖的情况
很多 CDN(如 Cloudflare、阿里云全站加速)回源时会强制改写 Host 头为源站配置域名,导致 $host 变成 origin.example.com 而非用户原始请求的 shop-a.com,SNI 就会错配:
⚠️ 已弃用 — 该技能已拆分为两个独立技能,以提升模块化程度:**webchat-https-proxy**(HTTPS/WSS 反向代理)和 **webchat-voi...**
- 在 CDN 控制台开启“透传原始 Host”功能,通常表现为传递
X-Forwarded-Host头 - Nginx 中改用
proxy_ssl_name $http_x_forwarded_host; - 同时建议加一句
proxy_set_header X-Forwarded-Host $host;,方便后端识别真实请求来源
upstream 场景下不能省略 proxy\_ssl\_name
如果你用 upstream 做负载均衡(比如对接多个微服务实例),仅设 proxy_ssl_server_name on 不够。Nginx 解析 upstream 域名得到 IP 后,TLS 握手仍需明确告知服务器名称:
- upstream 定义保持简洁:
upstream api_backend { server api.example.com:443; } - 在 location 中必须指定:
proxy_ssl_name "api.example.com";(注意加引号,值必须是字符串) - 配套保留:
proxy_ssl_server_name on;和proxy_set_header Host "api.example.com";
验证是否真正生效
配置写对不等于生效,得确认 TLS 握手时发出的 SNI 值确实是预期域名:
- 在上游服务器(如另一台 Nginx)的
error_log中加入debug级别:error_log /var/log/nginx/error.log debug; - 触发一次请求后,搜索日志中类似
"client sent server name"的条目,确认输出的 SNI 是否匹配(如shop-a.com) - 更直接的方式:用
openssl s_client -connect 上游IP:443 -servername your-domain.com模拟请求,观察返回的证书是否对应该域名










