正向代理不会保留 TCP 分段边界
在检查正向代理两侧的流量时,请把 TCP 分段、套接字读取和 HTTP 帧界定区分开。
假设一个 HTTP 响应经过 Squid 之后,出现在多个抓取到的 TCP 分段中。这可能只是 TCP 的普通行为,而不是响应被错误拆分的证据。
正向代理通常有两条连接:
client ⇄ TCP connection A ⇄ proxy ⇄ TCP connection B ⇄ origin
每条连接都有自己的 TCP 状态、序列号和分包方式。代理可以从一条连接读取数据并写入另一条连接,而不保留原始分段大小。缓冲、发送时机、拥塞以及路径的大小限制都可能产生另一种分组。
值得分开看待的三个边界
| 边界 | 由什么决定 |
|---|---|
| TCP 分段 | 传输与网络路径 |
| 套接字读取结果 | 可用的流字节和调用方的缓冲区 |
| HTTP 消息或帧 | HTTP 协议的帧界定规则 |
一次读取可能包含报头的一部分、完整报头加正文字节,或者跨越一个以上应用层边界的数据。TCP 不会把“HTTP 响应的结束”附着在一次成功读取的末尾。
因此 HTTP/1.1 解析器会累积报头,并应用相应的正文界定规则,包括长度、传输编码或允许的连接关闭。HTTP/2 帧是一种协议结构,它本身也可以跨越 TCP 分段;它不是网络包的另一个名字。
成功的 CONNECT 隧道会保留隧道内的字节流,但仍然使用两段 TCP。即使代理没有改动隧道内的字节,其分段边界也可能不同。
调查数据损坏时,应比较重新组装后的应用数据。比较包数量,或期望两侧的包长度完全相同,是在要求 TCP 提供它并不提供的边界保证。