Nginx 不执行 WebSocket 协议转换,仅透传 HTTP 升级请求并维持长连接;需强制 proxy_http_version 1.1、动态透传 Upgrade 和 Connection 头、设置 X-Forwarded-Proto 保持 wss/ws 一致性,并确保路径与 Host 精准匹配。

Nginx 本身不执行 WebSocket 协议转换——它不会把 HTTP 请求“变成” WebSocket 帧,也不会在 ws/wss、HTTP/1.1/HTTP/2 之间做协议层面的翻译或升级。所谓“协议转换”,实际是确保客户端发起的 HTTP → WebSocket 升级流程不被拦截、不被降级、完整透传到后端。
关键在于:Nginx 只做透传与协调,不是转换器。
必须强制使用 HTTP/1.1 与后端通信
WebSocket 握手(101 Switching Protocols)是 HTTP/1.1 特有机制,HTTP/2 已移除 Upgrade 和 Connection: upgrade 语义。
- 必须写死:
proxy_http_version 1.1; - 禁止写
proxy_http_version 2.0,哪怕前端走的是 HTTPS+HTTP/2 - 若主 server 启用了
http2,建议为 WebSocket 流量单独配置子域名(如ws.example.com),其 server 块中不加http2
升级头必须原样、动态透传
Nginx 默认丢弃逐跳头(hop-by-hop headers),而 Upgrade 和 Connection 正是这类头。需显式放行:
-
proxy_set_header Upgrade $http_upgrade;
—— 客户端没带Upgrade头时,变量为空,不发送该头,安全 -
proxy_set_header Connection $connection_upgrade;
——$connection_upgrade是 Nginx 内置变量(1.3.10+),自动判断:有升级请求则设为"upgrade",否则设为"close"
⚠️ 切勿写死Connection "upgrade",否则普通 HTTP 请求也会被误升级,导致 400 错误
wss → ws 的“协议转换”本质是 SSL 终止 + 头部透传
当用户访问 wss://example.com/ws:
- Nginx 终止 TLS,收到的是标准 HTTPS 请求(
$scheme = https) - 它以明文
ws://方式proxy_pass到后端(如http://127.0.0.1:8080/ws) - 同时必须添加:
proxy_set_header X-Forwarded-Proto $scheme;
—— 后端据此知道原始是 wss,用于 Origin 校验、重定向生成、CORS 策略等 - 不需要后端再处理 TLS,也不应让后端监听
https://
路径与 Host 必须精准匹配,避免握手发错地方
-
location /ws/ { ... }要和前端连接路径一致(如wss://a.com/ws/chat) -
proxy_pass http://backend/ws/;末尾带斜杠,可避免 Nginx 自动重写路径出错 -
proxy_set_header Host $host;透传原始 Host,防止后端因 Host 不匹配拒绝连接
不复杂但容易忽略











