Tighten up reset handling in order to make reset attacks as difficult as

possible while maintaining compatibility with the widest range of TCP stacks.

The algorithm is as follows:

---
For connections in the ESTABLISHED state, only resets with
sequence numbers exactly matching last_ack_sent will cause a reset,
all other segments will be silently dropped.

For connections in all other states, a reset anywhere in the window
will cause the connection to be reset.  All other segments will be
silently dropped.
---

The necessity of accepting all in-window resets was discovered
by jayanth and jlemon, both of whom have seen TCP stacks that
will respond to FIN-ACK packets with resets not meeting the
strict last_ack_sent check.

Idea by:        Darren Reed
Reviewed by:    truckman, jlemon, others(?)
This commit is contained in:
Mike Silbersack 2004-04-26 02:56:31 +00:00
parent 1c168bb710
commit 80dd2a81fb
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=128653
3 changed files with 21 additions and 0 deletions

View File

@ -1532,6 +1532,12 @@ tcp_input(m, off0)
* echo of our outgoing acknowlegement numbers, but some hosts
* send a reset with the sequence number at the rightmost edge
* of our receive window, and we have to handle this case.
* Note 2: Paul Watson's paper "Slipping in the Window" has shown
* that brute force RST attacks are possible. To combat this,
* we use a much stricter check while in the ESTABLISHED state,
* only accepting RSTs where the sequence number is equal to
* last_ack_sent. In all other states (the states in which a
* RST is more likely), the more permissive check is used.
* If we have multiple segments in flight, the intial reset
* segment sequence numbers will be to the left of last_ack_sent,
* but they will eventually catch up.
@ -1570,6 +1576,10 @@ tcp_input(m, off0)
goto close;
case TCPS_ESTABLISHED:
if (tp->last_ack_sent != th->th_seq) {
tcpstat.tcps_badrst++;
goto drop;
}
case TCPS_FIN_WAIT_1:
case TCPS_FIN_WAIT_2:
case TCPS_CLOSE_WAIT:

View File

@ -1532,6 +1532,12 @@ tcp_input(m, off0)
* echo of our outgoing acknowlegement numbers, but some hosts
* send a reset with the sequence number at the rightmost edge
* of our receive window, and we have to handle this case.
* Note 2: Paul Watson's paper "Slipping in the Window" has shown
* that brute force RST attacks are possible. To combat this,
* we use a much stricter check while in the ESTABLISHED state,
* only accepting RSTs where the sequence number is equal to
* last_ack_sent. In all other states (the states in which a
* RST is more likely), the more permissive check is used.
* If we have multiple segments in flight, the intial reset
* segment sequence numbers will be to the left of last_ack_sent,
* but they will eventually catch up.
@ -1570,6 +1576,10 @@ tcp_input(m, off0)
goto close;
case TCPS_ESTABLISHED:
if (tp->last_ack_sent != th->th_seq) {
tcpstat.tcps_badrst++;
goto drop;
}
case TCPS_FIN_WAIT_1:
case TCPS_FIN_WAIT_2:
case TCPS_CLOSE_WAIT:

View File

@ -414,6 +414,7 @@ struct tcpstat {
u_long tcps_badsyn; /* bogus SYN, e.g. premature ACK */
u_long tcps_mturesent; /* resends due to MTU discovery */
u_long tcps_listendrop; /* listen queue overflows */
u_long tcps_badrst; /* ignored RSTs in the window */
u_long tcps_sc_added; /* entry added to syncache */
u_long tcps_sc_retransmitted; /* syncache entry was retransmitted */