本质是nginx未正确传递sni导致后端返回错误证书,须启用proxy_ssl_server_name on并动态设proxy_ssl_name $host;(cdn场景改用$http_x_forwarded_host),同时开启proxy_ssl_verify on及指定可信ca路径以确保校验稳。

这个问题本质是 Nginx 与后端 HTTPS 服务建立 TLS 连接时,没把用户真正要访问的域名作为 SNI(Server Name Indication)发过去,导致后端返回了错误的证书,Nginx 校验失败后报错或返回 502。解决关键不是改前端证书,而是让 SNI 值对、传得准、验证稳。
启用并正确设置 SNI
Nginx 默认不发送 SNI,必须显式开启,并确保内容匹配客户端原始请求:
- 在 location 块中添加 proxy_ssl_server_name on;
- 紧跟着配置 proxy_ssl_name $host;(推荐),它会自动取 Host 请求头中的域名(已标准化,不含端口、小写)
- 若用 upstream 或后端是固定 IP,proxy_ssl_name 必须写死为双引号包裹的字符串,例如 proxy_ssl_name "api.example.com";,且该值需与后端证书的 SAN 或 CN 完全一致
- 避免写 proxy_ssl_name $http_host;(可能含端口)或未加引号的变量(Nginx 启动时报错)
处理 CDN 或多层代理导致的 Host 失真
Cloudflare、阿里云全站加速等常重写 Host 头为源站名,使 $host 不再是用户原始域名,SNI 就会错配:
- 在 CDN 控制台开启“透传原始 Host”功能,通常表现为传递 X-Forwarded-Host 头
- Nginx 中改用 proxy_ssl_name $http_x_forwarded_host;
- 同时建议加 proxy_set_header X-Forwarded-Host $host;,方便后端识别真实意图
配套证书验证不能缺位
只传对 SNI 不够,Nginx 还要能验证后端证书是否可信:
- 必须开启校验:proxy_ssl_verify on;(生产环境强制要求)
- 指定可信根证书路径:proxy_ssl_trusted_certificate /etc/nginx/ssl/ca-bundle.crt;
- 该文件需为 PEM 格式,包含完整的信任链(根证书 + 可选中间证书),权限设为 644,所有者为 nginx 运行用户
- 若后端用自签名或私有 CA 证书,必须把对应根证书加入该文件
验证 SNI 是否真正发出
配置 reload 成功 ≠ 实际生效,必须从上游确认:
- 在后端 HTTPS 服务(如另一台 Nginx)开启 debug 日志:error_log /var/log/nginx/error.log debug;
- 触发一次请求后,搜索日志中 client sent server name 字样,核对输出域名是否为你期望的原始 Host
- 快速模拟:在 Nginx 服务器上执行 openssl s_client -connect 后端IP:443 -servername your-domain.com -showcerts,观察返回证书的 Subject 和 SAN 是否匹配











