多级 Nginx 代理 WebSocket 的核心是每层必须完整透传 Upgrade 和 Connection 头:需统一配置 proxy_http_version 1.1、proxy_set_header Upgrade $http_upgrade、proxy_set_header Connection "upgrade"、proxy_read_timeout 86400,并确保 X-Forwarded-Proto 传递及路径重写准确。

多级 Nginx 代理 WebSocket 时,核心问题不是“能不能转”,而是每层是否都完整透传协议升级信号。只要任意一层漏掉 Upgrade 或 Connection 头,连接就会在握手阶段失败(常见 400 错误),且日志往往不报错,排查困难。
每层都必须显式配置协议升级头
WebSocket 握手依赖 HTTP/1.1 的 Upgrade 流程,而默认情况下 Nginx 不会透传 Upgrade 和 Connection 头。每一级代理都得独立写全以下四条指令:
- proxy_http_version 1.1:不能省略,也不能设为 1.0;这是 Upgrade 机制的前提
- proxy_set_header Upgrade $http_upgrade:用变量,不是写死 "websocket",否则无法兼容 MQTT、STOMP 等其他升级协议
- proxy_set_header Connection "upgrade":固定字符串 upgrade,别用 $connection_upgrade(除非你额外配了 map 块)
- proxy_read_timeout 86400:防止某层默认 60 秒超时主动断连,尤其影响空闲聊天或监控场景
避免 Connection 头被覆盖或清空
常见错误是某层代理没设 Connection 头,或写了 proxy_set_header Connection "" 这类清空操作——这会让后端收到 Connection: close,直接拒绝升级。更稳妥的做法是:
- 所有代理层统一写
proxy_set_header Connection "upgrade" - 如果要用
$connection_upgrade变量,必须在 http 块里提前定义 map:
default upgrade;
'' close;
}
否则变量为空时,Connection 头变成空值,等效于 close。
路径重写与 proxy_pass 斜杠要严格匹配
多级转发中路径处理容易出错,导致后端收到错误 URI。关键看 proxy_pass 末尾有没有 /:
- 前端请求
wss://a.com/api/ws→ 第一层 location /api/ws { proxy_pass http://b.com/; } → 后端收到/ws - 前端请求
wss://a.com/ws→ 第一层 location /ws { proxy_pass http://b.com; } → 后端收到/ws - 若 proxy_pass 尾部多一个 /,又没对应 location 路径,可能触发 404 或重定向循环
HTTPS(wss)穿透需传递协议标识
如果最外层是 HTTPS,中间还有 Nginx 层,后端需要知道原始是 wss 而非 ws,否则可能生成错误的跳转链接或鉴权失败:
- 每层都加
proxy_set_header X-Forwarded-Proto $scheme - 最外层 SSL 配置必须就绪(listen 443 ssl、证书路径正确)
- wss 流量在首层解密后转为 ws 向内传递,内部各层无需再处理 TLS


















