如何测试通过代理建立的 WebSocket 连接

浏览器流量经过代理中继连接互联网服务,并交换双向 WebSocket 心跳信号

普通 HTTP 探测成功,不代表 WebSocket 工作流可靠。连接可能完成升级,却在后续因代理关闭空闲隧道、重连时出口改变、Worker 未发送心跳、DNS 在错误位置解析,或客户端绕过代理直连而失败。

对于已获授权的聊天、遥测、浏览器自动化、实时价格与应用质量验证,应把 WebSocket 当作完整生命周期测试,而不是只检查一个状态码。有效结果必须证明升级握手、双向流量、连接存活、受控关闭和可预测恢复。

定义唯一测试身份

发送流量前,为每次运行分配非敏感测试编号,并记录:

  • 浏览器或客户端版本;
  • 代理协议与网关标签;
  • 请求地区与出口批次标签;
  • DNS 执行方:本地、浏览器、网关或 SOCKS 远程 DNS;
  • 地址族;
  • 连接开始与结束时间;
  • 升级状态、关闭码、消息数量和心跳时间;
  • 预期内容标记与最终结论。

不要记录代理密码、Authorization、Cookie、可复用会话令牌或包含个人数据的消息正文。仅使用自己控制或已获授权评估的测试端点。

验证打开握手

标准 WebSocket 先通过 HTTP 请求要求服务器切换协议。应确认:

  1. 请求确实经过配置的代理;
  2. 目标主机、端口和协议符合计划;
  3. 服务器返回有效升级,而不是缓存页、重定向循环、登录页或阻断页;
  4. 必需的子协议协商成功;
  5. 代理没有移除升级所需字段;
  6. 安全 WebSocket 的 TLS 主机名验证仍然正确。

不能因为浏览器显示 socket 已打开就判定通过。使用同一个非敏感测试编号,把客户端时间与代理网关侧记录关联起来。

证明两个方向都能传输

已打开的连接仍可能“半失效”。客户端发送一个小型唯一测试消息,受控服务器必须回显或确认;随后服务器发送独立消息,客户端必须完成内容校验。

记录发送时间、接收时间、方向、字节数和无害消息哈希,原始正文不进入长期日志。先以单并发运行,避免不同连接的消息相互混淆。

若客户端到服务器正常,而服务器到客户端停止,应检查代理缓冲、中间层超时、浏览器或 Worker 生命周期和应用订阅状态。在确定故障边界前不要轮换出口。

测量真实空闲超时

许多代理、负载均衡器和应用网关会关闭安静连接,文档值也可能与实际路径不同。

使用阶梯测试:

  1. 建立并验证连接;
  2. 让应用保持 15 秒静默,再发送探测;
  3. 依次测试 30、60、120 和 300 秒;
  4. 记录第一次探测或确认失败的间隔;
  5. 在同一出口批次重复边界区间。

安全的应用心跳间隔必须短于最低可复现空闲截止值,并为网络抖动和事件循环延迟留出余量。不要为了保持所有隧道而设置过于激进的心跳;在大规模任务中,不必要心跳会放大带宽与负载。

区分协议 Ping/Pong 与应用心跳

部分客户端暴露 WebSocket ping/pong 帧;浏览器 JavaScript 通常依赖应用层消息。测试记录必须标明具体机制。

心跳测试需验证三件事:

  • 心跳确实通过代理离开客户端;
  • pong 或应用确认在截止时间前返回;
  • 确认缺失时,连接会被关闭或隔离,而不是作为僵尸连接留在池中。

延迟使用单调计时器,墙上时钟只用于跨系统关联。系统时间调整不应产生负心跳延迟。

分开测试粘性路由与重连

连接保持打开时路径天然固定,但重连属于新的路由事件。若应用依赖地区、账户状态或上游亲和 Cookie,需要明确重连是复用相同代理会话,还是刻意创建新会话。

运行两种场景:

  • 粘性重连:复用批准的会话标识,验证逻辑地区与应用状态保持一致;
  • 全新重连:新建会话并标注为新样本,验证应用状态可以安全重建。

不要把两者都称为“重试”。它们回答不同问题。重连使用带随机抖动的指数退避;明确拒绝或限流不能触发快速出口轮换。

验证关闭行为

测试客户端正常关闭、服务器正常关闭、策略拒绝、应用重启、网络中断和代理关闭。记录关闭码,以及对端是否收到关闭握手。

正常关闭应释放浏览器、Worker、代理隧道与应用订阅。异常关闭应进入有界恢复流程,重连后不能留下两个活动订阅。

批准的代理不可用时,客户端必须故障关闭,不能回退到设备直连。IPv4 与 IPv6 需要分别测试,因为一个地址族的代理路径失败时,另一个地址族可能仍可直连。

七项发布矩阵

场景单一变量必需证据
基线正常连接有效升级与双向消息
空闲边界逐步增加静默时间可复现截止值与安全心跳余量
心跳缺失抑制确认检测并清除僵尸连接
粘性重连相同代理会话保持预期地区与应用状态
全新重连新代理会话新路径被标注并重建状态
代理丢失网关不可用故障关闭且无直连回退
双栈先 IPv4 后 IPv6每个地址族的路由与 DNS 证据

每项重复足够次数,以区分确定性策略与短暂路由故障。结论只能是通过、失败或无法判定,缺失证据不能算通过。

常见排错

升级成功,但连接总在固定时间关闭

测量实际空闲截止值并与心跳时序比较,分别检查代理、负载均衡器、服务器、浏览器 Worker 和 NAT 的空闲策略。

消息只能单向到达

检查订阅状态、代理缓冲、事件循环健康度,以及中间层是否把连接视为空闲。必须使用两个方向的受控消息。

重连后到达错误地区

检查代理会话是否复用、DNS 是否换了解析器,以及新出口批次是否符合请求地区。验证响应内容,而不是只看 IP 标签。

不使用代理时正常,通过代理时失败

比较握手请求、TLS 校验、代理鉴权、目标端口策略和升级字段处理。不要用关闭证书验证作为捷径。

发布检查清单

  • 握手与代理侧观察成功关联。
  • 双向消息均通过受控内容验证。
  • 实际空闲超时经过测量,而非假设。
  • 心跳间隔留有余量,确认缺失会清除僵尸连接。
  • 粘性重连与全新重连是独立测试。
  • 重连使用有界退避与随机抖动。
  • 关闭码与资源清理已记录。
  • IPv4 与 IPv6 的代理丢失都保持故障关闭。
  • 日志不含可复用凭据或不必要消息正文。
  • 明确拒绝与限流信号得到尊重。

合规说明

WebSocket 测试不会创造访问权限。仅测试自己控制或已获授权评估的端点和账户。遵守访问控制、应用条款、速率限制、数据最小化要求、隐私义务和明确拒绝信号。不得利用重连或轮换出口规避目标站点决定。

相关 98IP 指南

来源说明:IETF,《The WebSocket Protocol》,RFC 6455;MDN Web Docs,WebSocket API。外部来源 URL 仅保存在内部运营记录中。