根本原因是SNI未发送或与Host头不一致,须启用proxy_ssl_server_name on并设proxy_ssl_name $host;透传真实租户域名,同时proxy_set_header Host $host;保持TLS层与HTTP层标识一致。

必须启用 SNI 并指定动态域名值
默认情况下,Nginx 与 HTTPS 后端建连时不发送 SNI 字段,即使 `proxy_pass` 指向的是 HTTPS 地址。后端若托管多个租户域名(如 tenant-a.app.com、tenant-b.app.com),就无法选出对应证书。
- 在 location 块中添加
proxy_ssl_server_name on;—— 这是开启 TLS Client Hello 中 SNI 扩展的开关 - 紧接着配置
proxy_ssl_name $host;—— $host 是标准化后的请求 Host(小写、去端口),比$http_host更可靠 - 避免写死,例如
proxy_ssl_name "api.app.com";,除非所有流量都固定指向同一租户
确保 Host 请求头与 SNI 保持一致
SNI 是 TLS 层标识,Host 是 HTTP 层标识。两者不匹配时,部分 SaaS 后端会在 TLS 成功后二次校验 Host,导致租户路由错误或 404/403。
安全更新和维护 CLI Proxy API(CPA)部署与配置。用于 CPA 镜像升级、配置变更、认证目录兼容修复、上线验证与回滚。适用于用户提到“CPA 更新/升级/配置改了/容器重建/回滚”等场景。
- 加上
proxy_set_header Host $host;,不要用$http_host(可能含端口) - 若上游依赖原始客户端 IP,一并透传:
proxy_set_header X-Real-IP $remote_addr;和proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
应对 CDN 或网关覆盖 Host 头的情况
阿里云全站加速、Cloudflare 等 CDN 回源时,常将 Host 改为源站配置名(如 origin.prod.app.com),导致 $host 失真,SNI 错配。
- 在 CDN 控制台开启“透传原始 Host”,通常会自动注入 X-Forwarded-Host 请求头
- Nginx 中改用
proxy_ssl_name $http_x_forwarded_host; - 同时加一句
proxy_set_header X-Forwarded-Host $host;,方便下游服务识别租户上下文
验证配置是否真正生效
配置写对 ≠ 运行时生效。需确认 TLS 握手阶段实际发出的 SNI 值是否匹配预期。
- 在上游 SaaS 网关或后端 Nginx 上开启 debug 日志:
error_log /var/log/nginx/error.log debug;,搜索日志中的 client sent server name - 用 OpenSSL 手动测试:
openssl s_client -connect 10.0.0.100:443 -servername tenant-a.app.com,观察返回证书的 CN 或 SAN 是否匹配 - 检查 OpenSSL 版本:
nginx -V | grep OpenSSL,确保 ≥ 1.0.2h 且编译时启用了 enable-tlsext

















