关键是要启用 proxy_ssl_server_name on 并动态设置 proxy_ssl_name $host,确保 SNI 发送真实租户域名,同时透传 Host 头与之保持一致,避免证书匹配失败。

要让 Nginx 在回源到多租户 SaaS 平台时正确匹配 HTTPS 证书,关键不是只打开 proxy_ssl_server_name,而是让它把用户真实请求的域名作为 SNI 值发给后端——否则同一 IP 上多个租户域名共用证书时,TLS 握手必然失败。
必须启用 SNI 并绑定动态域名
Nginx 默认不发送 SNI 扩展,所以第一步是显式开启:
- 在
location或upstream引用的作用域内添加proxy_ssl_server_name on; - 该指令仅对
proxy_pass https://...生效,HTTP 回源下无效 - 若使用
upstream块定义后端,proxy_ssl_server_name必须写在location中,不能放在upstream内部
proxy_ssl_name 必须用变量,不能写死
SNI 字段内容决定后端选哪张证书。默认它取 proxy_pass 里的地址(如 https://10.0.0.100),这在多租户场景下完全不可用:
- 配置
proxy_ssl_name $host;——推荐用$host,它已标准化为小写、不含端口,比$http_host更可靠 - 绝对避免写成
proxy_ssl_name "tenant-a.example.com";,除非所有流量都指向唯一租户域名 - 如果后端需识别原始请求域名(比如租户子域名
shop-a.example.com),而 CDN 改写了 Host 头,就得让 CDN 透传X-Forwarded-Host,然后改用proxy_ssl_name $http_x_forwarded_host;
配合 Host 头与租户识别保持一致
光传对 SNI 还不够,上游服务通常也依赖 Host 头做租户路由:
- 加上
proxy_set_header Host $host;,确保后端收到的 Host 与 SNI 值一致 - 若租户通过二级域名识别(如
aaa.example.com),可在 server 块中用正则捕获:server_name ~^(?,再透传.+)\.example\.com$; proxy_set_header X-Tenant-ID $tenant; - 建议同步加
proxy_set_header X-Forwarded-Host $host;,方便下游服务还原原始请求意图
验证 SNI 是否真正发出
配置写对不等于生效,必须确认 Nginx 实际发出的 SNI 值:
- 在上游服务(如另一台 Nginx 或测试用的 OpenSSL 服务器)开启 debug 日志:
error_log /var/log/nginx/error.log debug; - 发起一次请求后,搜索日志中的
client sent server name或SSL_do_handshake行 - 确认输出的域名是
shop-a.example.com这类实际租户域名,而不是backend.internal或空值











