起因是cgt用的自签名证书导致api访问会因为证书不安全导致资源加载失败,申请了企业的域名,由于企业的域名只能在机房电脑上,所以需要加一层lb,为了防止部署后影响制作,先用自己的域名
生产力工具上场,一下为gpt-5-chat的沟通
提出需求
server {
listen 60288 ssl;
listen [::]:60288 ssl;
server_name cgt.tdxinglian.com;
ssl_certificate /media/nas/docker_images/acme/data/certd/ssl/cert.crt;
ssl_certificate_key /media/nas/docker_images/acme/data/certd/ssl/cert.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 60s;
proxy_send_timeout 120s;
proxy_read_timeout 120s;
proxy_pass http://180.184.58.112:8181;
}
}
这是docker中的nginx配置, 其中的80端口映射到的宿主机的8181端口,8686映射到宿主机的8686端口, 现在我需要在另一台电脑上做一个nginx的转发,cgt.tdxinglian.com会解析到这台新的电脑的ip, 宿主机的ip是180.184.58.112, 60288, 60289 分别对应宿主机的8181, 8686,60288跟60289都是https端口 8181是纯http端口, 8686是wss端口 ssl_certificate /media/nas/docker_images/acme/data/certd/ssl/cert.crt; ssl_certificate_key /media/nas/docker_images/acme/data/certd/ssl/cert.key; 证书路径是这个,写一个完整的nginx.conf文件给我
给出答案
ssl_protocols TLSv1.2 TLSv1.3; 禁用低强度加密套件, 这句与server语句同一层级
# 启用websocket (wss端口)
proxy_http_version 1.1; # wss端口版本必须是1.1
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
访问测试 直接ip访问正常,域名访问返回502,贴上报错信息
upstream prematurely closed connection while reading response header from upstream
日常抽搐
还是会出现回复死循环,这种时候最好清空上下文,整理有用信息,重新开启回话
中间gpt多次纠结反代机器与cgt之间的网络是否能连接,清除上下文,将 curl -v -follow访问ip与域名的log放在一次会话中告诉gpt
为什么反代会 502 而 curl 正常
原因可能是:
- 302 重定向 + Host 头
上游返回的是相对路径index.php?...,Nginx 会转发这个响应给客户端。
如果客户端是TTPS(60288端口)而上游是 HTTP,某些情况下浏览器会尝试直接访问上游返回的绝对/相对地址,却走错协议或端口,从而显示错误。
Nginx 在默认配置下不会出错,但如果 upstream 关闭连接太快(302时没有返回完整的Body等),也可能导致upstream prematurely closed connection→ 502。 - 解决方案方向
既然 curl 发正常结果,那让 Nginx 按 curl的行为来适配上游返回即可。proxy_http_version 1.0;# 避免 chunked 响应问题proxy_set_header Connection close;# 立即关闭,防止长连接问题
另外如果上游返回的 Location 是相对路径,浏览器没问题。但如果是绝对路径并带协议,可能需要:
proxy_redirect off; 或者 proxy_redirect http://$proxy_host https://$host:$server_port;
这样反代会把上游的重定向改成前端的 HTTPS 地址,不会跳错。
根据回答修改,并再次使用curl -vk进行测试
可能的原因
上游返回信息
HTTP/1.1 302 Found
Location: index.php?controller=v_login&method=show_page
Set-Cookie: ws_port=8686
这是一个相对路径的重定向。
Nginx 在反代这种响应时:
- 如果使用 HTTP/1.1 且启用了
Connection: keep-alive,上游可能会在发送响应头后立刻断开连接,Nginx 就认为响应未完成,从而直接 502。 - 如果上游是 PHP-FPM/nginx 组合,某些 chunked/no-body 响应在反代时会触发这种错误。
proxy_set_header Connection ""或keep-alive对这种老式短连接响应不友好,需要改为关闭连接。- 我怀疑上游是 PHP 或某个应用网关,它对
Host非常敏感,你现在反代发的是:Host: cgt.tdxinglian.com:60288
而直接curl http://180.184.58.112:8181发的是:Host: 180.184.58.112:8181
这种差异在某些应用会导致直接退出连接。
解决方法
我们在反代时可以强制:
- 使用 HTTP/1.0 转发(避免 chunked 传输和 keep-alive 对这种场景的影响)。
- 强制关闭连接。
- 禁用自动修改重定向头(防止 proxy_redirect 把相对路径改出问题)。
- 反代改成
proxy_set_header Host 180.184.58.112;
修改后的 nginx.conf 示例(针对 60288 端口的 HTTP 反代):
为什么这样能解决
- HTTP/1.0 + Connection close
每个请求/响应独立,不依赖持久连接,避免“上游提前关闭连接”导致 Nginx 报 502。 - proxy_redirect off
避免 Nginx 强制把 HTTP 重定向改成 HTTPS,保持上游返回的相对路径。 - 3、4步的修改可以模拟直连时的请求头,使反代更接近你直接
curl上游的行为,而你直接 curl 是正常的。