diff options
author | imp <imp@FreeBSD.org> | 2000-01-28 06:13:09 +0000 |
---|---|---|
committer | imp <imp@FreeBSD.org> | 2000-01-28 06:13:09 +0000 |
commit | 9d11326d8605120adbea532fa69211355d967edf (patch) | |
tree | eb7ddca9067c455c52a591ee0e9e14f4d82c1f1b | |
parent | f8e48f511e5de002b13eb638515c1422d6ca1173 (diff) | |
download | FreeBSD-src-9d11326d8605120adbea532fa69211355d967edf.zip FreeBSD-src-9d11326d8605120adbea532fa69211355d967edf.tar.gz |
Mitigate the stream.c attacks
o Drop all broadcast and multicast source addresses in tcp_input.
o Enable ICMP_BANDLIM in GENERIC.
o Change default to 200/s from 100/s. This will still stop the attack, but
is conservative enough to do this close to code freeze.
This is not the optimal patch for the problem, but is likely the least
intrusive patch that can be made for this.
Obtained from: Don Lewis and Matt Dillon.
Reviewed by: freebsd-security
-rw-r--r-- | sys/alpha/conf/GENERIC | 1 | ||||
-rw-r--r-- | sys/alpha/conf/NOTES | 1 | ||||
-rw-r--r-- | sys/amd64/conf/GENERIC | 1 | ||||
-rw-r--r-- | sys/i386/conf/GENERIC | 1 | ||||
-rw-r--r-- | sys/netinet/ip_icmp.c | 2 | ||||
-rw-r--r-- | sys/netinet/tcp_input.c | 48 | ||||
-rw-r--r-- | sys/netinet/tcp_reass.c | 48 |
7 files changed, 69 insertions, 33 deletions
diff --git a/sys/alpha/conf/GENERIC b/sys/alpha/conf/GENERIC index 94c108b..b019739 100644 --- a/sys/alpha/conf/GENERIC +++ b/sys/alpha/conf/GENERIC @@ -59,6 +59,7 @@ options KTRACE #ktrace(1) syscall trace support options SYSVSHM #SYSV-style shared memory options SYSVMSG #SYSV-style message queues options SYSVSEM #SYSV-style semaphores +options ICMP_BANDLIM # Rate limit bad replies # Standard busses device isa diff --git a/sys/alpha/conf/NOTES b/sys/alpha/conf/NOTES index 94c108b..b019739 100644 --- a/sys/alpha/conf/NOTES +++ b/sys/alpha/conf/NOTES @@ -59,6 +59,7 @@ options KTRACE #ktrace(1) syscall trace support options SYSVSHM #SYSV-style shared memory options SYSVMSG #SYSV-style message queues options SYSVSEM #SYSV-style semaphores +options ICMP_BANDLIM # Rate limit bad replies # Standard busses device isa diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC index ea60ce8..a668d6f 100644 --- a/sys/amd64/conf/GENERIC +++ b/sys/amd64/conf/GENERIC @@ -51,6 +51,7 @@ options SYSVSEM #SYSV-style semaphores options P1003_1B #Posix P1003_1B real-time extentions options _KPOSIX_PRIORITY_SCHEDULING options _KPOSIX_VERSION=199309L +options ICMP_BANDLIM # Rate limit bad replies # To make an SMP kernel, the next two are needed #options SMP # Symmetric MultiProcessor Kernel diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC index ea60ce8..a668d6f 100644 --- a/sys/i386/conf/GENERIC +++ b/sys/i386/conf/GENERIC @@ -51,6 +51,7 @@ options SYSVSEM #SYSV-style semaphores options P1003_1B #Posix P1003_1B real-time extentions options _KPOSIX_PRIORITY_SCHEDULING options _KPOSIX_VERSION=199309L +options ICMP_BANDLIM # Rate limit bad replies # To make an SMP kernel, the next two are needed #options SMP # Symmetric MultiProcessor Kernel diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index 76ff004..c2f464e 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -96,7 +96,7 @@ SYSCTL_INT(_net_inet_icmp, OID_AUTO, log_redirect, CTLFLAG_RW, * variable content is -1 and read-only. */ -static int icmplim = 100; +static int icmplim = 200; SYSCTL_INT(_net_inet_icmp, ICMPCTL_ICMPLIM, icmplim, CTLFLAG_RW, &icmplim, 0, ""); #else diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 2a847e6..b802880 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -615,10 +615,6 @@ findpcb: break; } } -#ifdef ICMP_BANDLIM - if (badport_bandlim(1) < 0) - goto drop; -#endif if (blackhole) { switch (blackhole) { case 1: @@ -631,11 +627,11 @@ findpcb: 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 @@ findpcb: */ if (thflags & TH_ACK) { tcpstat.tcps_badsyn++; - goto dropwithreset; + goto maybedropwithreset; } goto drop; } @@ -772,7 +768,7 @@ findpcb: */ if (thflags & TH_ACK) { tcpstat.tcps_badsyn++; - goto dropwithreset; + goto maybedropwithreset; } goto drop; } @@ -999,7 +995,7 @@ findpcb: 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,16 +1013,22 @@ findpcb: * 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))) + if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) || + IN_MULTICAST(ntohl(ip->ip_src.s_addr)) || + ip->ip_src.s_addr == htonl(INADDR_BROADCAST)) goto drop; #ifdef INET6 if (isipv6) { @@ -1187,7 +1189,7 @@ findpcb: 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 +1531,7 @@ trimthenstep6: * 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 +2194,7 @@ dropafterack: 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 +2205,17 @@ dropafterack: (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 +2230,14 @@ dropwithreset: 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)) || + ip->ip_src.s_addr == htonl(INADDR_BROADCAST)) goto drop; /* IPv6 anycast check is done at tcp6_input() */ #ifdef TCPDEBUG diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c index 2a847e6..b802880 100644 --- a/sys/netinet/tcp_reass.c +++ b/sys/netinet/tcp_reass.c @@ -615,10 +615,6 @@ findpcb: break; } } -#ifdef ICMP_BANDLIM - if (badport_bandlim(1) < 0) - goto drop; -#endif if (blackhole) { switch (blackhole) { case 1: @@ -631,11 +627,11 @@ findpcb: 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 @@ findpcb: */ if (thflags & TH_ACK) { tcpstat.tcps_badsyn++; - goto dropwithreset; + goto maybedropwithreset; } goto drop; } @@ -772,7 +768,7 @@ findpcb: */ if (thflags & TH_ACK) { tcpstat.tcps_badsyn++; - goto dropwithreset; + goto maybedropwithreset; } goto drop; } @@ -999,7 +995,7 @@ findpcb: 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,16 +1013,22 @@ findpcb: * 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))) + if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) || + IN_MULTICAST(ntohl(ip->ip_src.s_addr)) || + ip->ip_src.s_addr == htonl(INADDR_BROADCAST)) goto drop; #ifdef INET6 if (isipv6) { @@ -1187,7 +1189,7 @@ findpcb: 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 +1531,7 @@ trimthenstep6: * 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 +2194,7 @@ dropafterack: 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 +2205,17 @@ dropafterack: (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 +2230,14 @@ dropwithreset: 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)) || + ip->ip_src.s_addr == htonl(INADDR_BROADCAST)) goto drop; /* IPv6 anycast check is done at tcp6_input() */ #ifdef TCPDEBUG |