必须启用 proxy_ssl_server_name on 并配合 proxy_ssl_name 指令,否则 HTTPS 后端因缺失 SNI 无法选择正确证书,导致 TLS 握手失败;还需 proxy_set_header Host $host 保持请求头一致。

要让 Nginx 在代理到 HTTPS 后端时正确识别并传递目标域名,必须启用 proxy_ssl_server_name 并配合 proxy_ssl_name。否则,当一个 IP 对应多个 HTTPS 域名(如 CDN 回源、SaaS 多租户场景),上游服务器无法判断该返回哪张证书,会默认返回一张不匹配的证书,导致 TLS 握手失败或证书校验报错。
为什么必须显式开启 proxy_ssl_server_name
Nginx 默认关闭 SNI 扩展(proxy_ssl_server_name off),即在与后端建立 TLS 连接时,Client Hello 中不携带 Server Name 字段。这意味着:
- 上游若为 Nginx、Traefik、ALB 或支持多域名证书的网关,只能返回默认证书;
- 若后端使用泛域名证书但未覆盖请求域名,或完全依赖 SAN 匹配,则连接直接中断;
- 即使证书验证被跳过(proxy_ssl_verify off),部分严格实现(如某些 CDN 回源策略)仍会拒绝无 SNI 的握手。
核心配置三要素缺一不可
-
启用 SNI 扩展:添加
proxy_ssl_server_name on;,确保 Client Hello 包含 SNI 字段 -
指定 SNI 值内容:用
proxy_ssl_name $host;动态传入客户端原始 Host(推荐),避免硬编码;若需固定值(如统一回源到api.example.com),可写proxy_ssl_name "api.example.com"; -
保持 Host 请求头一致:搭配
proxy_set_header Host $host;,防止后端路由或日志逻辑错乱
CDN 回源等特殊场景的适配要点
当 Nginx 作为源站被 CDN 回源调用时,常见陷阱是 CDN 自动改写 Host 头:
- 若 CDN 覆盖了原始 Host(例如把
shop-a.com改成origin.example.com),此时$host已失真,应让 CDN 透传原始 Host 到自定义头(如X-Forwarded-Host),再配置proxy_ssl_name $http_x_forwarded_host; - 确认 CDN 回源协议确为 HTTPS ——
proxy_ssl_*系列指令仅在proxy_pass https://...时生效 - 检查上游是否真正支持 SNI:老旧负载均衡器或低版本 Nginx(
验证是否生效的实用方法
最直接的方式是在上游服务器开启 TLS 调试日志:
- 在上游 Nginx 的
error_log中加入debug级别:error_log /var/log/nginx/error.log debug; - 触发一次回源请求后,搜索日志中的
SSL_do_handshake或SSL_get_servername相关行,确认输出的 SNI 值是否为你期望的域名(如shop-a.com) - 也可用
openssl s_client -connect IP:PORT -servername shop-a.com手动模拟验证,对比实际返回的证书 Subject Alternative Name











