From owner-freebsd-hackers Fri Sep 27 10:47:30 1996 Return-Path: owner-hackers Received: (from root@localhost) by freefall.freebsd.org (8.7.5/8.7.3) id KAA12438 for hackers-outgoing; Fri, 27 Sep 1996 10:47:30 -0700 (PDT) Received: from dream.demos.su (dream.demos.su [194.87.1.2]) by freefall.freebsd.org (8.7.5/8.7.3) with SMTP id KAA12392 for ; Fri, 27 Sep 1996 10:47:27 -0700 (PDT) Received: by dream.demos.su id VAA00421; (8.6.12/D) Fri, 27 Sep 1996 21:47:22 +0400 To: hackers@freebsd.org Message-ID: Organization: Demos, Moscow, Russia Date: Fri, 27 Sep 1996 21:47:22 +0400 (MSD) X-Mailer: Mail/@ [v2.40 FreeBSD] From: apg@demos.net (Paul Antonov) X-NCC-RegID: su.demos Subject: patch against SYN floods (RED impl.) Lines: 82 MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Sender: owner-hackers@freebsd.org X-Loop: FreeBSD.org Precedence: bulk Here's my quick patch for 2.1.0 kernel (although it will fit for 2.1.5 either) implementing Random Early Drop for tcp listen queues. I've tested in on SYN attacks with over 1000pps rate, and it works reasonably well. *** tcp_input.c.orig Fri Sep 27 14:53:03 1996 --- tcp_input.c Fri Sep 27 21:35:32 1996 *************** *** 396,405 **** } #endif if (so->so_options & SO_ACCEPTCONN) { ! register struct tcpcb *tp0 = tp; ! so = sonewconn(so, 0); ! if (so == 0) ! goto drop; /* * This is ugly, but .... * --- 396,412 ---- } #endif if (so->so_options & SO_ACCEPTCONN) { ! register struct tcpcb *tp0 = tp; ! register struct socket *so0 = so; ! void tcp_sodrop(); ! ! so = sonewconn(so0, 0); ! if (so == 0) { ! tcp_sodrop(so0, ti); ! so = sonewconn(so0, 0); ! if (so == 0) ! goto drop; ! } /* * This is ugly, but .... * *************** *** 1654,1659 **** --- 1661,1699 ---- (void) soabort(so); return; #ifndef TUBA_INCLUDE + } + + /* + * Simple RED (Random Early Drop) implementation against SYN floods. + */ + void + tcp_sodrop(so, ti) + struct socket *so; + struct tcpiphdr *ti; + { + extern struct timeval time; + struct tcpcb *tp; + struct inpcb *inp; + int rnd; + + /* pseudo-random function */ + rnd = (unsigned int) (ti->ti_seq + time.tv_usec / 33) % + so->so_q0len; + for (inp = tcb.lh_first; inp; inp = inp->inp_list.le_next) { + tp = intotcpcb(inp); + if (!tp || inp->inp_lport != ti->ti_dport) + continue; + rnd--; + if (tp->t_state != TCPS_SYN_RECEIVED) + continue; + if (rnd <= 0) { + tp->t_timer[TCPT_KEEP] = 0; + (void) tcp_usrreq(tp->t_inpcb->inp_socket, + PRU_SLOWTIMO, (struct mbuf *)0, + (struct mbuf *) TCPT_KEEP, (struct mbuf *)0); + return; + } + } } void ------- -- Paul