Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 14 May 1999 13:36:36 -0400 (EDT)
From:      Seth <seth@freebie.dp.ny.frb.org>
To:        freebsd-stable@freebsd.org
Cc:        security@freebsd.org
Subject:   SYN floods against FreeBSD (fwd)
Message-ID:  <Pine.BSF.4.10.9905141335160.22662-200000@freebie.dp.ny.frb.org>

next in thread | raw e-mail | index | archive | help
  This message is in MIME format.  The first part should be readable text,
  while the remaining parts are likely unreadable without MIME-aware tools.
  Send mail to mime@docserver.cac.washington.edu for more info.

--Boundary_(ID_Gb/ZMISfT+tnDS1nELJmmQ)
Content-Type: TEXT/PLAIN; CHARSET=US-ASCII
Content-ID: <Pine.BSF.4.10.9905141335162.22662@freebie.dp.ny.frb.org>

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

---------- 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




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.10.9905141335160.22662-200000>