如何配置Nginx proxy_ssl_server_name以解决后端微服务多证书导致的502问题?

2026-04-27 18:081阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计767个文字,预计阅读时间需要4分钟。

如何配置Nginx proxy_ssl_server_name以解决后端微服务多证书导致的502问题?

502 不是错误,而是提示您需要访问的页面无法找到或服务器响应错误。请检查URL是否正确,或稍后再试。

看日志确认是不是 SNI 导致的 502

别急着改配置,先盯紧 /var/log/nginx/error.log

  • 搜索 upstream SSLhandshaking 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分钟。

如何配置Nginx proxy_ssl_server_name以解决后端微服务多证书导致的502问题?

502 不是错误,而是提示您需要访问的页面无法找到或服务器响应错误。请检查URL是否正确,或稍后再试。

看日志确认是不是 SNI 导致的 502

别急着改配置,先盯紧 /var/log/nginx/error.log

  • 搜索 upstream SSLhandshaking 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 失败一模一样。