Index: sys/netinet/icmp_var.h =================================================================== --- sys/netinet/icmp_var.h +++ sys/netinet/icmp_var.h @@ -96,7 +96,8 @@ #define BANDLIM_RST_OPENPORT 4 /* No connection, listener */ #define BANDLIM_ICMP6_UNREACH 5 #define BANDLIM_SCTP_OOTB 6 -#define BANDLIM_MAX 7 +#define BANDLIM_TCP_ACKTOOMUCH 7 +#define BANDLIM_MAX 8 #endif #endif Index: sys/netinet/ip_icmp.c =================================================================== --- sys/netinet/ip_icmp.c +++ sys/netinet/ip_icmp.c @@ -987,7 +987,8 @@ { "closed port RST response" }, { "open port RST response" }, { "icmp6 unreach response" }, - { "sctp ootb response" } + { "sctp ootb response" }, + { "tcp out-of-window ACK responses" }, }; #define V_icmp_rates VNET(icmp_rates) Index: sys/netinet/tcp_input.c =================================================================== --- sys/netinet/tcp_input.c +++ sys/netinet/tcp_input.c @@ -2503,6 +2503,27 @@ case TCPS_LAST_ACK: if (SEQ_GT(th->th_ack, tp->snd_max)) { TCPSTAT_INC(tcps_rcvacktoomuch); + /* + * This likely indicates either a spoofed + * packet or an unsynchronized connection. In + * the latter case, RFC 793 provides some + * examples of how sending an ACK can help the + * remote side determine the connection is + * unsynchronized, leading it to close the + * connection. So, it probably makes sense to + * continue to send ACKs in this case. + * + * However, these ACKs often will *not* be + * useful. And, in some extreme cases, we can + * even end up in a cyclical pattern of + * badness. (Bug 184680 documents one such + * case which involves sessions opened with a + * SYN cookie.) + * + * Therefore, we should rate-limit these responses. + */ + if (badport_bandlim(BANDLIM_TCP_ACKTOOMUCH) < 0) + goto drop; goto dropafterack; } if ((tp->t_flags & TF_SACK_PERMIT) &&