summaryrefslogtreecommitdiffstats
path: root/sys/netinet/tcp_syncache.c
diff options
context:
space:
mode:
authorsilby <silby@FreeBSD.org>2003-02-23 19:04:23 +0000
committersilby <silby@FreeBSD.org>2003-02-23 19:04:23 +0000
commit2f99c6cb310d3987a93a6b2c1a79ef8dcd4cf940 (patch)
tree89ee8b8f945fc628b80086163f4cfef9c3ca006e /sys/netinet/tcp_syncache.c
parent479f59745501b273454b80ecb51657ed230bb295 (diff)
downloadFreeBSD-src-2f99c6cb310d3987a93a6b2c1a79ef8dcd4cf940.zip
FreeBSD-src-2f99c6cb310d3987a93a6b2c1a79ef8dcd4cf940.tar.gz
Improve the security and performance of syncookies:
Security improvements: - Increase the size of each syncookie secret from 32 to 128 bits in order to make brute force attacks on the secrets much more difficult. - Always return the lowest order dword from the MD5 hash; this allows us to expose 2 more bits of the cookie and makes ACK floods which seek to guess the cookie value more difficult. Performance improvements: - Increase the lifetime of each syncookie from 4 seconds to 16 seconds. This increases the usefulness of syncookies during an attack. - From Yahoo!: Reduce the number of calls to MD5Update; this results in a ~17% increase in cookie generation time here. Reviewed by: hsu, jayanth, jlemon, nectar MFC After: 15 seconds
Diffstat (limited to 'sys/netinet/tcp_syncache.c')
-rw-r--r--sys/netinet/tcp_syncache.c73
1 files changed, 47 insertions, 26 deletions
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index a8b031b..7c76c56 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -1235,22 +1235,20 @@ syncache_respond(sc, m)
/*
* The values below are chosen to minimize the size of the tcp_secret
- * table, as well as providing roughly a 4 second lifetime for the cookie.
+ * table, as well as providing roughly a 16 second lifetime for the cookie.
*/
-#define SYNCOOKIE_HASHSHIFT 2 /* log2(# of 32bit words from hash) */
-#define SYNCOOKIE_WNDBITS 7 /* exposed bits for window indexing */
-#define SYNCOOKIE_TIMESHIFT 5 /* scale ticks to window time units */
+#define SYNCOOKIE_WNDBITS 5 /* exposed bits for window indexing */
+#define SYNCOOKIE_TIMESHIFT 1 /* scale ticks to window time units */
-#define SYNCOOKIE_HASHMASK ((1 << SYNCOOKIE_HASHSHIFT) - 1)
#define SYNCOOKIE_WNDMASK ((1 << SYNCOOKIE_WNDBITS) - 1)
-#define SYNCOOKIE_NSECRETS (1 << (SYNCOOKIE_WNDBITS - SYNCOOKIE_HASHSHIFT))
+#define SYNCOOKIE_NSECRETS (1 << SYNCOOKIE_WNDBITS)
#define SYNCOOKIE_TIMEOUT \
(hz * (1 << SYNCOOKIE_WNDBITS) / (1 << SYNCOOKIE_TIMESHIFT))
#define SYNCOOKIE_DATAMASK ((3 << SYNCOOKIE_WNDBITS) | SYNCOOKIE_WNDMASK)
static struct {
- u_int32_t ts_secbits;
+ u_int32_t ts_secbits[4];
u_int ts_expire;
} tcp_secret[SYNCOOKIE_NSECRETS];
@@ -1260,6 +1258,16 @@ static MD5_CTX syn_ctx;
#define MD5Add(v) MD5Update(&syn_ctx, (u_char *)&v, sizeof(v))
+struct md5_add {
+ u_int32_t laddr, faddr;
+ u_int32_t secbits[4];
+ u_int16_t lport, fport;
+};
+
+#ifdef CTASSERT
+CTASSERT(sizeof(struct md5_add) == 28);
+#endif
+
/*
* Consider the problem of a recreated (and retransmitted) cookie. If the
* original SYN was accepted, the connection is established. The second
@@ -1275,35 +1283,42 @@ syncookie_generate(struct syncache *sc)
{
u_int32_t md5_buffer[4];
u_int32_t data;
- int wnd, idx;
+ int idx, i;
+ struct md5_add add;
- wnd = ((ticks << SYNCOOKIE_TIMESHIFT) / hz) & SYNCOOKIE_WNDMASK;
- idx = wnd >> SYNCOOKIE_HASHSHIFT;
+ idx = ((ticks << SYNCOOKIE_TIMESHIFT) / hz) & SYNCOOKIE_WNDMASK;
if (tcp_secret[idx].ts_expire < ticks) {
- tcp_secret[idx].ts_secbits = arc4random();
+ for (i = 0; i < 4; i++)
+ tcp_secret[idx].ts_secbits[i] = arc4random();
tcp_secret[idx].ts_expire = ticks + SYNCOOKIE_TIMEOUT;
}
for (data = sizeof(tcp_msstab) / sizeof(int) - 1; data > 0; data--)
if (tcp_msstab[data] <= sc->sc_peer_mss)
break;
- data = (data << SYNCOOKIE_WNDBITS) | wnd;
+ data = (data << SYNCOOKIE_WNDBITS) | idx;
data ^= sc->sc_irs; /* peer's iss */
MD5Init(&syn_ctx);
#ifdef INET6
if (sc->sc_inc.inc_isipv6) {
MD5Add(sc->sc_inc.inc6_laddr);
MD5Add(sc->sc_inc.inc6_faddr);
+ add.laddr = 0;
+ add.faddr = 0;
} else
#endif
{
- MD5Add(sc->sc_inc.inc_laddr);
- MD5Add(sc->sc_inc.inc_faddr);
+ add.laddr = sc->sc_inc.inc_laddr.s_addr;
+ add.faddr = sc->sc_inc.inc_faddr.s_addr;
}
- MD5Add(sc->sc_inc.inc_lport);
- MD5Add(sc->sc_inc.inc_fport);
- MD5Add(tcp_secret[idx].ts_secbits);
+ add.lport = sc->sc_inc.inc_lport;
+ add.fport = sc->sc_inc.inc_fport;
+ add.secbits[0] = tcp_secret[idx].ts_secbits[0];
+ add.secbits[1] = tcp_secret[idx].ts_secbits[1];
+ add.secbits[2] = tcp_secret[idx].ts_secbits[2];
+ add.secbits[3] = tcp_secret[idx].ts_secbits[3];
+ MD5Add(add);
MD5Final((u_char *)&md5_buffer, &syn_ctx);
- data ^= (md5_buffer[wnd & SYNCOOKIE_HASHMASK] & ~SYNCOOKIE_WNDMASK);
+ data ^= (md5_buffer[0] & ~SYNCOOKIE_WNDMASK);
return (data);
}
@@ -1317,10 +1332,10 @@ syncookie_lookup(inc, th, so)
struct syncache *sc;
u_int32_t data;
int wnd, idx;
+ struct md5_add add;
data = (th->th_ack - 1) ^ (th->th_seq - 1); /* remove ISS */
- wnd = data & SYNCOOKIE_WNDMASK;
- idx = wnd >> SYNCOOKIE_HASHSHIFT;
+ idx = data & SYNCOOKIE_WNDMASK;
if (tcp_secret[idx].ts_expire < ticks ||
sototcpcb(so)->ts_recent + SYNCOOKIE_TIMEOUT < ticks)
return (NULL);
@@ -1329,17 +1344,23 @@ syncookie_lookup(inc, th, so)
if (inc->inc_isipv6) {
MD5Add(inc->inc6_laddr);
MD5Add(inc->inc6_faddr);
+ add.laddr = 0;
+ add.faddr = 0;
} else
#endif
{
- MD5Add(inc->inc_laddr);
- MD5Add(inc->inc_faddr);
+ add.laddr = inc->inc_laddr.s_addr;
+ add.faddr = inc->inc_faddr.s_addr;
}
- MD5Add(inc->inc_lport);
- MD5Add(inc->inc_fport);
- MD5Add(tcp_secret[idx].ts_secbits);
+ add.lport = inc->inc_lport;
+ add.fport = inc->inc_fport;
+ add.secbits[0] = tcp_secret[idx].ts_secbits[0];
+ add.secbits[1] = tcp_secret[idx].ts_secbits[1];
+ add.secbits[2] = tcp_secret[idx].ts_secbits[2];
+ add.secbits[3] = tcp_secret[idx].ts_secbits[3];
+ MD5Add(add);
MD5Final((u_char *)&md5_buffer, &syn_ctx);
- data ^= md5_buffer[wnd & SYNCOOKIE_HASHMASK];
+ data ^= md5_buffer[0];
if ((data & ~SYNCOOKIE_DATAMASK) != 0)
return (NULL);
data = data >> SYNCOOKIE_WNDBITS;
OpenPOWER on IntegriCloud