summaryrefslogtreecommitdiffstats
path: root/sys/netinet/tcp_reass.c
diff options
context:
space:
mode:
authorandre <andre@FreeBSD.org>2004-01-08 17:40:07 +0000
committerandre <andre@FreeBSD.org>2004-01-08 17:40:07 +0000
commit491421126ec7822911bd729e856e18a32253d876 (patch)
treed8cee9c3cad3ec8e336b6e4409f27542451db5cc /sys/netinet/tcp_reass.c
parent7884615822e443a520d39b632a86d7b4c5f5353f (diff)
downloadFreeBSD-src-491421126ec7822911bd729e856e18a32253d876.zip
FreeBSD-src-491421126ec7822911bd729e856e18a32253d876.tar.gz
Limiters and sanity checks for TCP MSS (maximum segement size)
resource exhaustion attacks. For network link optimization TCP can adjust its MSS and thus packet size according to the observed path MTU. This is done dynamically based on feedback from the remote host and network components along the packet path. This information can be abused to pretend an extremely low path MTU. The resource exhaustion works in two ways: o during tcp connection setup the advertized local MSS is exchanged between the endpoints. The remote endpoint can set this arbitrarily low (except for a minimum MTU of 64 octets enforced in the BSD code). When the local host is sending data it is forced to send many small IP packets instead of a large one. For example instead of the normal TCP payload size of 1448 it forces TCP payload size of 12 (MTU 64) and thus we have a 120 times increase in workload and packets. On fast links this quickly saturates the local CPU and may also hit pps processing limites of network components along the path. This type of attack is particularly effective for servers where the attacker can download large files (WWW and FTP). We mitigate it by enforcing a minimum MTU settable by sysctl net.inet.tcp.minmss defaulting to 256 octets. o the local host is reveiving data on a TCP connection from the remote host. The local host has no control over the packet size the remote host is sending. The remote host may chose to do what is described in the first attack and send the data in packets with an TCP payload of at least one byte. For each packet the tcp_input() function will be entered, the packet is processed and a sowakeup() is signalled to the connected process. For example an attack with 2 Mbit/s gives 4716 packets per second and the same amount of sowakeup()s to the process (and context switches). This type of attack is particularly effective for servers where the attacker can upload large amounts of data. Normally this is the case with WWW server where large POSTs can be made. We mitigate this by calculating the average MSS payload per second. If it goes below 'net.inet.tcp.minmss' and the pps rate is above 'net.inet.tcp.minmssoverload' defaulting to 1000 this particular TCP connection is resetted and dropped. MITRE CVE: CAN-2004-0002 Reviewed by: sam (mentor) MFC after: 1 day
Diffstat (limited to 'sys/netinet/tcp_reass.c')
-rw-r--r--sys/netinet/tcp_reass.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c
index 36f0444..263dfd8 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
OpenPOWER on IntegriCloud