Why are TCP's window scale, SACK-permitted and timestamps options confined to SYN segments, and what breaks if a middlebox strips one from the SYN-ACK?
answer
- fixed when the connection opens
- an offer needs a matching reply
- responder echoes only what it saw
- permission to receive, not to send
- two ends with different conclusions
basics
~20 sThese options change how the whole connection behaves, so they are offered in the SYN before data flows. Window scale and timestamps apply only if both SYN and SYN-ACK carry them; stripping one from the SYN-ACK leaves the two ends disagreeing.
solid answer
~50 sWindow scale, SACK-permitted and timestamps each change how every later segment is written or read, so both ends must know the outcome before data flows; RFC 7323 fixes the window scale in each direction when the connection opens. They are offers: `Window Scale` (kind 3) and `Timestamps` (kind 8) are in effect only if both the SYN and the SYN-ACK carry them, and a responder may include them in its SYN-ACK only if the SYN did. `SACK-permitted` (kind 4) gives permission: a TCP may send SACK blocks only if its peer sent it. If a middlebox strips window scale from the SYN-ACK, the responder believes scaling is on while the initiator believes it is off, so they misread each other's windows. If it strips timestamps after they were negotiated, RFC 7323 tells the receiver to drop the segments that lack them.
go deeper
Remember that some TCP features are switched on during the handshake, and that most of them work only when both sides include the option.
State the SYN and SYN-ACK rules for window scale, timestamps and SACK-permitted, and why each has to be settled before data flows.
Diagnose a middlebox that strips or edits handshake options by comparing both endpoints' view of the SYN-ACK, and predict what each end concludes.
Explain why TCP extensions depend on unmodified SYNs, and what that dependence on middlebox behaviour means for evolving a transport protocol.
## Why the SYN is the only place for these options A TCP option can appear in any segment, but three common extensions are restricted to the handshake because they change the **meaning of later segments**: - **Window Scale** changes how every later 16-bit window field is read. RFC 7323 says the option "is sent only in a `<SYN>` segment ... hence the window scale is fixed in each direction when a connection is opened". Changing it mid-connection would make windows already advertised ambiguous. - **Timestamps**, once agreed, MUST appear in every non-`RST` segment, and the receiver checks for them. Both ends must know from the first data segment whether to expect them. - **SACK-permitted** tells the peer that this TCP can process SACK blocks, which must be known before the first loss. RFC 7323 adds a historical reason: early worries that buggy implementations would crash on options in non-`SYN` segments made negotiating in the `SYN` the conservative choice, and it notes that avoiding such bugs "is not the only reason for negotiating TCP options on `<SYN>` segments". ## The rules for each option | Option | Kind / length | In the `SYN` | In the `SYN-ACK` | In effect when | |---|---|---|---|---| | Window Scale | 3 / 3 | MAY be sent | MAY be sent only if the `SYN` carried it | Both sent it; otherwise neither direction scales | | Timestamps | 8 / 10 | MAY be sent | MAY be sent only if the `SYN` carried it | Both sent it; then required in every non-`RST` segment | | SACK-permitted | 4 / 2 | MAY be sent | MAY be sent | A TCP may send SACK blocks only if its **peer** sent it | Three details that trip people up: - RFC 7323 calls window scale "an offer, not a promise": **both** sides MUST send it for scaling to work in **either** direction. A shift count of 0 is a legal way to say "I understand scaling but do not need it". - The shift count is capped at **14**, which allows windows up to 2^30 bytes (1 GiB). A received value above 14 is logged and treated as 14. - A Window Scale option in a segment without `SYN` MUST be ignored, and the window field of a `SYN` or `SYN-ACK` is never scaled. What the negotiated scale factor then does to the receive window, how SACK blocks are chosen, and how timestamps are used for round-trip sampling are separate topics; this one is about how each extension gets switched on. ## What a middlebox can break RFC 7323 warns that "some middleboxes have been known to remove" these options, and that removing them from the `SYN-ACK` "will leave the end hosts in a state that destroys the proper operation of the protocol". 1. **Window Scale stripped from the `SYN-ACK`.** The responder received the option and sent its own, so it enables scaling. The initiator never sees a reply, so it disables scaling. From then on the two ends read each other's window fields with different shift counts, and throughput or correctness suffers. 2. **Window Scale stripped from the `SYN`.** Both ends agree that scaling is off. Nothing is inconsistent, but the connection loses large windows. 3. **Timestamps stripped from the handshake.** Removed from the `SYN`, neither end enables them, and fast connections lose the protection against wrapped sequence numbers (PAWS) they provide. Removed from the `SYN-ACK` only, the responder saw the option in the `SYN` and sent its own, so it considers timestamps agreed while the initiator does not, which is the broken state RFC 7323 warns about. 4. **Timestamps stripped from later segments.** After negotiation, RFC 7323 says a non-`RST` segment without the option SHOULD be silently dropped, and a TCP MUST NOT abort because of it. A middlebox that re-segments and drops the option can therefore stall the session. RFC 7323 also notes that a stateful firewall that tracks windows but ignores the scale factor cannot judge which segments are in window, and must either apply the factor or skip window checks. ## Reading it in a capture - Compare the options in the `SYN` with those in the `SYN-ACK`. An option offered and not answered means it is off for window scale and timestamps. - If the endpoints' own traces disagree about what the `SYN-ACK` contained, something on the path edited it. - Check whether later segments still carry timestamps if the handshake agreed them.
- Why does a TCP that needs no window scaling still send a Window Scale option with a shift count of 0?Scaling works in either direction only when both sides send the option. A TCP with small buffers that stays silent would stop its peer from scaling its own receive window. RFC 7323 says a TCP prepared to scale SHOULD send the option even with an exponent of 0, which signals 'I understand scaling' while applying a factor of 1 to its own window.
- What limits the largest window that TCP window scaling can express?RFC 7323 caps the shift count at 14, so the 16-bit window field shifted by 14 bits stays just under 2^30 bytes, about 1 GiB. A received shift above 14 is logged and treated as 14. The cap keeps twice the maximum window below 2^31, which TCP's sequence-number comparisons require.
saying these in an interview costs you the question
- Window scaling is on once the client offers it in its SYN
- A responder may add window scale to its SYN-ACK unprompted
- Sending SACK-permitted lets a TCP send SACK blocks to its peer
- Window scale can be renegotiated later with a new option
- A segment missing negotiated timestamps makes TCP abort the connection