nginx代理websocket返回400错误的本质是未正确透传upgrade和connection头部,导致后端无法识别协议升级请求;必须配置proxy_http_version 1.1、proxy_set_header upgrade $http_upgrade、proxy_set_header connection "upgrade"三要素,并排查日志、请求头完整性及cdn/waf拦截。

WebSocket 握手返回 400 错误,通常不是后端服务本身的问题,而是 Nginx 在代理过程中未正确透传关键请求头或协议升级字段导致的。核心在于确认 Nginx 是否真正完成了 WebSocket 协议升级(Upgrade)的透传。
检查 Nginx 是否启用了 WebSocket 必需的代理配置
Nginx 默认不支持 WebSocket 代理,必须显式设置以下三项头信息和连接行为:
- proxy_http_version 1.1:WebSocket 升级依赖 HTTP/1.1,不能用默认的 1.0
-
proxy_set_header Upgrade $http_upgrade:将客户端发来的
Upgrade: websocket头原样转发 - proxy_set_header Connection "upgrade":告诉 Nginx 允许升级连接(注意双引号不可省略)
典型配置示例:
proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://backend;
确认客户端发起的 Upgrade 请求头是否完整
浏览器或客户端必须发送符合规范的 WebSocket 握手请求,Nginx 才能识别并透传。关键字段包括:
-
Connection: Upgrade(大小写不敏感,但值必须是
Upgrade) -
Upgrade: websocket(小写
websocket,不是WebSocket或其他变体) - Sec-WebSocket-Key 和 Sec-WebSocket-Version:由客户端自动生成,Nginx 不修改,但缺失会导致 400
可用 curl 模拟验证:
排查 Nginx 日志中的具体拒绝原因
开启 Nginx 的 error_log 并设为 info 级别,可捕获握手阶段的细节:
- 如果日志出现
client sent invalid "Upgrade" header,说明客户端 Upgrade 值非法(如空格、大小写错误、拼写错误) - 若出现
client sent invalid "Connection" header,多因 Connection 值不是Upgrade或含多余字段(如keep-alive, Upgrade) - 没有相关日志?可能是请求根本没到 Nginx(DNS、防火墙、TLS 握手失败等前置问题)
临时在 server 块中加一行:error_log /var/log/nginx/websocket.log info;,然后复现问题查看。
验证后端服务是否收到正确的 Upgrade 请求
在后端(如 Node.js、Spring Boot)加日志,打印原始请求头,重点确认:
-
Upgrade头是否为websocket -
Connection头是否包含Upgrade(允许同时有keep-alive,但 Nginx 配置中应设为"upgrade"以覆盖) -
Host和Origin是否合法(部分后端会校验 Origin,不匹配也返回 400)
若后端收不到 Upgrade 头,问题一定出在 Nginx 配置或其上游(如 CDN、WAF)拦截了升级头。











