Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 25 Jan 2000 09:37:09 -0700
From:      Warner Losh <imp@village.org>
To:        security@freebsd.org
Subject:   Merged patches
Message-ID:  <200001251637.JAA04226@harmony.village.org>

next in thread | raw e-mail | index | archive | help

OK.  I've very lightly tested the following patch.  It combines what
appears to be the best of all the patches floating around.  It does
two things.  First, it is more agressive about discarding packets that
are from broadcast addresses.  Second, it ties rate limiting of RST
packets to ICMP_BANDLIM.  Likely not the best name, but we can work
that out later.

It doesn't try to optimize the tcp_input path more than this.  I
judged it too risky this close to a release.

Please let me know what you think of this patch and what testing
reveals.  Make sure that you have an options ICMP_BANDLIM in your
kernel and that you have it enabled before reporting problems with
this patch.  I'm thinking seriously of removing the ICMP_BANDLIM
option as an option (eg compile the code in no matter what), but
raising the limit from 100 to 1000 or something like that so it won't
normally impact people, but those desiring to harden their servers can
drift the number downward.

Comment?

Warner

Index: netinet/tcp_input.c
===================================================================
RCS file: /home/imp/FreeBSD/CVS/src/sys/netinet/tcp_input.c,v
retrieving revision 1.103
diff -u -r1.103 tcp_input.c
--- netinet/tcp_input.c	2000/01/15 14:56:35	1.103
+++ netinet/tcp_input.c	2000/01/25 16:31:14
@@ -615,10 +615,6 @@
 				break;
 			}
 		}
-#ifdef ICMP_BANDLIM
-		if (badport_bandlim(1) < 0)
-			goto drop;
-#endif
 		if (blackhole) { 
 			switch (blackhole) {
 			case 1:
@@ -631,11 +627,11 @@
 				goto drop;
 			}
 		}
-		goto dropwithreset;
+		goto maybedropwithreset;
 	}
 	tp = intotcpcb(inp);
 	if (tp == 0)
-		goto dropwithreset;
+		goto maybedropwithreset;
 	if (tp->t_state == TCPS_CLOSED)
 		goto drop;
 
@@ -695,7 +691,7 @@
 				 */
 				if (thflags & TH_ACK) {
 					tcpstat.tcps_badsyn++;
-					goto dropwithreset;
+					goto maybedropwithreset;
 				}
 				goto drop;
 			}
@@ -772,7 +768,7 @@
 				 */
 				if (thflags & TH_ACK) {
 					tcpstat.tcps_badsyn++;
-					goto dropwithreset;
+					goto maybedropwithreset;
 				}
 				goto drop;
 			}
@@ -999,7 +995,7 @@
 		if (thflags & TH_RST)
 			goto drop;
 		if (thflags & TH_ACK)
-			goto dropwithreset;
+			goto maybedropwithreset;
 		if ((thflags & TH_SYN) == 0)
 			goto drop;
 		if (th->th_dport == th->th_sport) {
@@ -1017,17 +1013,22 @@
 		 * RFC1122 4.2.3.10, p. 104: discard bcast/mcast SYN
 		 * in_broadcast() should never return true on a received
 		 * packet with M_BCAST not set.
+ 		 *
+ 		 * Packets with a multicast source address should also
+ 		 * be discarded.
 		 */
 		if (m->m_flags & (M_BCAST|M_MCAST))
 			goto drop;
 #ifdef INET6
 		if (isipv6) {
-			if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst))
+			if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
+			    IN6_IS_ADDR_MULTICAST(&ip6->ip6_src))
 				goto drop;
 		} else
 #endif
-		if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)))
-			goto drop;
+		if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) ||
+		    IN_MULTICAST(ntohl(ip->ip_src.s_addr)) ||
+		    IN_EXPERIMENTAL(ntohl(ip->ip_src.s_addr)))
 #ifdef INET6
 		if (isipv6) {
 			MALLOC(sin6, struct sockaddr_in6 *, sizeof *sin6,
@@ -1187,7 +1188,7 @@
 		if ((thflags & TH_ACK) &&
 		    (SEQ_LEQ(th->th_ack, tp->snd_una) ||
 		     SEQ_GT(th->th_ack, tp->snd_max)))
-				goto dropwithreset;
+				goto maybedropwithreset;
 		break;
 
 	/*
@@ -1529,7 +1530,7 @@
 	 * for the "LAND" DoS attack.
 	 */
 	if (tp->t_state == TCPS_SYN_RECEIVED && SEQ_LT(th->th_seq, tp->irs))
-		goto dropwithreset;
+		goto maybedropwithreset;
 
 	todrop = tp->rcv_nxt - th->th_seq;
 	if (todrop > 0) {
@@ -2192,7 +2193,7 @@
 	if (tp->t_state == TCPS_SYN_RECEIVED && (thflags & TH_ACK) &&
 	    (SEQ_GT(tp->snd_una, th->th_ack) ||
 	     SEQ_GT(th->th_ack, tp->snd_max)) )
-		goto dropwithreset;
+		goto maybedropwithreset;
 #ifdef TCPDEBUG
 	if (so->so_options & SO_DEBUG)
 		tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,
@@ -2203,6 +2204,17 @@
 	(void) tcp_output(tp);
 	return;
 
+
+	/*
+	 * Conditionally drop with reset or just drop depending on whether
+	 * we think we are under attack or not.
+	 */
+maybedropwithreset:
+#ifdef ICMP_BANDLIM
+	if (badport_bandlim(1) < 0)
+		goto drop;
+#endif
+	/* fall through */
 dropwithreset:
 #ifdef TCP_RESTRICT_RST
 	if (restrict_rst)
@@ -2217,11 +2229,14 @@
 		goto drop;
 #ifdef INET6
 	if (isipv6) {
-		if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst))
+		if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
+		    IN6_IS_ADDR_MULTICAST(&ip6->ip6_src))
 			goto drop;
 	} else
 #endif /* INET6 */
-	if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)))
+	if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) ||
+	    IN_MULTICAST(ntohl(ip->ip_src.s_addr)) ||
+	    IN_EXPERIMENTAL(ntohl(ip->ip_src.s_addr)))
 		goto drop;
 	/* IPv6 anycast check is done at tcp6_input() */
 #ifdef TCPDEBUG


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-security" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200001251637.JAA04226>