A Forward Proxy Does Not Preserve TCP Segment Boundaries
Separate TCP segmentation, socket reads and HTTP framing when inspecting traffic on either side of a forward proxy.
Suppose an HTTP response appears in several captured TCP segments after passing through Squid. That can be ordinary TCP behavior, rather than evidence that the response was split incorrectly.
A forward proxy normally has two connections:
client ⇄ TCP connection A ⇄ proxy ⇄ TCP connection B ⇄ origin
Each connection has its own TCP state, sequence numbers and packetization. The proxy can read data from one connection and write it to the other without preserving the original segment sizes. Buffering, send timing, congestion and the path's size limits can produce another grouping.
Three boundaries worth keeping separate
| Boundary | What determines it |
|---|---|
| TCP segment | The transport and network path |
| A socket read result | Available stream bytes and the caller's buffer |
| HTTP message or frame | The HTTP protocol's framing rules |
One read can contain part of a header, an entire header plus body bytes, or data spanning more than one application-level boundary. TCP does not attach “end of HTTP response” to the end of a successful read.
An HTTP/1.1 parser therefore accumulates headers and uses the applicable body-framing rules, including length, transfer coding or permitted connection closure. An HTTP/2 frame is a protocol structure that can itself cross TCP segments; it is not another name for a network packet.
A successful CONNECT tunnel preserves the tunneled byte stream while still using two TCP legs. Its segment boundaries can differ even when the proxy has not changed the bytes inside the tunnel.
Compare reassembled application data when investigating corruption. Comparing packet counts or expecting identical packet lengths on both sides asks TCP for a boundary guarantee it does not provide.