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:
parent
1c168bb710
commit
80dd2a81fb
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=128653
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user