Date: Sat, 9 Nov 1996 15:13:58 -0700 (MST) From: Marc Slemko <marcs@znep.com> To: hackers@freebsd.org Subject: TCP SYN attack prevention Message-ID: <Pine.BSF.3.95.961109141806.23409C-100000@alive.ampr.ab.ca>
next in thread | raw e-mail | index | archive | help
I'm having a little bit of trouble understanding exactly how the change in -current to help protect against TCP SYN attacks works. The relevant function from uipc_socket2.c: struct socket * sodropablereq(head) register struct socket *head; { register struct socket *so; unsigned int i, j, qlen; static int rnd; static long old_mono_secs; static unsigned int cur_cnt, old_cnt; if ((i = (mono_time.tv_sec - old_mono_secs)) != 0) { old_mono_secs = mono_time.tv_sec; old_cnt = cur_cnt / i; cur_cnt = 0; } so = TAILQ_FIRST(&head->so_incomp); if (!so) return (so); qlen = head->so_incqlen; if (++cur_cnt > qlen || old_cnt > qlen) { rnd = (314159 * rnd + 66329) & 0xffff; j = ((qlen + 1) * rnd) >> 16; while (j-- && so) so = TAILQ_NEXT(so, so_list); } return (so); } How I read the code is that cur_cnt will be the count of the number of times this routine has been called during second; at high rates of attack, this will be approximately equal to the total number of SYN packets received. old_cnt looks like it is the average number of times per second that sodropablereq has been called in the previous one or more (i) seconds; under high rates of attack, i will be 1. TAILQ_FIRST(&head->so_incomp) will be the oldest incomplete connection. qlen will be the current number of incomplete pending connections. Where I get a bit confused is at the (++cur_cnt > qlen || old_cnt > qlen) conditional. I am reading this as saying that the body of the if is only execured if the number of packets so far this second is greater than the length of the queue, or the number of packets per second in the last i second(s) is greater than the length of the queue. That makes no sense at all to me. If somaxconn is set to something moderate like 512 (and the application calls listen() in the right manner to be able to use all of that) then it would take an extremely high rate of attack to enable the random drop. If this conditional isn't enabled, then it just does oldest early drop. Is this code intented to only switch to random early drop from oldest early drop when the rate of attack is extremely high? If so, I'm not sure I quite see the logic behind the current condition. BTW, I notice this code is still disabled in tcp_input.c behind a TCPSYNRED ifdef. From my reading of it, that essentially removes most of the protection from -current and just does the standard BSD thing of dropping the new reqeust. This should probably be fixed up before 2.2; actually, it probably would be a very good thing to have (even if it was just oldest early drop) in 2.1.6. Oh, now I remember, -stable doesn't use the 4.4 queue macros so you can't find the oldest pending connection cleanly. Random drop would still work though.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.3.95.961109141806.23409C-100000>