You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Nginx作为反向代理调用API时出现502 Bad Gateway错误

问题:Nginx反向代理SSL握手失败返回502,但Golang客户端直接调用正常

我尝试用Nginx做反向代理对接外部REST GET API,用来调试Golang服务和外部服务之间的延迟问题。Golang通过net/http库直接调用目标公开URL能正常获取响应,但走Nginx反向代理时却返回502 Bad Gateway。Nginx错误日志显示SSL握手失败(错误码SSL: error:0A000438),但我搞不懂为什么Golang客户端调用没问题。另外已经通过/ping-nginx接口验证Nginx本身运行正常,相关代码、测试响应及日志如下:


相关代码与输出

1. Golang服务代码(ping.go)

package main

import (
    "fmt"
    "log"
    "net/http"
    "strconv"
)

func main() {
    http.HandleFunc("/ping-via-go-client", func(w http.ResponseWriter, r *http.Request) {
        url := "https://flights-explorer.makemytrip.com/ping"
        resp, err := http.Get(url)
        var statusCode string
        if err == nil {
            statusCode = strconv.Itoa(resp.StatusCode)
        }
        fmt.Fprintf(w, "pong-via-go-client with statusCode:"+statusCode)
    })

    http.HandleFunc("/ping-via-nginx", func(w http.ResponseWriter, r *http.Request) {
        url := "http://localhost/ping"
        resp, err := http.Get(url)
        var statusCode string
        if err == nil {
            statusCode = strconv.Itoa(resp.StatusCode)
        }
        fmt.Fprintf(w, "pong-via-nginx with statusCode:"+statusCode)
    })

    log.Fatal(http.ListenAndServe(":3003", nil))
}

2. curl测试响应

➜  ~ curl http://localhost:3003/ping-via-go-client
pong-via-go-client with statusCode:200%
➜  ~ curl http://localhost:3003/ping-via-nginx
pong-via-nginx with statusCode:502%

3. Nginx配置(nginx.conf)

#user  nginx;
daemon off;

worker_processes  auto;

error_log  /opt/logs/nginx-error.log warn;
pid        /var/run/nginx.pid;
events {
    worker_connections  250;
}
http {
log_format upstream_time '$time_local $status $remote_addr to:- $upstream_addr $request '
    'uct:$upstream_connect_time uht:$upstream_header_time urt:$upstream_response_time '
    'request_time:$request_time tid_header:$http_tid status:$upstream_cache_status '
    'slot:$http_slot slot_time:$http_slotstarttime ttl_req:$http_ttl ttl_resp:$upstream_http_x_accel_expires '
    'job_flag:$http_jobflag cookies:"$http_cookie" bytes_sent:$bytes_sent gzip_ratio:$gzip_ratio '
    '"$http_referer" "$http_user_agent" $http_x_forwarded_for cur_time:$msec';
        keepalive_timeout 85;
        upstream flights-explorer.makemytrip.com {
              server flights-explorer.makemytrip.com:443;
              keepalive 30;
        }
    server {
        listen 80;
        access_log /opt/logs/nginx-access.log upstream_time;
                  location = /basic_status {
                            stub_status;
                  }

        location /ping-nginx {
            return 200 'pong-nginx\n';
            add_header Content-Type text/plain;
        }

        location /ping {
               # proxy_buffering off;
             proxy_pass https://flights-explorer.makemytrip.com$request_uri;
             proxy_http_version 1.1;
             proxy_set_header Connection "";
             proxy_ssl_verify off;  # Disable SSL certificate verification
             proxy_ssl_verify_depth 0;
             #proxy_ssl_session_reuse on;
             #proxy_socket_keepalive on;
             proxy_connect_timeout 10s;
             proxy_read_timeout 10s;
        }

    }
}

4. Nginx错误日志(nginx-error.log)

2024/03/03 11:07:55 [error] 20078#0: *6 SSL_do_handshake() failed (SSL: error:0A000438:SSL routines::tlsv1 alert internal error:SSL alert number 80) while SSL handshaking to upstream, client: 127.0.0.1, server: , request: "GET /ping HTTP/1.1", upstream: "https://23.63.110.25:443/ping", host: "localhost"
2024/03/03 11:07:55 [warn] 20078#0: *6 upstream server temporarily disabled while SSL handshaking to upstream, client: 127.0.0.1, server: , request: "GET /ping HTTP/1.1", upstream: "https://23.63.110.25:443/ping", host: "localhost"
2024/03/03 11:07:55 [error] 20078#0: *6 SSL_do_handshake() failed (SSL: error:0A000438:SSL routines::tlsv1 alert internal error:SSL alert number 80) while SSL handshaking to upstream, client: 127.0.0.1, server: , request: "GET /ping HTTP/1.1", upstream: "https://23.63.110.67:443/ping", host: "localhost"
2024/03/03 11:07:55 [warn] 20078#0: *6 upstream server temporarily disabled while SSL handshaking to upstream, client: 127.0.0.1, server: , request: "GET /ping HTTP/1.1", upstream: "https://23.63.110.67:443/ping", host: "localhost"
2024/03/03 11:07:56 [error] 20078#0: *6 SSL_do_handshake() failed (SSL: error:0A000438:SSL routines::tlsv1 alert internal error:SSL alert number 80) while SSL handshaking to upstream, client: 127.0.0.1, server: , request: "GET /ping HTTP/1.1", upstream: "https://23.63.110.74:443/ping", host: "localhost"
2024/03/03 11:07:56 [warn] 20078#0: *6 upstream server temporarily disabled while SSL handshaking to upstream, client: 127.0.0.1, server: , request: "GET /ping HTTP/1.1", upstream: "https://23.63.110.74:443/ping", host: "localhost"

5. Nginx访问日志(nginx-access.log)

03/Mar/2024:11:07:56 +0530 502 127.0.0.1 to:- 23.63.110.25:443, 23.63.110.67:443, 23.63.110.74:443 GET /ping HTTP/1.1 uct:-, -, - uht:-, -, - urt:0.131, 0.116, 0.107 request_time:0.354 tid_header:- status:- slot:- slot_time:- ttl_req:- ttl_resp:- job_flag:- cookies:"-" bytes_sent:314 gzip_ratio:- "-" "Go-http-client/1.1" - cur_time:1709444276.083

问题分析与解决方法

核心原因

目标服务器flights-explorer.makemytrip.com对SSL握手的**SNI(服务器名称指示)**有严格要求:Golang的net/http客户端默认会自动发送SNI信息,而你的Nginx配置中未启用SNI传递,导致握手时没有告知目标服务器要访问的域名,触发了SSL内部错误(alert 80)。

验证方式

用openssl测试不带SNI的握手,会出现相同错误:

openssl s_client -connect flights-explorer.makemytrip.com:443 -servername ""

带SNI的请求则会成功:

openssl s_client -connect flights-explorer.makemytrip.com:443 -servername flights-explorer.makemytrip.com

修复方案

在Nginx的/ping location中添加proxy_ssl_server_name on;,确保SSL握手时传递正确的SNI:

location /ping {
       proxy_pass https://flights-explorer.makemytrip.com$request_uri;
       proxy_http_version 1.1;
       proxy_set_header Connection "";
       proxy_ssl_verify off;
       proxy_ssl_verify_depth 0;
       proxy_ssl_server_name on;  # 启用SNI传递
       proxy_connect_timeout 10s;
       proxy_read_timeout 10s;
}

另外,你定义的upstream块当前未被使用,可改为通过upstream转发,配置更规范:

upstream flights_upstream {
      server flights-explorer.makemytrip.com:443;
      keepalive 30;
}

location /ping {
       proxy_pass https://flights_upstream$request_uri;
       proxy_http_version 1.1;
       proxy_set_header Connection "";
       proxy_ssl_verify off;
       proxy_ssl_verify_depth 0;
       proxy_ssl_server_name on;
       proxy_connect_timeout 10s;
       proxy_read_timeout 10s;
}

内容的提问来源于stack exchange,提问作者Sharath BJ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 14:39:49