skip to content

In TCP, what is TIME-WAIT assassination as described in RFC 1337, and why does it undermine the protection TIME-WAIT is meant to give?

level: seniorimportance: nice to knowfreq 12%

answer

  1. an old duplicate arrives late
  2. the ACK meets a forgotten connection
  3. a reset cuts the wait short
  4. RFC 1337's simplest fix

basics

~20 s

An old duplicate segment reaches an endpoint in TIME-WAIT; its ACK reaches a peer with no record of the connection, which answers RST, and the reset ends TIME-WAIT early, exposing a reopened connection to stale segments.

solid answer

~40 s

RFC 1337 (Informational) calls it TIME-WAIT assassination. After a normal close, A holds `TIME-WAIT` and B has deleted the connection. An old duplicate segment of the connection reaches A; it is unacceptable, so A answers with an ACK carrying its current `SND.NXT` and `RCV.NXT`. B has no connection, so it replies `RST`, taking the reset's sequence number from that ACK: exactly the number A expects. Under RFC 9293's base processing a valid reset in `TIME-WAIT` means enter `CLOSED` and delete the connection, so the state meant to let old duplicates die is killed by one of them. If the same four-tuple is reopened at once, RFC 1337 lists three hazards: old data accepted, a desynchronized connection, or the new connection dying. Its simplest fix is to ignore `RST` segments in `TIME-WAIT`.

go deeper

for a junior

Recall that a TCP reset arriving during TIME-WAIT can end that state early, and that RFC 1337 named this TIME-WAIT assassination.

for a middle

Trace the segments: old duplicate, ACK from the TIME-WAIT side, reset from the peer with no record, and why that reset is valid.

for a senior

Explain the three hazards for a reopened four-tuple, why they need overlapping sequence spaces, and why F1 is an implementation choice rather than base RFC 9293 behaviour.

for a principal

Use the case to reason about teardown guarantees in general: state held for safety is only as reliable as the ways it can be ended early, which argues against shortcuts around TIME-WAIT.

## What TIME-WAIT is supposed to guarantee When a TCP connection closes, the endpoint that sent the first `FIN`, the **active closer**, enters `TIME-WAIT` and, per RFC 9293, MUST stay there for twice the **maximum segment lifetime** (MSL, taken as 2 minutes). One reason is to let every delayed duplicate of the old connection expire before the same **four-tuple** (both addresses and both ports) can carry a new **incarnation** of the connection. RFC 1337 lists this as the mechanism that protects fast or long-lived connections, for which the initial-sequence-number choice alone cannot prevent the old and new sequence spaces from overlapping. RFC 1337, an Informational RFC from 1992, observed that this protection is **unreliable**: `TIME-WAIT` can be ended early, "assassinated", by the very kind of segment it is waiting out. ## The assassination, segment by segment RFC 1337 extends the normal close from the TCP specification. A is the active closer, B the passive closer: 1. A sends `FIN` (sequence 100); B acknowledges with ACK 101. 2. B sends its `FIN` (sequence 300); A acknowledges with ACK 301 and enters `TIME-WAIT`. 3. B receives the ACK and goes to `CLOSED`: it has no record of the connection any more. 4. An **old duplicate** segment of this connection, delayed somewhere in the network, reaches A. It is unacceptable, for example because its sequence number lies outside A's window. 5. RFC 9293 tells A to answer an unacceptable segment with an ACK carrying `<SEQ=SND.NXT><ACK=RCV.NXT>`, here `SEQ=101, ACK=301`. 6. B has no connection for that four-tuple. A `CLOSED` endpoint answers any segment except a reset with `RST`, taking the reset's sequence number from the ACK field: `SEQ=301`. 7. A receives a reset whose sequence number is exactly its `RCV.NXT`. It is valid, so A goes to `CLOSED` long before 2×MSL has passed. No attacker is involved. Every step is a correct endpoint following the specification; the trigger is one old duplicate, and RFC 1337 notes that PAWS timestamps (then RFC 1323, now RFC 7323) cannot prevent the assassination itself, since it can happen within a single tick of the timestamp clock. ## Why the reset is accepted Two rules combine: - **Reset validation** accepts a reset whose sequence number is in the window. Even RFC 5961's stricter check, adopted into RFC 9293 as an option, accepts one that matches `RCV.NXT` exactly, and B's reset matches exactly because it was built from A's own acknowledgment. - **Base processing in `TIME-WAIT`**: RFC 9293 says that if the RST bit is set, the endpoint enters `CLOSED`, deletes the connection record and returns. Nothing in the base specification exempts `TIME-WAIT`. The pseudocode shows the three things that can happen to a segment in `TIME-WAIT`: ```pseudocode on segment arrival, state TIME-WAIT: if not acceptable(seg.seq): # e.g. an old duplicate if not seg.RST: send <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK> drop seg; return if seg.RST: if IGNORE_RST_IN_TIME_WAIT: # RFC 1337 fix F1 drop seg; return delete TCB; state = CLOSED # RFC 9293 base processing return if seg.FIN: # retransmitted remote FIN send <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK> restart timer(2 * MSL) ``` ## The three hazards If the four-tuple is reopened immediately after an assassination, the new incarnation meets the old duplicates `TIME-WAIT` was supposed to outlast: | Hazard | What goes wrong | |---|---| | H1 | old duplicate data is accepted by the new connection as if it were new | | H2 | the two ends desynchronize and disagree permanently about state; RFC 1337 notes that following RFC 793 this becomes an endless ACK loop | | H3 | an old duplicate arriving during the new connection's opening kills it | Each hazard needs the old and new sequence spaces to overlap, which only fast or long connections allow, so RFC 1337 judges them much less probable than the assassination itself. ## The fixes RFC 1337 weighed - **F1: ignore `RST` segments in `TIME-WAIT`.** The simplest fix; if the 2-minute MSL is enforced it avoids all three hazards. RFC 1337 recommends it as the best short-term solution and argues it is formally correct, since a state meant to let old duplicates die should not be truncated by a reset. - **F2: use PAWS**, ignoring resets in `TIME-WAIT` only until the timestamp clocks have ticked. A partial fix: it stops old data (H1) but old duplicate ACKs can still slip through, leaving H2 and H3. - **F3: 64-bit sequence numbers.** Would not prevent the assassination itself, but with suitable parameters could defeat all three hazards; a significant protocol change. F1 is a recommendation in an Informational RFC, not part of RFC 9293's base processing; whether a stack applies it is an implementation choice (Linux, for example, offers it as a setting that is off by default). ## What it teaches about resets - A valid reset ends a connection in almost **every** state (a listening endpoint simply ignores one). That is why resets are validated against the window and why forged resets are an attack surface, a subject owned by the in-window injection topic. - The guarantees of `TIME-WAIT` are only as strong as its handling of resets, which is one more reason not to treat it as a timer that can safely be cut short.

  • In TIME-WAIT assassination, why does the peer's RST pass even RFC 5961's stricter reset check?
    The peer builds the reset from the ACK it received, taking the reset's sequence number from that ACK's acknowledgment field. The ACK carried the TIME-WAIT side's own `RCV.NXT`, so the reset's sequence number is exactly the next expected one, which is the one case RFC 5961 still accepts as a reset rather than answering with a challenge ACK.
  • Does ignoring RST in TIME-WAIT, RFC 1337's fix F1, make TCP's TIME-WAIT protection complete?
    RFC 1337 says F1 avoids all three hazards if the 2-minute MSL is enforced. That condition matters: a stack that shortens TIME-WAIT far below 2×MSL has already given up part of the protection by its own choice, whatever it does with resets.

saying these in an interview costs you the question

  • Once entered, TIME-WAIT always lasts the full 2×MSL
  • TIME-WAIT assassination requires an attacker to forge segments
  • RFC 1337 is a standards-track change every TCP must implement
  • PAWS timestamps prevent TIME-WAIT assassination
  • The peer's reset is rejected because its sequence number is out of window