summaryrefslogtreecommitdiffstats
path: root/sys/netinet/tcp_input.c
diff options
context:
space:
mode:
authorangelos <angelos@openbsd.org>1997-08-09 01:26:00 +0000
committerangelos <angelos@openbsd.org>1997-08-09 01:26:00 +0000
commitbac2006fcf6add909c336ad82b0dec4012758f54 (patch)
treedb94bd0dde9a5d018f44d5486b89850ab29e66d1 /sys/netinet/tcp_input.c
parentClarify a bit. (diff)
downloadwireguard-openbsd-bac2006fcf6add909c336ad82b0dec4012758f54.tar.xz
wireguard-openbsd-bac2006fcf6add909c336ad82b0dec4012758f54.zip
SYN flood protection, by specifying
option TCPCOOKIE in the kernel config file. For very busy servers, consider raising the TCK_NFRIENDS value (it's currenly set to 16). Code originally from Matt Blaze and John Ioannidis.
Diffstat (limited to 'sys/netinet/tcp_input.c')
-rw-r--r--sys/netinet/tcp_input.c153
1 files changed, 151 insertions, 2 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 2dde11271fb..e31c9f7f7e3 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_input.c,v 1.12 1997/07/06 08:04:10 deraadt Exp $ */
+/* $OpenBSD: tcp_input.c,v 1.13 1997/08/09 01:26:00 angelos Exp $ */
/* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */
/*
@@ -62,8 +62,8 @@
#include <netinet/tcpip.h>
#include <netinet/tcp_debug.h>
#include <dev/rndvar.h>
-
#include <machine/stdarg.h>
+#include <sys/md5k.h>
int tcprexmtthresh = 3;
struct tcpiphdr tcp_saveti;
@@ -78,6 +78,123 @@ extern u_long sb_max;
#define TSTMP_LT(a,b) ((int)((a)-(b)) < 0)
#define TSTMP_GEQ(a,b) ((int)((a)-(b)) >= 0)
+#ifdef TCPCOOKIE
+/*
+ * Code originally by Matt Blaze and John Ioannidis. This code implements
+ * a cookie-like extension for TCP. Adapted to OpenBSD by Angelos D.
+ * Keromytis.
+ */
+
+#ifndef TCK_NFRIENDS
+#define TCK_NFRIENDS 16
+#endif /* TCK_NFRIENDS */
+
+static struct in_addr tck_friends[TCK_NFRIENDS];
+static int tck_nfriends = 0;
+static int tck_initialized = 0;
+
+#define TCK_PORT 333 /* Unused port! */
+
+static int
+tck_isafriend(struct in_addr f)
+{
+ register int i;
+
+ for (i = tck_nfriends - 1; i >= 0; i--)
+ if (tck_friends[i].s_addr == f.s_addr)
+ return 1;
+
+ return 0;
+}
+
+static void
+tck_delat(int n)
+{
+ int i;
+
+ if ((n >= tck_nfriends) || (tck_nfriends == 0))
+ return;
+
+ for (i = n+1; i < tck_nfriends ; i++)
+ tck_friends[i - 1] = tck_friends[i];
+
+ tck_nfriends--;
+}
+
+static void
+tck_addfriend(struct in_addr f)
+{
+#ifdef DEBUG_TCPCOOKIE
+ printf("tck_addfriend: 0x%08x\n", ntohl(f.s_addr));
+#endif /* DEBUG_TCPCOOKIE */
+
+ if (tck_isafriend(f))
+ return;
+
+ if (tck_nfriends == TCK_NFRIENDS)
+ tck_delat(0);
+
+ tck_friends[tck_nfriends++] = f;
+}
+
+/*
+ * static void
+ * tck_delfriend(struct in_addr f)
+ * {
+ * int i;
+ *
+ * for (i = tck_nfriends - 1; i >= 0; i--)
+ * if (tck_friends[i].s_addr == f.s_addr)
+ * goto found1;
+ *
+ * return;
+ *
+ * found1:
+ * tck_delat(i);
+ * }
+*/
+
+static u_int32_t
+tck_makecookie(struct in_addr f)
+{
+ static MD5_CTX ctx;
+ u_int8_t buf[16];
+ MD5_CTX ctx2;
+
+ if (tck_initialized == 0) /* This only happens once per reboot */
+ {
+ tck_initialized = 1;
+
+ get_random_bytes((void *) buf, 16);
+
+ MD5Init(&ctx);
+ MD5Update(&ctx, buf, 16);
+ }
+
+ ctx2 = ctx;
+ MD5Update(&ctx2, (void *) &f, sizeof(f));
+ MD5Final(buf, &ctx2); /* This may not be necessary */
+
+ return ((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]);
+}
+
+static int
+tck_chkcookie(struct tcpiphdr *ti)
+{
+#ifdef DEBUG_TCPCOOKIE
+ printf("tck_chkcookie: src = 0x%08x, cookie = 0x%08x, ack = 0x%08x\n", ntohl(ti->ti_src.s_addr), tck_makecookie(ti->ti_src), ti->ti_ack);
+#endif /* DEBUG_TCPCOOKIE */
+
+ if (tck_makecookie(ti->ti_src) == ti->ti_seq) /* seq in host order */
+ {
+ tck_addfriend(ti->ti_src);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+#endif /* TCPCOOKIE */
/*
* Insert segment ti into reassembly queue of tcp with
@@ -394,6 +511,18 @@ tcp_input(m, va_alist)
NTOHS(ti->ti_win);
NTOHS(ti->ti_urp);
+#ifdef TCPCOOKIE
+ /*
+ * If this looks like a cookie response, check it.
+ * If it is, the check routine also adds the source
+ * of the packet to the friends list.
+ */
+
+ if ((tiflags & TH_RST) && (ntohs(ti->ti_dport) == TCK_PORT))
+ if (tck_chkcookie(ti))
+ goto drop; /* RST is no longer needed */
+#endif /* TCPCOOKIE */
+
/*
* Locate pcb for segment.
*/
@@ -636,6 +765,26 @@ findpcb:
goto dropwithreset;
if ((tiflags & TH_SYN) == 0)
goto drop;
+
+#ifdef TCPCOOKIE
+ /*
+ * If source address is on friends list, proceed, otherwise
+ * try to obtain a cookie and drop the frame.
+ */
+
+ if (!tck_isafriend(ti->ti_src))
+ {
+ u_long acookie;
+ acookie = tck_makecookie(ti->ti_src);
+ ti->ti_dport = htons(TCK_PORT);
+ tcp_respond(tp, ti, m, acookie, acookie, TH_ACK);
+ /* destroy temporarily created socket */
+ if (dropsocket)
+ (void) soabort(so);
+ return;
+ }
+#endif /* TCPCOOKIE */
+
/*
* RFC1122 4.2.3.10, p. 104: discard bcast/mcast SYN
* in_broadcast() should never return true on a received