如何配置Nginx proxy_ssl_server_name以解决后端微服务多证书导致的502问题?
- 内容介绍
- 文章标签
- 相关推荐
本文共计767个文字,预计阅读时间需要4分钟。
502 不是错误,而是提示您需要访问的页面无法找到或服务器响应错误。请检查URL是否正确,或稍后再试。
看日志确认是不是 SNI 导致的 502
别急着改配置,先盯紧 /var/log/nginx/error.log:
- 搜索
upstream SSL、handshaking to upstream这类关键词 - 如果报错里带
tlsv1 alert internal error(alert number 80)或certificate verify failed但你没开proxy_ssl_verify,大概率是 SNI 缺失 - 对比:用
curl -v https://your-backend-domain.com能成功,但 Nginx 访问同域名却失败 → 说明问题出在 Nginx 发起连接时的行为差异,不是网络或服务本身
proxy_ssl_server_name on 是开关,但光开它不够
proxy_ssl_server_name on 只是告诉 Nginx “去发 SNI”,但它默认用什么值发?答案是:proxy_pass 指令里的主机名。所以必须确保三者一致:
-
proxy_pass https://api.example.com/→ 域名必须写全,不能写 IP -
proxy_ssl_server_name on;→ 必须显式开启 -
proxy_set_header Host "api.example.com";→ 不能用$host或$http_host,它们可能被客户端污染;Host 头必须和 SNI 值相同,否则某些网关(如 Istio sidecar)会拒绝
漏掉任意一条,都可能握手失败或返回 404/403。
用了 upstream 块?proxy_ssl_name 必须加引号手动指定
upstream 里写的是 server api.example.com:443;,Nginx 解析后只拿到 IP,SNI 信息就丢了。这时 proxy_ssl_server_name on 不起作用,必须补上:
-
proxy_ssl_name "api.example.com";→ 值必须是字符串字面量,带双引号 - 这个值要和后端证书的 CN 或 SAN 完全匹配,大小写敏感
- 如果后端是泛域名证书(
*.internal.com),这里就得填svc.internal.com这样的具体子域,不能填internal.com
常见错误:写成 proxy_ssl_name $host; —— 变量在 SSL 握手阶段不可用,Nginx 启动时就会报错。
证书验证开着?记得配好 trusted_certificate
如果开了 proxy_ssl_verify on; 却没指定 CA 链,也会 502,错误提示容易和 SNI 混淆:
-
proxy_ssl_trusted_certificate /etc/nginx/certs/ca-bundle.crt;→ 必须是 PEM 格式,包含根 + 中间证书 - 自签名证书场景下,可临时关掉验证(
proxy_ssl_verify off;),但生产环境不建议 - 注意路径权限:Nginx worker 进程必须有读取该文件的权限,否则日志里会报 open() failed
真正难排查的点往往在这里:SNI 配对了,Host 头也对了,但证书链不全,TLS 握手卡在验证环节,日志看起来和 SNI 失败一模一样。
本文共计767个文字,预计阅读时间需要4分钟。
502 不是错误,而是提示您需要访问的页面无法找到或服务器响应错误。请检查URL是否正确,或稍后再试。
看日志确认是不是 SNI 导致的 502
别急着改配置,先盯紧 /var/log/nginx/error.log:
- 搜索
upstream SSL、handshaking to upstream这类关键词 - 如果报错里带
tlsv1 alert internal error(alert number 80)或certificate verify failed但你没开proxy_ssl_verify,大概率是 SNI 缺失 - 对比:用
curl -v https://your-backend-domain.com能成功,但 Nginx 访问同域名却失败 → 说明问题出在 Nginx 发起连接时的行为差异,不是网络或服务本身
proxy_ssl_server_name on 是开关,但光开它不够
proxy_ssl_server_name on 只是告诉 Nginx “去发 SNI”,但它默认用什么值发?答案是:proxy_pass 指令里的主机名。所以必须确保三者一致:
-
proxy_pass https://api.example.com/→ 域名必须写全,不能写 IP -
proxy_ssl_server_name on;→ 必须显式开启 -
proxy_set_header Host "api.example.com";→ 不能用$host或$http_host,它们可能被客户端污染;Host 头必须和 SNI 值相同,否则某些网关(如 Istio sidecar)会拒绝
漏掉任意一条,都可能握手失败或返回 404/403。
用了 upstream 块?proxy_ssl_name 必须加引号手动指定
upstream 里写的是 server api.example.com:443;,Nginx 解析后只拿到 IP,SNI 信息就丢了。这时 proxy_ssl_server_name on 不起作用,必须补上:
-
proxy_ssl_name "api.example.com";→ 值必须是字符串字面量,带双引号 - 这个值要和后端证书的 CN 或 SAN 完全匹配,大小写敏感
- 如果后端是泛域名证书(
*.internal.com),这里就得填svc.internal.com这样的具体子域,不能填internal.com
常见错误:写成 proxy_ssl_name $host; —— 变量在 SSL 握手阶段不可用,Nginx 启动时就会报错。
证书验证开着?记得配好 trusted_certificate
如果开了 proxy_ssl_verify on; 却没指定 CA 链,也会 502,错误提示容易和 SNI 混淆:
-
proxy_ssl_trusted_certificate /etc/nginx/certs/ca-bundle.crt;→ 必须是 PEM 格式,包含根 + 中间证书 - 自签名证书场景下,可临时关掉验证(
proxy_ssl_verify off;),但生产环境不建议 - 注意路径权限:Nginx worker 进程必须有读取该文件的权限,否则日志里会报 open() failed
真正难排查的点往往在这里:SNI 配对了,Host 头也对了,但证书链不全,TLS 握手卡在验证环节,日志看起来和 SNI 失败一模一样。

