netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] tcp: syncookies: reduce cookie lifetime to 128 seconds
@ 2013-08-25 17:54 Florian Westphal
  2013-08-25 17:54 ` [PATCH 2/2] tcp: syncookies: reduce mss table to four values Florian Westphal
  2013-08-28 22:20 ` [PATCH 1/2] tcp: syncookies: reduce cookie lifetime to 128 seconds David Miller
  0 siblings, 2 replies; 4+ messages in thread
From: Florian Westphal @ 2013-08-25 17:54 UTC (permalink / raw)
  To: netdev; +Cc: jbohac, Florian Westphal

We currently accept cookies that were created less than 4 minutes ago
(ie, cookies with counter delta 0-3).  Combined with the 8 mss table
values, this yields 32 possible values (out of 2**32) that will be valid.

Reducing the lifetime to < 2 minutes halves the guessing chance while
still providing a large enough period (possible cookies are
only validated if last synqueue overflow was less than 3 seconds ago).

While at it, get rid of jiffies value -- they overflow too quickly on
32 bit platforms.

getnstimeofday is used to create a counter that increments every 64s.

Reported-by: Jakob Lell <jakob@jakoblell.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/net/tcp.h     | 12 ++++++++++++
 net/ipv4/syncookies.c | 32 ++++++++++----------------------
 net/ipv6/syncookies.c | 25 ++++++++-----------------
 3 files changed, 30 insertions(+), 39 deletions(-)

diff --git a/include/net/tcp.h b/include/net/tcp.h
index 09cb5c1..89368db 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -478,7 +478,19 @@ void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb);
 extern __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS];
 extern struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, 
 				    struct ip_options *opt);
+
+#define MAX_SYNCOOKIE_AGE 2 /* 128 seconds */
+
 #ifdef CONFIG_SYN_COOKIES
+#include <linux/ktime.h>
+
+static inline u32 tcp_cookie_time(void)
+{
+	struct timespec now;
+	getnstimeofday(&now);
+	return now.tv_sec >> 6; /* 64 seconds granularity */
+}
+
 extern __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, 
 				     __u16 *mss);
 #else
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index b05c96e..e2f84eb 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -87,10 +87,8 @@ __u32 cookie_init_timestamp(struct request_sock *req)
 	return ts;
 }
 
-
 static __u32 secure_tcp_syn_cookie(__be32 saddr, __be32 daddr, __be16 sport,
-				   __be16 dport, __u32 sseq, __u32 count,
-				   __u32 data)
+				   __be16 dport, __u32 sseq, __u32 data)
 {
 	/*
 	 * Compute the secure sequence number.
@@ -102,7 +100,7 @@ static __u32 secure_tcp_syn_cookie(__be32 saddr, __be32 daddr, __be16 sport,
 	 * As an extra hack, we add a small "data" value that encodes the
 	 * MSS into the second hash value.
 	 */
-
+	u32 count = tcp_cookie_time();
 	return (cookie_hash(saddr, daddr, sport, dport, 0, 0) +
 		sseq + (count << COOKIEBITS) +
 		((cookie_hash(saddr, daddr, sport, dport, count, 1) + data)
@@ -114,22 +112,21 @@ static __u32 secure_tcp_syn_cookie(__be32 saddr, __be32 daddr, __be16 sport,
  * If the syncookie is bad, the data returned will be out of
  * range.  This must be checked by the caller.
  *
- * The count value used to generate the cookie must be within
- * "maxdiff" if the current (passed-in) "count".  The return value
- * is (__u32)-1 if this test fails.
+ * The count value used to generate the cookie must be less than
+ * MAX_SYNCOOKIE_AGE minutes in the past.
+ * The return value (__u32)-1 if this test fails.
  */
 static __u32 check_tcp_syn_cookie(__u32 cookie, __be32 saddr, __be32 daddr,
-				  __be16 sport, __be16 dport, __u32 sseq,
-				  __u32 count, __u32 maxdiff)
+				  __be16 sport, __be16 dport, __u32 sseq)
 {
-	__u32 diff;
+	u32 diff, count = tcp_cookie_time();
 
 	/* Strip away the layers from the cookie */
 	cookie -= cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq;
 
 	/* Cookie is now reduced to (count * 2^24) ^ (hash % 2^24) */
 	diff = (count - (cookie >> COOKIEBITS)) & ((__u32) - 1 >> COOKIEBITS);
-	if (diff >= maxdiff)
+	if (diff >= MAX_SYNCOOKIE_AGE)
 		return (__u32)-1;
 
 	return (cookie -
@@ -178,17 +175,10 @@ __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp)
 
 	return secure_tcp_syn_cookie(iph->saddr, iph->daddr,
 				     th->source, th->dest, ntohl(th->seq),
-				     jiffies / (HZ * 60), mssind);
+				     mssind);
 }
 
 /*
- * This (misnamed) value is the age of syncookie which is permitted.
- * Its ideal value should be dependent on TCP_TIMEOUT_INIT and
- * sysctl_tcp_retries1. It's a rather complicated formula (exponential
- * backoff) to compute at runtime so it's currently hardcoded here.
- */
-#define COUNTER_TRIES 4
-/*
  * Check if a ack sequence number is a valid syncookie.
  * Return the decoded mss if it is, or 0 if not.
  */
@@ -198,9 +188,7 @@ static inline int cookie_check(struct sk_buff *skb, __u32 cookie)
 	const struct tcphdr *th = tcp_hdr(skb);
 	__u32 seq = ntohl(th->seq) - 1;
 	__u32 mssind = check_tcp_syn_cookie(cookie, iph->saddr, iph->daddr,
-					    th->source, th->dest, seq,
-					    jiffies / (HZ * 60),
-					    COUNTER_TRIES);
+					    th->source, th->dest, seq);
 
 	return mssind < ARRAY_SIZE(msstab) ? msstab[mssind] : 0;
 }
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
index d5dda20..6a6d585 100644
--- a/net/ipv6/syncookies.c
+++ b/net/ipv6/syncookies.c
@@ -18,6 +18,7 @@
 #include <linux/random.h>
 #include <linux/cryptohash.h>
 #include <linux/kernel.h>
+#include <linux/ktime.h>
 #include <net/ipv6.h>
 #include <net/tcp.h>
 
@@ -36,14 +37,6 @@ static __u16 const msstab[] = {
 	9000 - 60,
 };
 
-/*
- * This (misnamed) value is the age of syncookie which is permitted.
- * Its ideal value should be dependent on TCP_TIMEOUT_INIT and
- * sysctl_tcp_retries1. It's a rather complicated formula (exponential
- * backoff) to compute at runtime so it's currently hardcoded here.
- */
-#define COUNTER_TRIES 4
-
 static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,
 					   struct request_sock *req,
 					   struct dst_entry *dst)
@@ -86,8 +79,9 @@ static u32 cookie_hash(const struct in6_addr *saddr, const struct in6_addr *dadd
 static __u32 secure_tcp_syn_cookie(const struct in6_addr *saddr,
 				   const struct in6_addr *daddr,
 				   __be16 sport, __be16 dport, __u32 sseq,
-				   __u32 count, __u32 data)
+				   __u32 data)
 {
+	u32 count = tcp_cookie_time();
 	return (cookie_hash(saddr, daddr, sport, dport, 0, 0) +
 		sseq + (count << COOKIEBITS) +
 		((cookie_hash(saddr, daddr, sport, dport, count, 1) + data)
@@ -96,15 +90,14 @@ static __u32 secure_tcp_syn_cookie(const struct in6_addr *saddr,
 
 static __u32 check_tcp_syn_cookie(__u32 cookie, const struct in6_addr *saddr,
 				  const struct in6_addr *daddr, __be16 sport,
-				  __be16 dport, __u32 sseq, __u32 count,
-				  __u32 maxdiff)
+				  __be16 dport, __u32 sseq)
 {
-	__u32 diff;
+	__u32 diff, count = tcp_cookie_time();
 
 	cookie -= cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq;
 
 	diff = (count - (cookie >> COOKIEBITS)) & ((__u32) -1 >> COOKIEBITS);
-	if (diff >= maxdiff)
+	if (diff >= MAX_SYNCOOKIE_AGE)
 		return (__u32)-1;
 
 	return (cookie -
@@ -130,8 +123,7 @@ __u32 cookie_v6_init_sequence(struct sock *sk, const struct sk_buff *skb, __u16
 	NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SYNCOOKIESSENT);
 
 	return secure_tcp_syn_cookie(&iph->saddr, &iph->daddr, th->source,
-				     th->dest, ntohl(th->seq),
-				     jiffies / (HZ * 60), mssind);
+				     th->dest, ntohl(th->seq), mssind);
 }
 
 static inline int cookie_check(const struct sk_buff *skb, __u32 cookie)
@@ -140,8 +132,7 @@ static inline int cookie_check(const struct sk_buff *skb, __u32 cookie)
 	const struct tcphdr *th = tcp_hdr(skb);
 	__u32 seq = ntohl(th->seq) - 1;
 	__u32 mssind = check_tcp_syn_cookie(cookie, &iph->saddr, &iph->daddr,
-					    th->source, th->dest, seq,
-					    jiffies / (HZ * 60), COUNTER_TRIES);
+					    th->source, th->dest, seq);
 
 	return mssind < ARRAY_SIZE(msstab) ? msstab[mssind] : 0;
 }
-- 
1.8.1.5

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/2] tcp: syncookies: reduce mss table to four values
  2013-08-25 17:54 [PATCH 1/2] tcp: syncookies: reduce cookie lifetime to 128 seconds Florian Westphal
@ 2013-08-25 17:54 ` Florian Westphal
  2013-08-28 22:22   ` David Miller
  2013-08-28 22:20 ` [PATCH 1/2] tcp: syncookies: reduce cookie lifetime to 128 seconds David Miller
  1 sibling, 1 reply; 4+ messages in thread
From: Florian Westphal @ 2013-08-25 17:54 UTC (permalink / raw)
  To: netdev; +Cc: jbohac, Florian Westphal

Halve mss table size to make blind cookie guessing more difficult.
This is sad since the tables were already small, but there
is little alternative except perhaps adding more precise mss information
in the tcp timestamp.  Timestamps are unfortunately not ubiquitous.

Guessing all possible cookie values still has 8-in 2**32 chance.

Reported-by: Jakob Lell <jakob@jakoblell.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
---
 Another argument AGAINST this patch is that if 16-in 2**32 is
 too easy then 8-in-2**32 will be doable, too.

 net/ipv4/syncookies.c | 6 +-----
 net/ipv6/syncookies.c | 4 ----
 2 files changed, 1 insertion(+), 9 deletions(-)

diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index e2f84eb..fd52401 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -143,14 +143,10 @@ static __u32 check_tcp_syn_cookie(__u32 cookie, __be32 saddr, __be32 daddr,
  * Table must be sorted.
  */
 static __u16 const msstab[] = {
-	64,
-	512,
 	536,
-	1024,
+	1200,
 	1440,
 	1460,
-	4312,
-	8960,
 };
 
 /*
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
index 6a6d585..cc4513b 100644
--- a/net/ipv6/syncookies.c
+++ b/net/ipv6/syncookies.c
@@ -27,13 +27,9 @@
 
 /* Table must be sorted. */
 static __u16 const msstab[] = {
-	64,
-	512,
-	536,
 	1280 - 60,
 	1480 - 60,
 	1500 - 60,
-	4460 - 60,
 	9000 - 60,
 };
 
-- 
1.8.1.5

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/2] tcp: syncookies: reduce cookie lifetime to 128 seconds
  2013-08-25 17:54 [PATCH 1/2] tcp: syncookies: reduce cookie lifetime to 128 seconds Florian Westphal
  2013-08-25 17:54 ` [PATCH 2/2] tcp: syncookies: reduce mss table to four values Florian Westphal
@ 2013-08-28 22:20 ` David Miller
  1 sibling, 0 replies; 4+ messages in thread
From: David Miller @ 2013-08-28 22:20 UTC (permalink / raw)
  To: fw; +Cc: netdev, jbohac

From: Florian Westphal <fw@strlen.de>
Date: Sun, 25 Aug 2013 19:54:01 +0200

> We currently accept cookies that were created less than 4 minutes ago
> (ie, cookies with counter delta 0-3).  Combined with the 8 mss table
> values, this yields 32 possible values (out of 2**32) that will be valid.
> 
> Reducing the lifetime to < 2 minutes halves the guessing chance while
> still providing a large enough period (possible cookies are
> only validated if last synqueue overflow was less than 3 seconds ago).
> 
> While at it, get rid of jiffies value -- they overflow too quickly on
> 32 bit platforms.
> 
> getnstimeofday is used to create a counter that increments every 64s.
> 
> Reported-by: Jakob Lell <jakob@jakoblell.com>
> Signed-off-by: Florian Westphal <fw@strlen.de>

Moving from jiffies as a time seed to getnstimeofday() obviously will
have some performance impact, can you talk a little bit about that?


> +#define MAX_SYNCOOKIE_AGE 2 /* 128 seconds */

I'm sure you understand how 2 translates into 128 seconds in this syncookie
code, but I sure don't and the next person who reads this patch or this
code after I apply it may not either.

Could you in some way expose the calculation?  Thanks.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 2/2] tcp: syncookies: reduce mss table to four values
  2013-08-25 17:54 ` [PATCH 2/2] tcp: syncookies: reduce mss table to four values Florian Westphal
@ 2013-08-28 22:22   ` David Miller
  0 siblings, 0 replies; 4+ messages in thread
From: David Miller @ 2013-08-28 22:22 UTC (permalink / raw)
  To: fw; +Cc: netdev, jbohac

From: Florian Westphal <fw@strlen.de>
Date: Sun, 25 Aug 2013 19:54:02 +0200

> Halve mss table size to make blind cookie guessing more difficult.
> This is sad since the tables were already small, but there
> is little alternative except perhaps adding more precise mss information
> in the tcp timestamp.  Timestamps are unfortunately not ubiquitous.
> 
> Guessing all possible cookie values still has 8-in 2**32 chance.
> 
> Reported-by: Jakob Lell <jakob@jakoblell.com>
> Signed-off-by: Florian Westphal <fw@strlen.de>

It seems you've decided to retain different sets of entries in these
two tables.

It is not at all obvious to me if this was intentional, and if so
then why such a choice was made.

Please clarify this.

Thank you.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2013-08-28 22:22 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-08-25 17:54 [PATCH 1/2] tcp: syncookies: reduce cookie lifetime to 128 seconds Florian Westphal
2013-08-25 17:54 ` [PATCH 2/2] tcp: syncookies: reduce mss table to four values Florian Westphal
2013-08-28 22:22   ` David Miller
2013-08-28 22:20 ` [PATCH 1/2] tcp: syncookies: reduce cookie lifetime to 128 seconds David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).