Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 14 May 1999 12:57:31 -0700 (PDT)
From:      Matthew Dillon <dillon@apollo.backplane.com>
To:        freebsd-stable@FreeBSD.ORG, security@FreeBSD.ORG
Subject:   Re: SYN floods against FreeBSD (fwd)
Message-ID:  <199905141957.MAA03794@apollo.backplane.com>
References:   <Pine.BSF.4.10.9905141335160.22662-200000@freebie.dp.ny.frb.org>

next in thread | previous in thread | raw e-mail | index | archive | help
:Don't know whether this hit the list yet, so I'm passing along.  Apologies
:if it's old news.
:
:Note: I am not the author of the message; I'm just reposting it here.
:Please remove my address from any replies to the -stable mailing list.
:Thanks.
:
:SB

    Addressing the bugtrack posting and not the messenger :-)

    I think this patch is a bad idea. 

    I recall fixing a bug in the route table code that could cause a
    double-free panic, but I do not remember if it was before or after
    the 3.1 release.  In anycase, a double-free panic has nothing to do
    with a high volume of SYN traffic apart from ticking some new bug.
    The appropriate fix is *not* to try to limit the sync traffic but
    instead to track down, locate, and fix the double-free.

    I will go over the route table code to see if the softclock interrupt
    is being properly masked while the route table is being manipulated.

					    -Matt
    
:---------- Forwarded message ----------
:Date: Thu, 13 May 1999 11:35:43 -0700
:From: Richard Steenbergen <humble@LIGHTNING.NET>
:To: BUGTRAQ@netspace.org
:Subject: SYN floods against FreeBSD
:
:Here's a quickie for the people who have been plagued with high bandwidth
:syn flood attacks, a kernel patch for FreeBSD 3.1-STABLE which rate limits
:SYN processing. Its messy but functional and I don't have time to make it
:better (thats the fbsd developers job, not mine :P), cd /usr/src/sys,
:patch < synlim, add "options SYN_RATELIM" (I highly recommend ICMP_BANDLIM
:as well) to your kernel, recompile, and sysctl net.inet.tcp.synlim will be
:available (default to 100). This is the maximium number of SYNs per second
:that will be processed, the rest will be silently discarded. On my test
:system (P2 450 running 3.1-stable being hit w/15,000 packets per sec),
:this has successfully brought CPU usage from 100% to ~20% (against an open
:port which is replying with unacknowledged ACKs).
:
:Which brings us to the more sticky topic of kernel panics when under SYN
:flood (which I believe to be the cause of some earlier posts from certain
:people at Exodus Communications *cough*). Lord knows I found enough of
:them when doing this testing, but the one that seems to be the biggie for
:crashing when under syn flood is as follows (heh just turned off the
:synlim and panic'd within 8 seconds while writing this):
:
:panic: free: multiple frees
:(kgdb) bt
:#0  boot (howto=256) at ../../kern/kern_shutdown.c:285
:#1  0xc0138c09 in panic (fmt=0xc02192b7 "free: multiple frees")
:    at ../../kern/kern_shutdown.c:446
:#2  0xc0135aaf in free (addr=0xc0cdd600, type=0xc0239330)
:    at ../../kern/kern_malloc.c:333
:#3  0xc01768f4 in ifafree (ifa=0xc0cdd600) at ../../net/route.c:262
:#4  0xc0176876 in rtfree (rt=0xc34ce700) at ../../net/route.c:236
:#5  0xc0176c84 in rtrequest (req=2, dst=0xc34cbac0, gateway=0xc34cbad0,
:    netmask=0x0, flags=393223, ret_nrt=0x0) at ../../net/route.c:536
:#6  0xc017b34d in in_rtqkill (rn=0xc34ce700, rock=0xc0231610)
:    at ../../netinet/in_rmx.c:242
:#7  0xc0176064 in rn_walktree (h=0xc0cd9e00, f=0xc017b2fc <in_rtqkill>,
:    w=0xc0231610) at ../../net/radix.c:956
:#8  0xc017b3ec in in_rtqtimo (rock=0xc0cd9e00) at ../../netinet/in_rmx.c:283
:#9  0xc013d19b in softclock () at ../../kern/kern_timeout.c:124
:
:Which after a quick examination seems to be a perioditic routing table
:cleanup. It seems that in_rtqtimo is scheduled to run every
:net.inet.ip.rtexpire seconds (which is dynamicly adjusted and can never go
:lower then net.inet.ip.rtminexpire). When the system is under heavy load
:from processing lots of small packets (they don't even have to be SYNs,
:anything which can get routed will do the trick, though the packet kiddies
:would get very little gain from just sending an ip header since its going
:to be padded to 64 bytes for the eth frame anyhow), this route cleanup
:code will go wacking at routes it shouldn't and free some memory twice. In
:the course of testing I've gotten my rtq_reallyold to -3 and seen lots of
:"tvotohz: negative time difference -2 sec 0 usec". Perhaps someone with
:free time or more specific knowledge of this area would like to FIX IT? =)
:
:Perhaps when I get more free time I'll test some other *nix's. I would
:really recommend putting all this rate limiting code at an ipfw level.
:
:If you would like to contact me regarding this please use
:humble@quadrunner.com (at least if you want a quick reply), thanks.
:
:--
:Richard Steenbergen <humble@lightning.net> humble@EFNet PGP ID: 0x741D0374
:PGP Key Fingerprint: C6EF EFA0 83B2 071F 1AB6  B879 1F70 4303 741D 0374
:http://users.quadrunner.com/humble
:
:--Boundary_(ID_Gb/ZMISfT+tnDS1nELJmmQ)
:Content-Type: TEXT/PLAIN; NAME=synlim; CHARSET=US-ASCII
:Content-ID: <Pine.LNX.4.10.9905131135430.25123@puffer.quadrunner.com>
:Content-Description: SYN rate limit patch for fbsd 3.1
:Content-Disposition: ATTACHMENT; FILENAME=synlim
:
:*** conf/options.old	Sat May 15 23:08:03 1999
:--- conf/options	Sat May 15 23:40:21 1999
:***************
:*** 68,73 ****
:--- 68,74 ----
:  SYSVSHM		opt_sysvipc.h
:  UCONSOLE
:  ICMP_BANDLIM
:+ SYN_RATELIM
:  
:  # POSIX kernel options
:  P1003_1B	opt_posix.h
:*** netinet/tcp_var.h.old	Sat May 15 23:25:39 1999
:--- netinet/tcp_var.h	Sat May 15 23:45:05 1999
:***************
:*** 40,45 ****
:--- 40,49 ----
:   * Kernel variables for tcp.
:   */
:  
:+ #ifdef KERNEL
:+ #include "opt_syn_ratelim.h"
:+ #endif
:+ 
:  /*
:   * Tcp control block, one per tcp; fields:
:   * Organized for 16 byte cacheline efficiency.
:***************
:*** 305,311 ****
:  #define	TCPCTL_RECVSPACE	9	/* receive buffer space */
:  #define	TCPCTL_KEEPINIT		10	/* receive buffer space */
:  #define	TCPCTL_PCBLIST		11	/* list of all outstanding PCBs */
:! #define TCPCTL_MAXID		12
:  
:  #define TCPCTL_NAMES { \
:  	{ 0, 0 }, \
:--- 309,316 ----
:  #define	TCPCTL_RECVSPACE	9	/* receive buffer space */
:  #define	TCPCTL_KEEPINIT		10	/* receive buffer space */
:  #define	TCPCTL_PCBLIST		11	/* list of all outstanding PCBs */
:! #define TCPCTL_SYNLIM		12	/* Rate limiting of SYNs */
:! #define TCPCTL_MAXID		13
:  
:  #define TCPCTL_NAMES { \
:  	{ 0, 0 }, \
:***************
:*** 320,325 ****
:--- 325,331 ----
:  	{ "recvspace", CTLTYPE_INT }, \
:  	{ "keepinit", CTLTYPE_INT }, \
:  	{ "pcblist", CTLTYPE_STRUCT }, \
:+ 	{ "synlim", CTLTYPE_INT }, \
:  }
:  
:  #ifdef KERNEL
:*** netinet/tcp_input.c.old	Sat May 15 23:08:10 1999
:--- netinet/tcp_input.c		Sun May 16 01:33:51 1999
:***************
:*** 72,77 ****
:--- 72,85 ----
:  static struct	tcpiphdr tcp_saveti;
:  #endif
:  
:+ #ifdef SYN_RATELIM 
:+ static int      synlim = 100;
:+ SYSCTL_INT(_net_inet_tcp, TCPCTL_SYNLIM, synlim, CTLFLAG_RW, &synlim, 0, "");
:+ #else
:+ static int      synlim = -1;
:+ SYSCTL_INT(_net_inet_tcp, TCPCTL_SYNLIM, synlim, CTLFLAG_RD, &synlim, 0, "");
:+ #endif
:+ 
:  static int	tcprexmtthresh = 3;
:  tcp_seq	tcp_iss;
:  tcp_cc	tcp_ccgen;
:***************
:*** 98,104 ****
:  	    struct tcpiphdr *, struct mbuf *));
:  static int	 tcp_reass __P((struct tcpcb *, struct tcpiphdr *, struct mbuf *));
:  static void	 tcp_xmit_timer __P((struct tcpcb *, int));
:! 
:  
:  /*
:   * Insert segment ti into reassembly queue of tcp with
:--- 106,112 ----
:  	    struct tcpiphdr *, struct mbuf *));
:  static int	 tcp_reass __P((struct tcpcb *, struct tcpiphdr *, struct mbuf *));
:  static void	 tcp_xmit_timer __P((struct tcpcb *, int));
:! static int	 syn_ratelim(void);
:  
:  /*
:   * Insert segment ti into reassembly queue of tcp with
:***************
:*** 130,135 ****
:--- 138,183 ----
:  	} \
:  }
:  
:+ #ifdef SYN_RATELIM
:+ int syn_ratelim(void)
:+ {
:+ 	static int lticks;
:+ 	static int lpackets;
:+ 	int dticks;
:+ 
:+ 	/*
:+ 	 * Return ok status if feature disabled or argument out of
:+ 	 * ranage.
:+ 	 */
:+ 
:+ 	if (synlim <= 0)
:+ 		return(0);
:+ 
:+ 	dticks = ticks - lticks;
:+ 
:+ 	/*
:+ 	 * reset stats when cumulative dt exceeds one second.
:+ 	 */
:+ 
:+ 	if ((unsigned int)dticks > hz) {
:+ 		if (lpackets > synlim)
:+ 			printf("syn rate limit reached %d/%d pps\n", lpackets, synlim);
:+ 		lticks = ticks;
:+ 		lpackets = 0;
:+ 	}
:+ 
:+ 	/*
:+ 	 * bump packet count
:+ 	 */
:+ 
:+ 	if (++lpackets > synlim) {
:+ 		return(-1);
:+ 	}
:+ 
:+ 	return(0);
:+ }
:+ #endif
:+ 
:  static int
:  tcp_reass(tp, ti, m)
:  	register struct tcpcb *tp;
:***************
:*** 379,384 ****
:--- 427,438 ----
:  		ip_fw_fwd_addr = NULL;
:  	} else
:  #endif	/* IPFIREWALL_FORWARD */
:+ 
:+ #ifdef SYN_RATELIM
:+ 	if ((tiflags & TH_SYN) && !(tiflags & TH_ACK))
:+ 		if (syn_ratelim() < 0)
:+ 			goto drop;
:+ #endif
:  
:  	inp = in_pcblookup_hash(&tcbinfo, ti->ti_src, ti->ti_sport,
:  	    ti->ti_dst, ti->ti_dport, 1);
:
:--Boundary_(ID_Gb/ZMISfT+tnDS1nELJmmQ)--
:
:
:To Unsubscribe: send mail to majordomo@FreeBSD.org
:with "unsubscribe freebsd-security" in the body of the message
:

					Matthew Dillon 
					<dillon@backplane.com>


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?199905141957.MAA03794>