Index: tcp_input.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/tcp_input.c,v retrieving revision 1.298 diff -u -r1.298 tcp_input.c --- tcp_input.c 21 Apr 2006 09:25:39 -0000 1.298 +++ tcp_input.c 7 Jun 2006 08:37:15 -0000 @@ -160,6 +160,27 @@ &tcp_reass_overflows, 0, "Global number of TCP Segment Reassembly Queue Overflows"); +static int tcp_rst_ttl_counter; +SYSCTL_INT(_net_inet_tcp, OID_AUTO, rst_ttl_counter, CTLFLAG_RD, + &tcp_rst_ttl_counter, 0, "Number of fuzzy ttl drops"); + +static int tcp_rst_ttl_test_counter; +SYSCTL_INT(_net_inet_tcp, OID_AUTO, rst_ttl_test_counter, CTLFLAG_RD, + &tcp_rst_ttl_test_counter, 0, "Number of fuzzy ttl tests"); + +static int tcp_rst_ttl_update_counter; +SYSCTL_INT(_net_inet_tcp, OID_AUTO, rst_ttl_update_counter, CTLFLAG_RD, + &tcp_rst_ttl_update_counter, 0, "Number of fuzzy ttl updates"); + +static int tcp_rst_ttl_checking = -1; +SYSCTL_INT(_net_inet_tcp, OID_AUTO, rst_ttl_checking, CTLFLAG_RW, + &tcp_rst_ttl_checking, 0, "Fuzzy ttl checking on resets."); + +static int tcp_rst_ttl_segment_counter; +SYSCTL_INT(_net_inet_tcp, OID_AUTO, tcp_rst_ttl_segment_counter, CTLFLAG_RD, + &tcp_rst_ttl_segment_counter, 0, + "Count of segments seen by rst checker"); + struct inpcbhead tcb; #define tcb6 tcb /* for KAME src sync over BSD*'s */ struct inpcbinfo tcbinfo; @@ -441,7 +462,7 @@ register struct tcpcb *tp = 0; register int thflags; struct socket *so = 0; - int todrop, acked, ourfinisacked, needoutput = 0; + int todrop, acked, ourfinisacked, needoutput = 0, ttl; u_long tiwin; struct tcpopt to; /* options in this segment */ int headlocked = 0; @@ -484,6 +505,7 @@ goto drop; } th = (struct tcphdr *)((caddr_t)ip6 + off0); + ttl = ip6->ip6_hlim; /* * Be proactive about unspecified IPv6 address in source. @@ -516,6 +538,7 @@ } } ip = mtod(m, struct ip *); + ttl = ip->ip_ttl; ipov = (struct ipovly *)ip; th = (struct tcphdr *)((caddr_t)ip + off0); tlen = ip->ip_len; @@ -1022,6 +1045,37 @@ KASSERT(tp->t_state != TCPS_LISTEN, ("tcp_input: TCPS_LISTEN")); /* + * Strict TCP RST checking: if not a RST packet, update our notion of + * a recently seen TTL. If it is a RST, check to make sure it fits + * our notion of an appropriate TTL, dropping if not. This reduces + * robustness in the face of changing network topology, as we may + * reject a legitimate RST packets, resulting in a delay in closing + * a connection that should be reset. However, it improves + * robustness against improperly injected RST's. + */ + if (((thflags & TH_RST) == 0) && (tp->t_lastttl != ttl)) { + tcp_rst_ttl_update_counter++; + tp->t_lastttl = ttl; + } + if (tcp_rst_ttl_checking != -1) { + tcp_rst_ttl_segment_counter++; + if ((thflags & TH_RST) && (tp->t_lastttl != 0)) { + tcp_rst_ttl_test_counter++; + if (ttl > (int)tp->t_lastttl + tcp_rst_ttl_checking || + ttl < (int)tp->t_lastttl - tcp_rst_ttl_checking) { + printf("Drop reset from %s:%u (t_ttl %d, ttl %d)\n", + isipv6 ? + ip6_sprintf(&inp->inp_inc.inc6_faddr) : + inet_ntoa(inp->inp_inc.inc_faddr), + inp->inp_inc.inc_fport, tp->t_lastttl, + ttl); + tcp_rst_ttl_counter++; + goto drop; + } + } + } + + /* * This is the second part of the MSS DoS prevention code (after * minmss on the sending side) and it deals with too many too small * tcp packets in a too short timeframe (1 second). Index: tcp_var.h =================================================================== RCS file: /home/ncvs/src/sys/netinet/tcp_var.h,v retrieving revision 1.129 diff -u -r1.129 tcp_var.h --- tcp_var.h 1 Apr 2006 16:36:36 -0000 1.129 +++ tcp_var.h 7 Jun 2006 08:37:39 -0000 @@ -200,6 +200,7 @@ episode starts at this seq number */ struct sackhint sackhint; /* SACK scoreboard hint */ int t_rttlow; /* smallest observerved RTT */ + u_char t_lastttl; /* ttl of last received packet. */ }; #define IN_FASTRECOVERY(tp) (tp->t_flags & TF_FASTRECOVERY)