Improving TCP's Robustness to Blind In-Window Attacks
updated by
- rfc-9293 — Transmission Control Protocol (TCP)
Extracted elements (23)
ACK throttling is introduced as a fail-safe to prevent a flood of spoofed RST/SYN segments from causing a flood of challenge ACKs. A timestamp-and-counter mechanism (no timer needed) is suggested; no amplification is expected but throttling guards against resource exhaustion and unusual network conditions.
Requiring RST sequence numbers to exactly match RCV.NXT (rather than falling anywhere in the window) forces an attacker to generate on average 1/2 the entire 32-bit sequence space (2^31 attempts) instead of only 2^31/window attempts, restoring the original design assumption of sequence-number protection.
The challenge-ACK mechanism for SYN attacks leaves an unhandled corner case: if a restarted host happens to reuse the same 4-tuple and its new ISN is exactly RCV.NXT-1 of the peer still in ESTABLISHED, the challenge ACK will be accepted and the reconnection will silently stall. The document notes this pre-exists in RFC 793 and is not introduced by these requirements.
The data injection mitigation is tagged MAY (weaker than the SHOULD for RST/SYN) because data injection requires correctly guessing both a sequence number and an ACK value, making it statistically twice as difficult as RST/SYN injection. Nonetheless, it improves robustness and is still recommended.
The RST and SYN mitigations are tagged SHOULD rather than MUST because they involve changes to existing RFC 793 state-machine behavior and were intended to be strongly recommended but not mandated, allowing implementers flexibility while strongly encouraging adoption for vulnerable deployment scenarios.
A middlebox that caches and resends RSTs with the old (non-exact) sequence number after receiving a challenge ACK will cause a RST/ACK loop; such middleboxes are generating non-conformant packets. RFC 793 requires RST sequence numbers to be derived from the ACK field of the incoming ACK, so this behavior is out of scope for mitigation here.
All mitigations in this document are backward compatible with RFC 793-compliant implementations; no new assumptions or conditions are introduced. However, for maximum effectiveness against the described vulnerabilities, both endpoints of the TCP connection must implement the fix.
Firewalls and NATs that lack the fix may drop the challenge ACK because the original in-window RST already cleared their flow-state entry. This leaves the TCP connection open at both endpoints indefinitely. The issue is resolved only if the middlebox is made conformant with this document.
Some middleboxes compute RST sequence numbers as (ACK + advertised window), placing the RST at the high end of the acceptable window. This causes repeated challenge-ACK/RST exchanges; the ACK throttling mechanism described in Section 7 can mitigate the resulting traffic.
An implementation SHOULD include an ACK throttling mechanism. The values for the time window and maximum challenge ACK count (e.g., no more than 10 challenge ACKs per 5-second window) SHOULD be tunable by the system administrator.
If a RST segment arrives with a sequence number within the receive window but not an exact match to RCV.NXT (RCV.NXT < SEG.SEQ < RCV.NXT+RCV.WND), TCP MUST send a challenge ACK (<SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>) and MUST drop the unacceptable segment. Implementations SHOULD apply this rule in place of the original RFC 793 RST handling.
Implementations that regularly maintain long-lived TCP connections (e.g., BGP) where endpoints are predictable and no auxiliary anti-spoofing like TCP MD5 is available SHOULD implement the mitigations specified in this document. These mitigations MAY be implemented in other cases.
TCP stacks MAY implement the data injection mitigation. Stacks that do implement it MUST add an input check requiring SEG.ACK to satisfy ((SND.UNA - MAX.SND.WND) <= SEG.ACK <= SND.NXT); segments failing this check MUST be discarded and an ACK sent back.
Upon receipt of a valid RST returned in response to a challenge ACK sent after an in-window SYN, the local TCP endpoint MUST terminate its connection and then rely on SYN retransmission from the remote end to re-establish.
When a RST segment is received in a synchronized state and its sequence number exactly matches the next expected sequence number (RCV.NXT), TCP MUST reset the connection. RSTs outside the receive window MUST be silently discarded.
When a SYN segment is received in a synchronized state, irrespective of sequence number, TCP MUST send a challenge ACK (<SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>) and MUST drop the segment. This replaces the RFC 793 behavior of sending RST on an in-window SYN. Implementations SHOULD apply this handling.
MAX.SND.WND is a new TCP state variable defined as the largest receive window ever advertised by the remote peer on this connection. It is used to bound the acceptable ACK range for incoming data segments and may be scaled when the window scaling option (RFC 1323) is in use.
The 'challenge ACK' is a TCP acknowledgment segment of the form <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK> sent in response to an in-window but non-exact RST or any synchronized-state SYN, prompting the remote peer to confirm or deny the connection state.
Forged ICMP messages provide off-path attackers an opportunity to disrupt or degrade TCP connections independently of the TCP-level mitigations described here. Unless implementations also address spoofed ICMP (see RFC 5927), the protection level may be lower than desired, particularly for path-MTU-related ICMP messages.
The mitigations in this document do NOT protect against on-path (man-in-the-middle) attacks; they only raise the bar for off-path blind attacks. Full protection against both on- and off-path attacks requires IPsec AH (RFC 4302) or IPsec ESP (RFC 4303).
The required RST/SYN challenge-ACK mechanism enables a reflector attack: an off-path attacker can cause a victim to emit one challenge ACK for each spoofed in-window RST/SYN. This is not an amplification attack (1:1 ratio) but can be used to cause traffic toward a victim's peer.
Modified RST processing in synchronized states: (1) SEQ outside window → silently discard; (2) SEQ == RCV.NXT → reset connection; (3) RCV.NXT < SEQ < RCV.NXT+RCV.WND → send challenge ACK and discard. In SYN-SENT, a RST is acceptable only if the ACK field acknowledges the SYN; otherwise silently discard.
Modified SYN processing in synchronized states: regardless of sequence number, always send a challenge ACK and drop the segment. A legitimate restarted peer receiving the challenge ACK will send a RST (no TCB exists), which — if valid — causes the local endpoint to close and await SYN retransmission.