Nginx 反向代理 htpps 站点 502 排查思路

一. 背景

前两天在配置 nginx 反向代理 github API 时遇到了 502 的问题,这里做个记录。

二. 故障场景

  • Nginx 配置
    1
    2
    3
    location = /login/oauth/access_token {
    proxy_pass https://github.com;
    }
  • curl 测试结果是 502

三. 排查过程与思路

1. 确认服务器可以正常访问被代理站点

curl -vo /dev/null https://github.com/login/oauth/access_token
测试结果是 404, 可以正常访问被代理接口

2. 检查 Nginx access log 和 error log

  • access log 显示 upstream_status 是 502
  • error log 显示 peer closed connection in SSL handshake while SSL handshaking to upstream
    说明是在 SSL 握手阶段失败了,并且是对端主动关闭了连接。

Tips: access log 中 upstream_status 502 并不一定是 upstream 返回的,需要参考 upstream_bytes_sent 做判断

3. 抓包分析具体原因

①. 可以看到 github 服务器收到 SSL Client Hello 包后主动关闭了连接
这里推断大概率是 Nginx 发送的 Client Hello 包不满足 github 服务器的要求

②. 抓取正常请求的包和异常数据包进行对比
正常请求 ssl client hello 包:
正常请求 ssl client hello 包
异常请求 ssl client hello 包:
异常请求 ssl client hello 包

可以看到异常 ssl client hello 数据包少了 “Extension: server_name”,我判断大概率是这个原因导致的,修改 nginx 配置进行验证。

4. 修改配置并验证

  • 修改后配置:
    1
    2
    3
    4
    5
    6
    7
    location = /login/oauth/access_token {
    proxy_set_header Connection "";
    proxy_http_version 1.1;
    proxy_ssl_server_name on;
    proxy_ssl_protocols TLSv1.1 TLSv1.2;
    proxy_pass https://github.com;
    }
  • 测试可以正常访问
  • 补充:这里主要是 proxy_ssl_server_name on; 这行配置起了作用,其他算是配置优化。

参考文档:

TLS SNI