WebSocket 升级失败——101 切换协议、代理和 TLS 问题
如何通过数据包捕获来解决 WebSocket 升级失败问题,包括 HTTP 101、升级标头、连接标头、代理剥离、TLS、重置和空闲超时。
WebSocket 故障通常隐藏在通用浏览器或应用程序消息后面:“WebSocket 连接失败”、“意外响应代码”、“在收到握手响应之前连接已关闭”、“101 切换协议丢失”或“套接字已断开连接”。当 HTTP 似乎工作但实时流量不起作用时,用户搜索“WebSocket 升级失败 pcap”、“未返回 101 切换协议”、“nginx websocket 代理标头”和“WebSocket 连接重置”。
数据包捕获可以显示是否发送了 HTTP 升级请求、服务器是否返回“101 Switching Protocols”、代理是否删除了所需的标头、TLS 是否成功以及升级后连接是否断开。
PCAP 手术很有用,因为 WebSocket 跟踪通常需要保留 HTTP 握手和升级后 TCP 时间线。
健康的 WebSocket 升级是什么样子的
客户端发送带有升级标头的 HTTP 请求:
GET /socket HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: ...
Sec-WebSocket-Version: 13
The server replies:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: ...
之后,连接就不再是普通的HTTP请求/响应流量。它携带 WebSocket 帧。
常见升级失败
常见原因包括:
- 代理删除“Upgrade”标头。
- 代理删除或重写“连接:升级”。
- 后端路由不支持WebSocket。
- TLS 终止将请求发送到错误的上游。
- HTTP/2 到 HTTP/1.1 的升级行为配置错误。
- 发生身份验证重定向,而不是 101。
- 后端返回 400、403、404、426、502 或 504。
- 升级后连接重置。
- 空闲超时关闭安静的 WebSocket。
状态代码和标头很重要。
代理标头问题
反向代理必须正确转发 WebSocket 升级标头。如果后端从未看到“Upgrade: websocket”,它可能会将请求视为普通 HTTP。
数据包证据:
- 客户端到代理的请求包含升级标头。
- 代理到后端的请求缺少它们。
- 后端返回正常的 HTTP 响应而不是 101。
这是代理配置问题,而不是 WebSocket 客户端错误。
TLS 和 SNI
对于安全的 WebSocket (wss://),TLS 在 HTTP 升级之前发生。如果 TLS 失败,WebSocket 握手将永远不会开始。保留 DNS、TCP、TLS ClientHello、SNI 和任何 TLS 警报或重置。
在验证 TLS 路径之前,不要诊断升级标头。
101 后连接断开
有时升级成功,然后连接关闭。那是另一种失败。
寻找:
- FIN 或 RST 发送方。
- 空闲超时时间。
- WebSocket ping/pong 活动。
- 代理读取超时。
- TCP 重传。
- 零窗口。
- 后端进程重新启动。
如果丢弃以固定间隔发生,则可能会出现超时策略。
Checklist
使用此工作流程:
- 保留 DNS 和 TCP 连接。
- 验证“wss://”的 TLS 握手。
- 检查客户端升级请求标头。
- 检查服务器响应状态。
- 如果需要,请确认“101 切换协议”。
- 比较客户端到代理和代理到后端的请求。
- 查找重定向或身份验证响应。
- 如果升级成功,请检查升级后的 FIN/RST/超时。
- 保留 WebSocket ping/pong 计时(如果可见)。
- 仅在保持完全握手后才进行修剪。
最终诊断
WebSocket 升级失败通常是 HTTP 握手或代理转发问题,直到“101 切换协议”得到证实。升级后,故障会变成长期存在的 TCP 超时、重置或应用程序协议问题。
PCAP 手术有助于保留这两个阶段,因此可以将模糊的 WebSocket 错误追溯到标头、代理行为、TLS、后端响应或连接生命周期。