核心是让Nginx在TLS握手时将客户端真实域名作为SNI发送给后端,需启用proxy_ssl_server_name on并动态设proxy_ssl_name $host;,CDN场景改用$http_x_forwarded_host,再通过debug日志或openssl验证SNI值是否准确。

要解决 Nginx 反向代理 HTTPS 后端时出现的证书名称不匹配(Host Mismatch)报错,核心不是改前端证书,而是让 Nginx 在 TLS 握手阶段准确告诉后端“用户想访问哪个域名”——这依赖 SNI(Server Name Indication)正确传递。常见错误日志如 SSL_do_handshake() failed、certificate verify failed 或 502 Bad Gateway,往往就源于 SNI 缺失或传错值。
启用 proxy_ssl_server_name 并动态设置 SNI 值
Nginx 默认不发送 SNI,必须显式开启,并确保 SNI 内容与客户端原始请求一致:
- 在
location块中添加proxy_ssl_server_name on; - 配合
proxy_ssl_name $host;(推荐),让 SNI 域名随请求 Host 头自动变化 - 避免写死为静态字符串(如
proxy_ssl_name "api.example.com";),除非所有请求都指向同一后端域名 - 该配置仅对
proxy_pass https://...生效,HTTP 回源无需此设置
处理 CDN 或代理覆盖 Host 头的情况
当请求经过 Cloudflare、阿里云全站加速等 CDN 时,CDN 常会重写 Host 头为源站域名,导致 $host 不再是用户原始域名,SNI 也随之错配:
- 在 CDN 控制台开启“透传原始 Host”功能(通常体现为传递
X-Forwarded-Host或X-Real-Host) - Nginx 中改用
proxy_ssl_name $http_x_forwarded_host; - 同时建议添加
proxy_set_header X-Forwarded-Host $host;,便于后端识别真实意图
验证 SNI 是否真正发出
配置写对 ≠ 实际生效。需从上游服务端确认收到的 SNI 值是否准确:
- 在后端 HTTPS 服务器(如另一台 Nginx)开启 debug 日志:
error_log /var/log/nginx/error.log debug; - 触发一次请求后,搜索日志中
client sent server name字样,核对输出的域名是否为你期望的原始 Host - 快速验证:用 OpenSSL 模拟握手:
openssl s_client -connect 10.0.0.5:443 -servername your-domain.com,观察返回证书是否匹配该域名
配套证书校验与安全加固
仅传对 SNI 还不够,还需确保证书链可信、验证机制健全:
- 开启证书验证:
proxy_ssl_verify on;(生产环境必须开启) - 指定可信 CA 根证书路径:
proxy_ssl_trusted_certificate /etc/nginx/certs/ca.crt; - 若后端使用自签名或私有 CA 签发证书,需将对应根证书加入该文件并确保格式 PEM、权限可读
- 避免忽略验证(如设
proxy_ssl_verify off),否则失去 HTTPS 安全意义


















