From owner-freebsd-net@FreeBSD.ORG Mon Jan 23 21:17:11 2012 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2E64E1065673 for ; Mon, 23 Jan 2012 21:17:11 +0000 (UTC) (envelope-from andre@freebsd.org) Received: from c00l3r.networx.ch (c00l3r.networx.ch [62.48.2.2]) by mx1.freebsd.org (Postfix) with ESMTP id 88CF08FC08 for ; Mon, 23 Jan 2012 21:17:10 +0000 (UTC) Received: (qmail 8815 invoked from network); 23 Jan 2012 19:39:03 -0000 Received: from c00l3r.networx.ch (HELO [127.0.0.1]) ([62.48.2.2]) (envelope-sender ) by c00l3r.networx.ch (qmail-ldap-1.03) with SMTP for ; 23 Jan 2012 19:39:03 -0000 Message-ID: <4F1DCE54.8060107@freebsd.org> Date: Mon, 23 Jan 2012 22:17:08 +0100 From: Andre Oppermann User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:9.0) Gecko/20111222 Thunderbird/9.0.1 MIME-Version: 1.0 To: Nikolay Denev References: <4F131A7D.4020006@zonov.org> <733BE6AF-33E0-4C16-A222-B5F5D0519194@gmail.com> <12379405.15603.1326656127893.JavaMail.mobile-sync@vbzh28> <3008402354236887854@unknownmsgid> <7D135FA9-6503-4263-AE55-5C80F94CDF5A@gmail.com> In-Reply-To: Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 8bit Cc: freebsd-net@freebsd.org Subject: Re: ICMP attacks against TCP and PMTUD X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 23 Jan 2012 21:17:11 -0000 On 23.01.2012 16:01, Nikolay Denev wrote: > > On Jan 20, 2012, at 10:32 AM, Nikolay Denev wrote: > >> On Jan 15, 2012, at 9:52 PM, Nikolay Denev wrote: >> >>> On 15.01.2012, at 21:35, Andrey Zonov wrote: >>> >>>> This helped me: >>>> /boot/loader.conf >>>> net.inet.tcp.hostcache.hashsizee536 >>>> net.inet.tcp.hostcache.cachelimit66080 >>>> >>>> Actually, this is a workaround. As I remember, real problem is in >>>> tcp_ctlinput(), it could not update MTU for destination IP if hostcache >>>> allocation fails. tcp_hc_updatemtu() should returns NULL if >>>> tcp_hc_insert() returns NULL and tcp_ctlinput() should check this case >>>> and sets updated MTU for this particular connection if >>>> tcp_hc_updatemtu() fails. Otherwise we've got infinite loop in MTU >>>> discovery. >>>> >>>> >>>> On 15.01.2012 22:59, Nikolay Denev wrote: >>>>> >>>>> % uptime >>>>> 7:57PM up 608 days, 4:06, 1 user, load averages: 0.30, 0.21, 0.17 >>>>> >>>>> % vmstat -z|grep hostcache >>>>> hostcache: 136, 15372, 15136, 236, 44946965, 10972760 >>>>> >>>>> >>>>> Hmm… probably I should increase this…. >>>>> >>>> >>>> -- >>>> Andrey Zonov >>> >>> Thanks, I will test this asap! >>> >>> Regards, >>> Nikolay >> >> I've upgraded from 7.3-STABLE to 8.2-STABLE and bumped significantly the hostcache tunables. >> So far so good, I'll report back if I see similar traffic spikes. >> > > Seems like I have been wrong about these traffic spikes being attacks, and > actually the problem seems to be the pmtu infinite loop Andrey described. > I'm now running 8.2-STABLE with hostcache significantly bumped and regularly > have more than 20K hostcache entries, which was more than the default limit of 15K I was running with before. The bug is real. Please try the attached patch to fix the issue for IPv4. It's against current but should apply to 8 or 9 as well. -- Andre http://people.freebsd.org/~andre/tcp_subr.c-pmtud-20120123.diff Index: netinet/tcp_subr.c =================================================================== --- netinet/tcp_subr.c (revision 230489) +++ netinet/tcp_subr.c (working copy) @@ -1410,9 +1410,11 @@ */ if (mtu <= tcp_maxmtu(&inc, NULL)) tcp_hc_updatemtu(&inc, mtu); - } - - inp = (*notify)(inp, inetctlerrmap[cmd]); + /* XXXAO: Slighly hackish. */ + inp = (*notify)(inp, mtu); + } else + inp = (*notify)(inp, + inetctlerrmap[cmd]); } } if (inp != NULL) @@ -1656,12 +1658,15 @@ * based on the new value in the route. Also nudge TCP to send something, * since we know the packet we just sent was dropped. * This duplicates some code in the tcp_mss() function in tcp_input.c. + * + * XXXAO: Slight abuse of 'errno'. */ struct inpcb * tcp_mtudisc(struct inpcb *inp, int errno) { struct tcpcb *tp; struct socket *so; + int mtu; INP_WLOCK_ASSERT(inp); if ((inp->inp_flags & INP_TIMEWAIT) || @@ -1671,7 +1676,12 @@ tp = intotcpcb(inp); KASSERT(tp != NULL, ("tcp_mtudisc: tp == NULL")); - tcp_mss_update(tp, -1, NULL, NULL); + /* Extract the MTU from errno for IPv4. */ + if (errno > PRC_NCMDS) + mtu = errno; + else + mtu = -1; + tcp_mss_update(tp, mtu, NULL, NULL); so = inp->inp_socket; SOCKBUF_LOCK(&so->so_snd);