Why does TCP not start every connection's sequence numbers at zero, and how does RFC 9293 say the initial sequence number should be chosen?
answer
- segments outlive their connection
- a clock plus a keyed function
- a separate number space per four-tuple
- off-path guessing
- 4 microseconds, about 4.55 hours
basics
~20 sA fixed start lets delayed segments from an earlier connection on the same ports be accepted; a predictable one lets off-path attackers forge segments. RFC 9293 sets ISN = M + F(four-tuple, secret key): a 4-microsecond clock plus a keyed pseudorandom offset.
solid answer
~50 sTwo reasons. First, segments can survive in the network for up to a maximum segment lifetime; if a new connection between the same addresses and ports reused the old numbering, a delayed segment could fall inside the new window and be accepted. `TIME-WAIT` is the main guard against that, and ISN choice adds protection. Second, an off-path attacker who can predict an ISN can complete a spoofed handshake or forge segments without seeing any traffic, an attack described in 1985 whose exploitation was widely publicized about ten years later. RFC 9293 section 3.4.1 answers both with `ISN = M + F(localip, localport, remoteip, remoteport, secretkey)`: `M` is a clock ticking roughly every 4 microseconds, and `F` is a pseudorandom function keyed by a secret that MUST NOT be computable from outside. This came from RFC 6528, which RFC 9293 obsoleted. It is deliberately not pure randomness: each four-tuple keeps its own increasing number space.
code
pseudocode · 5 lines// RFC 9293 section 3.4.1 initial sequence number
M = clock() // 32-bit, +1 about every 4 microseconds
key = secretkey // e.g. 128 bits, rotated at boot
F = PRF(key, localip, localport, remoteip, remoteport)
ISN = (M + F) mod 2^32go deeper
Remember that each side picks its own starting sequence number and that it is deliberately not zero and not guessable.
Explain both reasons, stale segments from an earlier incarnation and off-path guessing, and write out ISN = M + F(four-tuple, secret key) with what each part contributes.
Explain why pure randomness is rejected, where TIME-WAIT does the main stale-segment work, and why an unpredictable ISN is no defence against an on-path attacker.
Judge when sequence-number unpredictability is sufficient for long-lived or address-trusted sessions and when to require cryptographic protection instead.
## What the initial sequence number is TCP numbers every byte it sends. Each direction of a connection has its own numbering, starting from an **initial sequence number (ISN)** chosen by that direction's sender and announced in its `SYN`. The numbers are 32 bits wide and wrap around. A receiver accepts a segment only if its sequence number falls inside the receive window it currently expects, so the starting point decides which stray segments could be mistaken for valid ones. ## Problem 1: segments from an earlier incarnation A connection is identified by its **four-tuple**: local address, local port, remote address, remote port. When a connection closes and the same four-tuple is opened again, RFC 9293 calls the new one another *incarnation* of the connection. - Segments can be delayed in the network. RFC 9293 bounds this with the **maximum segment lifetime (MSL)**, which it takes to be 2 minutes as an engineering choice. - If every incarnation started at zero, a delayed segment from the previous one could carry a sequence number inside the new incarnation's window and be delivered as data. - The `TIME-WAIT` state, which holds a closed four-tuple for twice the MSL, is the main defence; RFC 9293 says ISN selection **further protects** against the ambiguity. Teardown and `TIME-WAIT` are their own topic. - The ISN clock is a 32-bit counter that ticks roughly every **4 microseconds**, so it cycles about every **4.55 hours**, much longer than the MSL. New incarnations therefore start ahead of numbers the old one used. - A host that has lost track of the numbers it was using, for example after a crash, is asked to stay quiet for one MSL before assigning sequence numbers again. ## Problem 2: prediction by an off-path attacker The original design used one global counter. RFC 6528 notes that this made it trivial for an off-path attacker to predict the ISN a host would use next. The classic abuse: 1. The attacker sends a `SYN` to a server, forging the source address of a host the server trusts by address. 2. The server's `SYN-ACK` goes to the real owner of that address, so the attacker never sees the server's ISN. 3. If the ISN is predictable, the attacker sends the final `ACK` with the right acknowledgment number, plus data, and the server believes it is talking to the trusted host. 4. This works only if the real owner does not answer the stray `SYN-ACK` with a reset, which would tear the half-built connection down. RFC 6528 traces this attack to a 1985 description whose exploitation was widely publicized about ten years later. Predictable numbers also help forge segments into existing connections, a threat covered by the in-window injection topic. ## The construction RFC 9293 specifies ```pseudocode // RFC 9293 section 3.4.1, from RFC 6528 M = 32-bit clock, incremented about every 4 microseconds F = keyed pseudorandom function, not computable from outside ISN = M + F(localip, localport, remoteip, remoteport, secretkey) ``` - A TCP implementation **MUST** use a clock-driven ISN generator (MUST-8) and **SHOULD** use the expression above (SHLD-1). - `F()` **MUST NOT** be computable from the outside (MUST-9); otherwise the ISN of one connection would reveal others. - `F()` can be a cryptographic hash of the four-tuple and secret data. RFC 6528 judged a 128-bit key adequate and suggested changing it occasionally, for example at boot. Each four-tuple thus gets its own number space: moving forward with the clock, but offset by an amount an outsider cannot compute. ## Comparing the options | Approach | Stale-segment protection | Unpredictable to outsiders | Drawback | |---|---|---|---| | Start at zero | none | no | old segments land in new windows | | One global clock | yes | no | any connection reveals the next ISN | | Fresh random value each time | weak | yes | a new incarnation may start behind the old one | | Clock plus keyed offset | yes, per four-tuple | yes | depends on keeping the secret | RFC 6528 adds a practical reason against pure randomness: BSD-derived stacks use the ISN of an incoming SYN to decide whether to accept a new incarnation while the previous one is still in `TIME-WAIT`, and random ISNs break that heuristic. ## Where the specification stands The algorithm was proposed in RFC 1948, taken to Standards Track by RFC 6528 in 2012, and folded into RFC 9293 in 2022, which obsoletes RFC 6528. Cite RFC 9293 for the current rule. An unpredictable ISN does **not** encrypt or authenticate anything. An attacker who can see the traffic reads the sequence numbers directly. RFC 9293 points to cryptographic protection such as IPsec or TCP-AO when that threat matters. SYN cookies, which reuse the ISN field to carry state, belong to the flood-defence topic.
- Why not simply choose a fresh random TCP ISN for every connection?Pure randomness defeats guessing but loses ordering: a new incarnation of the same four-tuple could start behind sequence numbers still in flight from the old one. RFC 6528 also notes it breaks the heuristic BSD-derived stacks use to accept a new SYN while the old connection is in TIME-WAIT. A clock plus a keyed offset keeps each four-tuple's numbers increasing yet unpredictable to outsiders.
- Does an unpredictable ISN protect a TCP connection from an attacker who can see its packets?No. An on-path observer reads sequence numbers directly, so unpredictability only raises the bar for off-path attackers who must guess. Protection against someone who can see or change traffic needs cryptographic integrity, such as IPsec or TCP-AO, which RFC 9293 points to.
saying these in an interview costs you the question
- TCP ISNs are pure random numbers with no clock component.
- Starting at zero is safe because ports already separate connections.
- A random ISN encrypts or authenticates the TCP connection.
- Both directions of a connection share one ISN chosen by the client.
- RFC 6528 is the current specification for choosing TCP ISNs.