From owner-freebsd-security Tue Jan 25 8:37:50 2000 Delivered-To: freebsd-security@freebsd.org Received: from rover.village.org (rover.village.org [204.144.255.49]) by hub.freebsd.org (Postfix) with ESMTP id 6C60314EB8 for ; Tue, 25 Jan 2000 08:37:24 -0800 (PST) (envelope-from imp@harmony.village.org) Received: from harmony.village.org (harmony.village.org [10.0.0.6]) by rover.village.org (8.9.3/8.9.3) with ESMTP id JAA06320 for ; Tue, 25 Jan 2000 09:37:23 -0700 (MST) (envelope-from imp@harmony.village.org) Received: from harmony.village.org (localhost.village.org [127.0.0.1]) by harmony.village.org (8.9.3/8.8.3) with ESMTP id JAA04226 for ; Tue, 25 Jan 2000 09:37:09 -0700 (MST) Message-Id: <200001251637.JAA04226@harmony.village.org> To: security@freebsd.org Subject: Merged patches Date: Tue, 25 Jan 2000 09:37:09 -0700 From: Warner Losh Sender: owner-freebsd-security@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org 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