必须启用 proxy_ssl_server_name on 并配合 proxy_ssl_name $host(或 $http_x_forwarded_host),才能使 Nginx 在反向代理 HTTPS 后端时正确传递 SNI 域名,确保多证书环境下上游服务器选用匹配证书;否则 TLS 握手失败导致 502 等错误。

要让 Nginx 在反向代理 HTTPS 后端时正确匹配多证书环境,关键不是只打开 proxy_ssl_server_name,而是它必须和 proxy_ssl_name 配合使用,才能把客户端请求的域名准确传递给后端服务器。
为什么必须启用 proxy_ssl_server_name
Nginx 默认不发送 SNI(Server Name Indication)字段,它会用 proxy_pass 中写的地址(比如 https://10.0.0.100)去建连,这时后端收不到“用户想访问哪个域名”,只能返回默认证书或直接中断握手。常见表现是 502 错误、SSL_do_handshake() failed 或 tlsv1 alert internal error。
- 该指令仅在
proxy_pass指向 HTTPS 地址时生效 - 必须显式设为
on,默认是off - 开启后只是“具备发送能力”,SNI 字段内容仍由
proxy_ssl_name决定
proxy_ssl_name 怎么配才有效
proxy_ssl_name 的值就是最终发给后端的 SNI 域名,必须与客户端原始意图一致,否则后端选错证书或拒绝连接。
⚠️ 已弃用 — 该技能已拆分为两个独立技能,以提升模块化程度:**webchat-https-proxy**(HTTPS/WSS 反向代理)和 **webchat-voi...**
- 常规场景:用
$host—— 它来自请求头 Host,已标准化,不含端口 - CDN 回源场景:CDN 可能改写 Host 头,需开启透传并改用
$http_x_forwarded_host - 避免写死字符串(如
"api.example.com"),除非所有请求都指向同一域名 - 若用
upstream块,proxy_ssl_name必须是字符串(带引号),不能是变量,除非配合map动态映射
动态多域名路由的配置方式
当一个 Nginx 实例要代理多个不同后端域名(例如按 Host 头分发到不同微服务),需要用 map 提前定义 SNI 映射关系:
- 在
http块中定义:map $host $backend_sni { hostnames; example-a.com "api.a.com"; example-b.com "api.b.com"; default "default.api.com"; } - 在
location中写:proxy_ssl_server_name on;和proxy_ssl_name $backend_sni; - 确保
proxy_pass使用 HTTPS 协议,并指向能解析该域名的 upstream 或直连地址
验证是否真正生效
光看配置是否写对没用,得确认 TLS 握手时发出的 SNI 值确实是预期域名:
- 在上游服务端开启 debug 日志,搜索
client sent server name看收到的值 - 用命令模拟:
openssl s_client -connect 后端IP:443 -servername your-domain.com,观察返回的证书是否匹配 - 抓包检查 Client Hello 是否携带
server_name扩展字段










