diff options
Diffstat (limited to 'sys/netinet/tcp_reass.c')
| -rw-r--r-- | sys/netinet/tcp_reass.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c index 36f044484028..263dfd83f163 100644 --- a/sys/netinet/tcp_reass.c +++ b/sys/netinet/tcp_reass.c @@ -919,6 +919,61 @@ after_listen: panic("tcp_input: TCPS_LISTEN"); /* + * 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). + * + * For every full second we count the number of received packets + * and bytes. If we get a lot of packets per second for this connection + * (tcp_minmssoverload) we take a closer look at it and compute the + * average packet size for the past second. If that is less than + * tcp_minmss we get too many packets with very small payload which + * is not good and burdens our system (and every packet generates + * a wakeup to the process connected to our socket). We can reasonable + * expect this to be small packet DoS attack to exhaust our CPU + * cycles. + * + * Care has to be taken for the minimum packet overload value. This + * value defines the minimum number of packets per second before we + * start to worry. This must not be too low to avoid killing for + * example interactive connections with many small packets like + * telnet or SSH. + * + * Setting either tcp_minmssoverload or tcp_minmss to "0" disables + * this check. + * + * Account for packet if payload packet, skip over ACK, etc. + */ + if (tcp_minmss && tcp_minmssoverload && + tp->t_state == TCPS_ESTABLISHED && tlen > 0) { + if (tp->rcv_second > ticks) { + tp->rcv_pps++; + tp->rcv_byps += tlen + off; + if (tp->rcv_pps > tcp_minmssoverload) { + if ((tp->rcv_byps / tp->rcv_pps) < tcp_minmss) { + printf("too many small tcp packets from " + "%s:%u, av. %lubyte/packet, " + "dropping connection\n", +#ifdef INET6 + isipv6 ? + ip6_sprintf(&inp->inp_inc.inc6_faddr) : +#endif + inet_ntoa(inp->inp_inc.inc_faddr), + inp->inp_inc.inc_fport, + tp->rcv_byps / tp->rcv_pps); + tp = tcp_drop(tp, ECONNRESET); + tcpstat.tcps_minmssdrops++; + goto drop; + } + } + } else { + tp->rcv_second = ticks + hz; + tp->rcv_pps = 1; + tp->rcv_byps = tlen + off; + } + } + + /* * Segment received on connection. * Reset idle time and keep-alive timer. */ @@ -2691,6 +2746,11 @@ tcp_mss(tp, offer) default: /* + * Prevent DoS attack with too small MSS. Round up + * to at least minmss. + */ + offer = max(offer, tcp_minmss); + /* * Sanity check: make sure that maxopd will be large * enough to allow some data on segments even if the * all the option space is used (40bytes). Otherwise |
