proxy_ssl_name 是 Nginx 反向代理中显式指定 TLS 握手 SNI 字段值的关键指令,必须与 proxy_ssl_server_name on 配合使用,且其值需与上游证书 SAN 精确匹配,否则导致 TLS 握手失败并返回 502。

nginx 中没有 ssl_name 这个参数,真正起作用的是 proxy_ssl_name,它在 HTTPS 后端回源场景中承担着明确指定 TLS 握手阶段 SNI 字段内容的关键角色。
proxy_ssl_name 是 SNI 字段的“填写人”
当 Nginx 作为反向代理访问 HTTPS 上游时,默认不发送 SNI 扩展(proxy_ssl_server_name 默认为 off)。即使你写了 proxy_pass https://api.example.com,Nginx 解析出 IP 后仍以纯 IP 建连,上游无法得知客户端本意访问哪个域名。这时 proxy_ssl_name 就是告诉 TLS 层“该往 ClientHello 的 SNI 字段里填什么”的唯一指令:
- 它的值必须与上游证书的 SAN(Subject Alternative Name)精确匹配,比如
"api.example.com"或变量$host - 它本身不生效,必须配合
proxy_ssl_server_name on—— 后者触发调用 OpenSSL 的SSL_set_tlsext_host_name(),把proxy_ssl_name的值塞进 SNI 扩展 - 单独配置其中任意一项,等同于未配置;TLS 握手失败,常见表现为 502 Bad Gateway
为什么不能靠 proxy_pass 地址自动推导
proxy_pass https://api.example.com 中的域名仅用于 DNS 解析,Nginx 不会自动将其用作 SNI 值。尤其在以下情况更明显:
- upstream 块中定义的是 IP 地址(如
server 10.0.1.5:443),完全无域名可参考 - 一个 location 需代理多个不同域名的后端(如按请求头路由),必须动态指定 SNI
- 后端是多租户网关或 CDN,同一 IP 托管数十个域名,SNI 是唯一区分依据
实际配置中的关键细节
正确写法需三项协同,缺一不可:
-
proxy_ssl_server_name on;—— 开启 SNI 发送能力 -
proxy_ssl_name $host;或proxy_ssl_name "api.example.com";—— 明确 SNI 内容(推荐用$host,已标准化、不含端口) -
proxy_set_header Host $host;—— 确保 HTTP 层也透传原始域名,避免上游因 Host 头缺失或错误而拒绝请求
若使用 upstream 块,proxy_ssl_name 仍需显式声明,不能省略;若需动态适配,可用 map 或请求头提取变量,但值必须合法、无空格、不含非法字符。
和 server 块里的 ssl_certificate 无关
注意区分:proxy_ssl_name 只影响 Nginx 与上游建立 TLS 连接时的行为,属于“出向 SNI”;而 ssl_certificate 和 server_name 控制的是 Nginx 自己作为 HTTPS 服务端接收请求时的“入向 SNI”处理逻辑。两者作用方向相反,不能互相替代或混淆。


















