All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] TCP: Add support for TCP Stealth
@ 2014-12-31 21:54 Julian Kirsch
  2015-01-01 15:25 ` Daniel Borkmann
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Julian Kirsch @ 2014-12-31 21:54 UTC (permalink / raw)
  To: netdev; +Cc: Christian Grothoff, Jacob Appelbaum

[-- Attachment #1: Type: text/plain, Size: 2090 bytes --]

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi,

one year ago [0] we tried to convince you to add support for a new
socket option to the linux kernel. Equipped with an improved version of
our patch we're back to accomplish this task today. :-)

TCP Stealth is a modern variant of port knocking which borrows
techniques from network steganography to enable clients to authenticate
themselves towards a server on TCP level. You can find technical details
in an rfc draft we wrote earlier this year [1] and in my master's thesis
[2]. In summary, TCP Stealth derives authentication information from a
pre-shared secret and embeds it into the ISN sent along with the first
SYN from the client.

Our motivation is simple: During this year we gained hard evidence on
secret services actively port scanning the internets followed by
exploitation of your services using 0-day exploits [3, 4]. We don't want
our machines to be turned into relays from where they continue to
cascade their attacks. TCP Stealth makes port scanning more expensive by
a factor of 2^31 (on average).

A copy of this patch as well as patches for several user space
applications can be found on the project's home page [5].

All the best for the upcoming year,
Julian & Christian



[0] https://lkml.org/lkml/2013/12/10/1155
[1] https://datatracker.ietf.org/doc/draft-kirsch-ietf-tcp-stealth/
[2] https://gnunet.org/kirsch2014knock
[3]
http://www.heise.de/ct/artikel/NSA-GCHQ-The-HACIENDA-Program-for-Internet-Colonization-2292681.html
[4]
https://firstlook.org/theintercept/2014/12/13/belgacom-hack-gchq-inside-story/
[5] https://gnunet.org/knock
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQEcBAEBAgAGBQJUpHCvAAoJENwkOWttRRA4g10IALbJZU9/5Gp8tVdpXqbkOIMp
Kz+yOMyYULqYeM8yguSBZjZLbaz/VAS7SNpQxKGU+W0aAXa22FsSfVoUU7wqp3NT
3EGRuPkMaJkQ66IP8MtX+6/hSeWSh78tEaIFWVjyutihPyQGz0LefFc66gm54X4T
s8IYW7jKFhNmmROu9CXLTxq4B5t2v+Evv/qWqotZqR1t3IbIUmZAiKrlkMRd7dtM
SaS5JwFeiObxn+0M/7javQCAhfgPXYEOU0QKAGY55MXcPAner/5PuExIZdOJ41R3
XD9tgoLGhHEiQkxj0/bP2cs3Cl5xfJl9t2iecVfTIR7PytaTJ/kFuE4gNgWEcTA=
=T6/C
-----END PGP SIGNATURE-----

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: tcp_stealth_3.18.diff --]
[-- Type: text/x-patch; name="tcp_stealth_3.18.diff", Size: 19140 bytes --]

Signed-off-by: Julian Kirsch <kirschju@sec.in.tum.de>
diff -Nurp linux-3.18-rc3/include/linux/tcp.h linux-3.18-rc3-knock/include/linux/tcp.h
--- linux-3.18-rc3/include/linux/tcp.h	2014-11-03 00:01:51.000000000 +0100
+++ linux-3.18-rc3-knock/include/linux/tcp.h	2014-11-06 21:26:34.976017001 +0100
@@ -19,6 +19,7 @@
 
 
 #include <linux/skbuff.h>
+#include <linux/cryptohash.h>
 #include <net/sock.h>
 #include <net/inet_connection_sock.h>
 #include <net/inet_timewait_sock.h>
@@ -309,6 +310,21 @@ struct tcp_sock {
 	struct tcp_md5sig_info	__rcu *md5sig_info;
 #endif
 
+#ifdef CONFIG_TCP_STEALTH
+/* Stealth TCP socket configuration */
+	struct {
+		#define TCP_STEALTH_MODE_AUTH		BIT(0)
+		#define TCP_STEALTH_MODE_INTEGRITY	BIT(1)
+		#define TCP_STEALTH_MODE_INTEGRITY_LEN	BIT(2)
+		int mode;
+		u8 secret[MD5_MESSAGE_BYTES];
+		int integrity_len;
+		u16 integrity_hash;
+		struct skb_mstamp mstamp;
+		bool saw_tsval;
+	} stealth;
+#endif
+
 /* TCP fastopen related information */
 	struct tcp_fastopen_request *fastopen_req;
 	/* fastopen_rsk points to request_sock that resulted in this big
diff -Nurp linux-3.18-rc3/include/net/secure_seq.h linux-3.18-rc3-knock/include/net/secure_seq.h
--- linux-3.18-rc3/include/net/secure_seq.h	2014-11-03 00:01:51.000000000 +0100
+++ linux-3.18-rc3-knock/include/net/secure_seq.h	2014-11-06 21:26:34.976017001 +0100
@@ -14,5 +14,10 @@ u64 secure_dccp_sequence_number(__be32 s
 				__be16 sport, __be16 dport);
 u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
 				  __be16 sport, __be16 dport);
+#ifdef CONFIG_TCP_STEALTH
+u32 tcp_stealth_do_auth(struct sock *sk, struct sk_buff *skb);
+u32 tcp_stealth_sequence_number(struct sock *sk, __be32 *daddr,
+				u32 daddr_size, __be16 dport);
+#endif
 
 #endif /* _NET_SECURE_SEQ */
diff -Nurp linux-3.18-rc3/include/net/tcp.h linux-3.18-rc3-knock/include/net/tcp.h
--- linux-3.18-rc3/include/net/tcp.h	2014-11-03 00:01:51.000000000 +0100
+++ linux-3.18-rc3-knock/include/net/tcp.h	2014-11-06 21:26:34.976017001 +0100
@@ -439,6 +439,12 @@ void tcp_parse_options(const struct sk_b
 		       struct tcp_options_received *opt_rx,
 		       int estab, struct tcp_fastopen_cookie *foc);
 const u8 *tcp_parse_md5sig_option(const struct tcphdr *th);
+#ifdef CONFIG_TCP_STEALTH
+const bool tcp_parse_tsval_option(u32 *tsval, const struct tcphdr *th);
+int tcp_stealth_integrity(u16 *hash, u8 *secret, u8 *payload, int len);
+#define be32_isn_to_be16_av(x)	(((__be16 *)&x)[0])
+#define be32_isn_to_be16_ih(x)	(((__be16 *)&x)[1])
+#endif
 
 /*
  *	TCP v4 functions exported for the inet6 API
diff -Nurp linux-3.18-rc3/include/uapi/linux/tcp.h linux-3.18-rc3-knock/include/uapi/linux/tcp.h
--- linux-3.18-rc3/include/uapi/linux/tcp.h	2014-11-03 00:01:51.000000000 +0100
+++ linux-3.18-rc3-knock/include/uapi/linux/tcp.h	2014-11-06 21:26:34.976017001 +0100
@@ -112,6 +112,9 @@ enum {
 #define TCP_FASTOPEN		23	/* Enable FastOpen on listeners */
 #define TCP_TIMESTAMP		24
 #define TCP_NOTSENT_LOWAT	25	/* limit number of unsent bytes in write queue */
+#define TCP_STEALTH		26
+#define TCP_STEALTH_INTEGRITY	27
+#define TCP_STEALTH_INTEGRITY_LEN	28
 
 struct tcp_repair_opt {
 	__u32	opt_code;
diff -Nurp linux-3.18-rc3/net/core/secure_seq.c linux-3.18-rc3-knock/net/core/secure_seq.c
--- linux-3.18-rc3/net/core/secure_seq.c	2014-11-03 00:01:51.000000000 +0100
+++ linux-3.18-rc3-knock/net/core/secure_seq.c	2014-11-24 14:31:20.227872751 +0100
@@ -8,7 +8,11 @@
 #include <linux/ktime.h>
 #include <linux/string.h>
 #include <linux/net.h>
+#include <linux/socket.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
 
+#include <net/tcp.h>
 #include <net/secure_seq.h>
 
 #if IS_ENABLED(CONFIG_IPV6) || IS_ENABLED(CONFIG_INET)
@@ -39,6 +43,103 @@ static u32 seq_scale(u32 seq)
 }
 #endif
 
+#ifdef CONFIG_TCP_STEALTH
+u32 tcp_stealth_sequence_number(struct sock *sk, __be32 *daddr,
+				u32 daddr_size, __be16 dport)
+{
+	struct tcp_sock *tp = tcp_sk(sk);
+	struct tcp_md5sig_key *md5;
+
+	__u32 sec[MD5_MESSAGE_BYTES / sizeof(__u32)];
+	__u32 i;
+	__u32 tsval = 0;
+
+	__be32 iv[MD5_DIGEST_WORDS] = { 0 };
+	__be32 isn;
+
+	memcpy(iv, (const __u8 *)daddr,
+	       (daddr_size > sizeof(iv)) ? sizeof(iv) : daddr_size);
+
+#ifdef CONFIG_TCP_MD5SIG
+	md5 = tp->af_specific->md5_lookup(sk, sk);
+#else
+	md5 = NULL;
+#endif
+	if (likely(sysctl_tcp_timestamps && !md5) || tp->stealth.saw_tsval)
+		tsval = tp->stealth.mstamp.stamp_jiffies;
+
+	((__be16 *)iv)[2] ^= cpu_to_be16(tp->stealth.integrity_hash);
+	iv[2] ^= cpu_to_be32(tsval);
+	((__be16 *)iv)[6] ^= dport;
+
+	for (i = 0; i < MD5_DIGEST_WORDS; i++)
+		iv[i] = le32_to_cpu(iv[i]);
+	for (i = 0; i < MD5_MESSAGE_BYTES / sizeof(__le32); i++)
+		sec[i] = le32_to_cpu(((__le32 *)tp->stealth.secret)[i]);
+
+	md5_transform(iv, sec);
+
+	isn = cpu_to_be32(iv[0]) ^ cpu_to_be32(iv[1]) ^
+	      cpu_to_be32(iv[2]) ^ cpu_to_be32(iv[3]);
+
+	if (tp->stealth.mode & TCP_STEALTH_MODE_INTEGRITY)
+		be32_isn_to_be16_ih(isn) =
+			cpu_to_be16(tp->stealth.integrity_hash);
+
+	return be32_to_cpu(isn);
+}
+EXPORT_SYMBOL(tcp_stealth_sequence_number);
+
+u32 tcp_stealth_do_auth(struct sock *sk, struct sk_buff *skb)
+{
+	struct tcp_sock *tp = tcp_sk(sk);
+	struct tcphdr *th = tcp_hdr(skb);
+	__be32 isn = th->seq;
+	__be32 hash;
+	__be32 *daddr;
+	u32 daddr_size;
+
+	tp->stealth.saw_tsval =
+		tcp_parse_tsval_option(&tp->stealth.mstamp.stamp_jiffies, th);
+
+	if (tp->stealth.mode & TCP_STEALTH_MODE_INTEGRITY_LEN)
+		tp->stealth.integrity_hash =
+			be16_to_cpu(be32_isn_to_be16_ih(isn));
+
+	switch (tp->inet_conn.icsk_inet.sk.sk_family) {
+#if IS_ENABLED(CONFIG_IPV6)
+	case PF_INET6:
+		daddr_size = sizeof(ipv6_hdr(skb)->daddr.s6_addr32);
+		daddr = ipv6_hdr(skb)->daddr.s6_addr32;
+	break;
+#endif
+	case PF_INET:
+		daddr_size = sizeof(ip_hdr(skb)->daddr);
+		daddr = &ip_hdr(skb)->daddr;
+	break;
+	default:
+		pr_err("TCP Stealth: Unknown network layer protocol, stop!\n");
+		return 1;
+	}
+
+	hash = tcp_stealth_sequence_number(sk, daddr, daddr_size, th->dest);
+	cpu_to_be32s(&hash);
+
+	if (tp->stealth.mode & TCP_STEALTH_MODE_AUTH &&
+	    tp->stealth.mode & TCP_STEALTH_MODE_INTEGRITY_LEN &&
+	    be32_isn_to_be16_av(isn) == be32_isn_to_be16_av(hash))
+		return 0;
+
+	if (tp->stealth.mode & TCP_STEALTH_MODE_AUTH &&
+	    !(tp->stealth.mode & TCP_STEALTH_MODE_INTEGRITY_LEN) &&
+	    isn == hash)
+		return 0;
+
+	return 1;
+}
+EXPORT_SYMBOL(tcp_stealth_do_auth);
+#endif
+
 #if IS_ENABLED(CONFIG_IPV6)
 __u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr,
 				   __be16 sport, __be16 dport)
diff -Nurp linux-3.18-rc3/net/ipv4/Kconfig linux-3.18-rc3-knock/net/ipv4/Kconfig
--- linux-3.18-rc3/net/ipv4/Kconfig	2014-11-03 00:01:51.000000000 +0100
+++ linux-3.18-rc3-knock/net/ipv4/Kconfig	2014-11-06 21:26:34.976017001 +0100
@@ -671,3 +671,13 @@ config TCP_MD5SIG
 	  on the Internet.
 
 	  If unsure, say N.
+
+config TCP_STEALTH
+	bool "TCP: Stealth TCP socket support"
+	default n
+	---help---
+	  This option enables support for stealth TCP sockets. If you do not
+	  know what this means, you do not need it.
+
+	  If unsure, say N.
+
diff -Nurp linux-3.18-rc3/net/ipv4/tcp.c linux-3.18-rc3-knock/net/ipv4/tcp.c
--- linux-3.18-rc3/net/ipv4/tcp.c	2014-11-03 00:01:51.000000000 +0100
+++ linux-3.18-rc3-knock/net/ipv4/tcp.c	2014-11-24 11:44:39.700059516 +0100
@@ -2329,6 +2329,43 @@ static int tcp_repair_options_est(struct
 	return 0;
 }
 
+#ifdef CONFIG_TCP_STEALTH
+int tcp_stealth_integrity(__be16 *hash, u8 *secret, u8 *payload, int len)
+{
+	struct scatterlist sg[2];
+	struct crypto_hash *tfm;
+	struct hash_desc desc;
+	__be16 h[MD5_DIGEST_WORDS * 2];
+	int i;
+	int err = 0;
+
+	tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(tfm)) {
+		err = -PTR_ERR(tfm);
+		goto out;
+	}
+	desc.tfm = tfm;
+	desc.flags = 0;
+
+	sg_init_table(sg, 2);
+	sg_set_buf(&sg[0], secret, MD5_MESSAGE_BYTES);
+	sg_set_buf(&sg[1], payload, len);
+
+	if (crypto_hash_digest(&desc, sg, MD5_MESSAGE_BYTES + len, (u8 *)h)) {
+		err = -EFAULT;
+		goto out;
+	}
+
+	*hash = be16_to_cpu(h[0]);
+	for (i = 1; i < MD5_DIGEST_WORDS * 2; i++)
+		*hash ^= be16_to_cpu(h[i]);
+
+out:
+	crypto_free_hash(tfm);
+	return err;
+}
+#endif
+
 /*
  *	Socket option code for TCP.
  */
@@ -2359,6 +2396,67 @@ static int do_tcp_setsockopt(struct sock
 		release_sock(sk);
 		return err;
 	}
+#ifdef CONFIG_TCP_STEALTH
+	case TCP_STEALTH: {
+		u8 secret[MD5_MESSAGE_BYTES] = { 0 };
+
+		val = copy_from_user(secret, optval,
+				     min_t(unsigned int, optlen,
+					   MD5_MESSAGE_BYTES));
+
+		if (val != 0)
+			return -EFAULT;
+
+		lock_sock(sk);
+		memcpy(tp->stealth.secret, secret, MD5_MESSAGE_BYTES);
+		tp->stealth.mode = TCP_STEALTH_MODE_AUTH;
+		tp->stealth.mstamp.v64 = 0;
+		tp->stealth.saw_tsval = false;
+		release_sock(sk);
+		return err;
+	}
+	case TCP_STEALTH_INTEGRITY: {
+		u8 *payload;
+
+		lock_sock(sk);
+
+		if (!(tp->stealth.mode & TCP_STEALTH_MODE_AUTH)) {
+			err = -EOPNOTSUPP;
+			goto stealth_integrity_out_1;
+		}
+
+		if (optlen < 1 || optlen > USHRT_MAX) {
+			err = -EINVAL;
+			goto stealth_integrity_out_1;
+		}
+
+		payload = vmalloc(optlen);
+		if (!payload) {
+			err = -ENOMEM;
+			goto stealth_integrity_out_1;
+		}
+
+		val = copy_from_user(payload, optval, optlen);
+		if (val != 0) {
+			err = -EFAULT;
+			goto stealth_integrity_out_2;
+		}
+
+		err = tcp_stealth_integrity(&tp->stealth.integrity_hash,
+					    tp->stealth.secret, payload,
+					    optlen);
+		if (err)
+			goto stealth_integrity_out_2;
+
+		tp->stealth.mode |= TCP_STEALTH_MODE_INTEGRITY;
+
+stealth_integrity_out_2:
+		vfree(payload);
+stealth_integrity_out_1:
+		release_sock(sk);
+		return err;
+	}
+#endif
 	default:
 		/* fallthru */
 		break;
@@ -2600,6 +2698,18 @@ static int do_tcp_setsockopt(struct sock
 		tp->notsent_lowat = val;
 		sk->sk_write_space(sk);
 		break;
+#ifdef CONFIG_TCP_STEALTH
+	case TCP_STEALTH_INTEGRITY_LEN:
+		if (!(tp->stealth.mode & TCP_STEALTH_MODE_AUTH)) {
+			err = -EOPNOTSUPP;
+		} else if (val < 1 || val > USHRT_MAX) {
+			err = -EINVAL;
+		} else {
+			tp->stealth.integrity_len = val;
+			tp->stealth.mode |= TCP_STEALTH_MODE_INTEGRITY_LEN;
+		}
+		break;
+#endif
 	default:
 		err = -ENOPROTOOPT;
 		break;
diff -Nurp linux-3.18-rc3/net/ipv4/tcp_input.c linux-3.18-rc3-knock/net/ipv4/tcp_input.c
--- linux-3.18-rc3/net/ipv4/tcp_input.c	2014-11-03 00:01:51.000000000 +0100
+++ linux-3.18-rc3-knock/net/ipv4/tcp_input.c	2014-11-06 21:26:34.976017001 +0100
@@ -77,6 +77,9 @@
 #include <linux/errqueue.h>
 
 int sysctl_tcp_timestamps __read_mostly = 1;
+#ifdef CONFIG_TCP_STEALTH
+EXPORT_SYMBOL(sysctl_tcp_timestamps);
+#endif
 int sysctl_tcp_window_scaling __read_mostly = 1;
 int sysctl_tcp_sack __read_mostly = 1;
 int sysctl_tcp_fack __read_mostly = 1;
@@ -3715,6 +3718,47 @@ static bool tcp_fast_parse_options(const
 	return true;
 }
 
+#ifdef CONFIG_TCP_STEALTH
+/* Parse only the TSVal field of the TCP Timestamp option header.
+ */
+const bool tcp_parse_tsval_option(u32 *tsval, const struct tcphdr *th)
+{
+	int length = (th->doff << 2) - sizeof(*th);
+	const u8 *ptr = (const u8 *)(th + 1);
+
+	/* If the TCP option is too short, we can short cut */
+	if (length < TCPOLEN_TIMESTAMP)
+		return false;
+
+	while (length > 0) {
+		int opcode = *ptr++;
+		int opsize;
+
+		switch (opcode) {
+		case TCPOPT_EOL:
+			return false;
+		case TCPOPT_NOP:
+			length--;
+			continue;
+		case TCPOPT_TIMESTAMP:
+			opsize = *ptr++;
+			if (opsize != TCPOLEN_TIMESTAMP || opsize > length)
+				return false;
+			*tsval = get_unaligned_be32(ptr);
+			return true;
+		default:
+			opsize = *ptr++;
+			if (opsize < 2 || opsize > length)
+				return false;
+		}
+		ptr += opsize - 2;
+		length -= opsize;
+	}
+	return false;
+}
+EXPORT_SYMBOL(tcp_parse_tsval_option);
+#endif
+
 #ifdef CONFIG_TCP_MD5SIG
 /*
  * Parse MD5 Signature option
@@ -4384,6 +4428,31 @@ err:
 	return -ENOMEM;
 }
 
+#ifdef CONFIG_TCP_STEALTH
+static int __tcp_stealth_integrity_check(struct sock *sk, struct sk_buff *skb)
+{
+	struct tcphdr *th = tcp_hdr(skb);
+	struct tcp_sock *tp = tcp_sk(sk);
+	u16 hash;
+	__be32 seq = cpu_to_be32(TCP_SKB_CB(skb)->seq - 1);
+	char *data = skb->data + th->doff * 4;
+	int len = skb->len - th->doff * 4;
+
+	if (len < tp->stealth.integrity_len)
+		return 1;
+
+	if (tcp_stealth_integrity(&hash, tp->stealth.secret, data,
+				  tp->stealth.integrity_len))
+		return 1;
+
+	if (be32_isn_to_be16_ih(seq) != cpu_to_be16(hash))
+		return 1;
+
+	tp->stealth.mode &= ~TCP_STEALTH_MODE_INTEGRITY_LEN;
+	return 0;
+}
+#endif
+
 static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
@@ -4393,6 +4462,14 @@ static void tcp_data_queue(struct sock *
 	if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq)
 		goto drop;
 
+#ifdef CONFIG_TCP_STEALTH
+	if (unlikely(tp->stealth.mode & TCP_STEALTH_MODE_INTEGRITY_LEN) &&
+	    __tcp_stealth_integrity_check(sk, skb)) {
+		tcp_reset(sk);
+		goto drop;
+	}
+#endif
+
 	skb_dst_drop(skb);
 	__skb_pull(skb, tcp_hdr(skb)->doff * 4);
 
@@ -5156,6 +5233,15 @@ void tcp_rcv_established(struct sock *sk
 			int eaten = 0;
 			bool fragstolen = false;
 
+#ifdef CONFIG_TCP_STEALTH
+			if (unlikely(tp->stealth.mode &
+				     TCP_STEALTH_MODE_INTEGRITY_LEN) &&
+			    __tcp_stealth_integrity_check(sk, skb)) {
+				tcp_reset(sk);
+				goto discard;
+			}
+#endif
+
 			if (tp->ucopy.task == current &&
 			    tp->copied_seq == tp->rcv_nxt &&
 			    len - tcp_header_len <= tp->ucopy.len &&
diff -Nurp linux-3.18-rc3/net/ipv4/tcp_ipv4.c linux-3.18-rc3-knock/net/ipv4/tcp_ipv4.c
--- linux-3.18-rc3/net/ipv4/tcp_ipv4.c	2014-11-03 00:01:51.000000000 +0100
+++ linux-3.18-rc3-knock/net/ipv4/tcp_ipv4.c	2014-11-06 21:26:34.976017001 +0100
@@ -75,6 +75,7 @@
 #include <net/secure_seq.h>
 #include <net/tcp_memcontrol.h>
 #include <net/busy_poll.h>
+#include <net/secure_seq.h>
 
 #include <linux/inet.h>
 #include <linux/ipv6.h>
@@ -235,6 +236,21 @@ int tcp_v4_connect(struct sock *sk, stru
 	sk->sk_gso_type = SKB_GSO_TCPV4;
 	sk_setup_caps(sk, &rt->dst);
 
+#ifdef CONFIG_TCP_STEALTH
+	/* If CONFIG_TCP_STEALTH is defined, we need to know the timestamp as
+	 * early as possible and thus move taking the snapshot of tcp_time_stamp
+	 * here.
+	 */
+	skb_mstamp_get(&tp->stealth.mstamp);
+
+	if (!tp->write_seq && likely(!tp->repair) &&
+	    unlikely(tp->stealth.mode & TCP_STEALTH_MODE_AUTH))
+		tp->write_seq = tcp_stealth_sequence_number(sk,
+					&inet->inet_daddr,
+					sizeof(inet->inet_daddr),
+					usin->sin_port);
+#endif
+
 	if (!tp->write_seq && likely(!tp->repair))
 		tp->write_seq = secure_tcp_sequence_number(inet->inet_saddr,
 							   inet->inet_daddr,
@@ -1423,6 +1439,8 @@ static struct sock *tcp_v4_hnd_req(struc
  */
 int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
 {
+	struct tcp_sock *tp = tcp_sk(sk);
+	struct tcphdr *th = tcp_hdr(skb);
 	struct sock *rsk;
 
 	if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
@@ -1443,6 +1461,15 @@ int tcp_v4_do_rcv(struct sock *sk, struc
 	if (skb->len < tcp_hdrlen(skb) || tcp_checksum_complete(skb))
 		goto csum_err;
 
+#ifdef CONFIG_TCP_STEALTH
+	if (sk->sk_state == TCP_LISTEN && th->syn && !th->fin &&
+	    unlikely(tp->stealth.mode & TCP_STEALTH_MODE_AUTH) &&
+	    tcp_stealth_do_auth(sk, skb)) {
+		rsk = sk;
+		goto reset;
+	}
+#endif
+
 	if (sk->sk_state == TCP_LISTEN) {
 		struct sock *nsk = tcp_v4_hnd_req(sk, skb);
 		if (!nsk)
diff -Nurp linux-3.18-rc3/net/ipv4/tcp_output.c linux-3.18-rc3-knock/net/ipv4/tcp_output.c
--- linux-3.18-rc3/net/ipv4/tcp_output.c	2014-11-03 00:01:51.000000000 +0100
+++ linux-3.18-rc3-knock/net/ipv4/tcp_output.c	2014-11-24 14:29:25.380852760 +0100
@@ -915,6 +915,13 @@ static int tcp_transmit_skb(struct sock
 	tcb = TCP_SKB_CB(skb);
 	memset(&opts, 0, sizeof(opts));
 
+#ifdef TCP_STEALTH
+	if (unlikely(tcb->tcp_flags & TCPHDR_SYN &&
+		     tp->stealth.mode & TCP_STEALTH_MODE_AUTH)) {
+		skb->skb_mstamp = tp->stealth.mstamp;
+	}
+#endif
+
 	if (unlikely(tcb->tcp_flags & TCPHDR_SYN))
 		tcp_options_size = tcp_syn_options(sk, skb, &opts, &md5);
 	else
@@ -3109,7 +3116,15 @@ int tcp_connect(struct sock *sk)
 	skb_reserve(buff, MAX_TCP_HEADER);
 
 	tcp_init_nondata_skb(buff, tp->write_seq++, TCPHDR_SYN);
+#ifdef CONFIG_TCP_STEALTH
+	/* The timetamp was already made at the time the ISN was generated
+	 * as we need to know its value in the stealth_tcp_sequence_number()
+	 * function.
+	 */
+	tp->retrans_stamp = tp->stealth.mstamp.stamp_jiffies;
+#else
 	tp->retrans_stamp = tcp_time_stamp;
+#endif
 	tcp_connect_queue_skb(sk, buff);
 	tcp_ecn_send_syn(sk, buff);
 
diff -Nurp linux-3.18-rc3/net/ipv6/tcp_ipv6.c linux-3.18-rc3-knock/net/ipv6/tcp_ipv6.c
--- linux-3.18-rc3/net/ipv6/tcp_ipv6.c	2014-11-03 00:01:51.000000000 +0100
+++ linux-3.18-rc3-knock/net/ipv6/tcp_ipv6.c	2014-11-06 21:26:34.976017001 +0100
@@ -63,6 +63,7 @@
 #include <net/secure_seq.h>
 #include <net/tcp_memcontrol.h>
 #include <net/busy_poll.h>
+#include <net/secure_seq.h>
 
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
@@ -297,6 +298,21 @@ static int tcp_v6_connect(struct sock *s
 
 	ip6_set_txhash(sk);
 
+#ifdef CONFIG_TCP_STEALTH
+	/* If CONFIG_TCP_STEALTH is defined, we need to know the timestamp as
+	 * early as possible and thus move taking the snapshot of tcp_time_stamp
+	 * here.
+	 */
+	skb_mstamp_get(&tp->stealth.mstamp);
+
+	if (!tp->write_seq && likely(!tp->repair) &&
+	    unlikely(tp->stealth.mode & TCP_STEALTH_MODE_AUTH))
+		tp->write_seq = tcp_stealth_sequence_number(sk,
+					sk->sk_v6_daddr.s6_addr32,
+					sizeof(sk->sk_v6_daddr),
+					inet->inet_dport);
+#endif
+
 	if (!tp->write_seq && likely(!tp->repair))
 		tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32,
 							     sk->sk_v6_daddr.s6_addr32,
@@ -1251,7 +1267,8 @@ out:
 static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
 {
 	struct ipv6_pinfo *np = inet6_sk(sk);
-	struct tcp_sock *tp;
+	struct tcp_sock *tp = tcp_sk(sk);
+	struct tcphdr *th = tcp_hdr(skb);
 	struct sk_buff *opt_skb = NULL;
 
 	/* Imagine: socket is IPv6. IPv4 packet arrives,
@@ -1310,6 +1327,13 @@ static int tcp_v6_do_rcv(struct sock *sk
 	if (skb->len < tcp_hdrlen(skb) || tcp_checksum_complete(skb))
 		goto csum_err;
 
+#ifdef CONFIG_TCP_STEALTH
+	if (sk->sk_state == TCP_LISTEN && th->syn && !th->fin &&
+	    tp->stealth.mode & TCP_STEALTH_MODE_AUTH &&
+	    tcp_stealth_do_auth(sk, skb))
+		goto reset;
+#endif
+
 	if (sk->sk_state == TCP_LISTEN) {
 		struct sock *nsk = tcp_v6_hnd_req(sk, skb);
 		if (!nsk)

[-- Attachment #3: tcp_stealth_3.18.diff.sig --]
[-- Type: application/pgp-signature, Size: 287 bytes --]

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

* Re: [PATCH] TCP: Add support for TCP Stealth
  2014-12-31 21:54 [PATCH] TCP: Add support for TCP Stealth Julian Kirsch
@ 2015-01-01 15:25 ` Daniel Borkmann
  2015-01-01 15:32   ` Christian Grothoff
  2015-01-01 19:06 ` Stephen Hemminger
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 9+ messages in thread
From: Daniel Borkmann @ 2015-01-01 15:25 UTC (permalink / raw)
  To: Julian Kirsch
  Cc: netdev, Christian Grothoff, Jacob Appelbaum, Pavel Emelyanov

Hi Julian,

On 12/31/2014 10:54 PM, Julian Kirsch wrote:
...
> one year ago [0] we tried to convince you to add support for a new
> socket option to the linux kernel. Equipped with an improved version of
> our patch we're back to accomplish this task today. :-)
>
> TCP Stealth is a modern variant of port knocking which borrows
> techniques from network steganography to enable clients to authenticate
> themselves towards a server on TCP level. You can find technical details
> in an rfc draft we wrote earlier this year [1] and in my master's thesis
> [2]. In summary, TCP Stealth derives authentication information from a
> pre-shared secret and embeds it into the ISN sent along with the first
> SYN from the client.

/me wondering (haven't tried that though) ... have you considered f.e.
building a library using a raw packet socket with a BPF filter to capture
SYN packets and then TCP_REPAIR [1] to build a full-blown TCP socket out
of it in case of a correct authentication from the ISN?

Thanks,
Daniel

   [1] http://www.criu.org/TCP_connection

> Our motivation is simple: During this year we gained hard evidence on
> secret services actively port scanning the internets followed by
> exploitation of your services using 0-day exploits [3, 4]. We don't want
> our machines to be turned into relays from where they continue to
> cascade their attacks. TCP Stealth makes port scanning more expensive by
> a factor of 2^31 (on average).
>
> A copy of this patch as well as patches for several user space
> applications can be found on the project's home page [5].
>
> All the best for the upcoming year,
> Julian & Christian
>
>
>
> [0] https://lkml.org/lkml/2013/12/10/1155
> [1] https://datatracker.ietf.org/doc/draft-kirsch-ietf-tcp-stealth/
> [2] https://gnunet.org/kirsch2014knock
> [3]
> http://www.heise.de/ct/artikel/NSA-GCHQ-The-HACIENDA-Program-for-Internet-Colonization-2292681.html
> [4]
> https://firstlook.org/theintercept/2014/12/13/belgacom-hack-gchq-inside-story/
> [5] https://gnunet.org/knock
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1
>
> iQEcBAEBAgAGBQJUpHCvAAoJENwkOWttRRA4g10IALbJZU9/5Gp8tVdpXqbkOIMp
> Kz+yOMyYULqYeM8yguSBZjZLbaz/VAS7SNpQxKGU+W0aAXa22FsSfVoUU7wqp3NT
> 3EGRuPkMaJkQ66IP8MtX+6/hSeWSh78tEaIFWVjyutihPyQGz0LefFc66gm54X4T
> s8IYW7jKFhNmmROu9CXLTxq4B5t2v+Evv/qWqotZqR1t3IbIUmZAiKrlkMRd7dtM
> SaS5JwFeiObxn+0M/7javQCAhfgPXYEOU0QKAGY55MXcPAner/5PuExIZdOJ41R3
> XD9tgoLGhHEiQkxj0/bP2cs3Cl5xfJl9t2iecVfTIR7PytaTJ/kFuE4gNgWEcTA=
> =T6/C
> -----END PGP SIGNATURE-----
>

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

* Re: [PATCH] TCP: Add support for TCP Stealth
  2015-01-01 15:25 ` Daniel Borkmann
@ 2015-01-01 15:32   ` Christian Grothoff
  2015-01-02 12:50     ` Daniel Borkmann
  0 siblings, 1 reply; 9+ messages in thread
From: Christian Grothoff @ 2015-01-01 15:32 UTC (permalink / raw)
  To: Daniel Borkmann, Julian Kirsch; +Cc: netdev, Jacob Appelbaum, Pavel Emelyanov

[-- Attachment #1: Type: text/plain, Size: 783 bytes --]

Dear Daniel,

That approach is highly vulnerable to timing attacks, and doesn't answer
how TCP clients without special capabilities could set the ISN correctly
either. Playing with raw sockets is the kind of geeky hack that is
unlikely to give us the combination of usability and security required
to significantly reduce the ongoing large-scale compromise of network
equipment by spy agencies.

Christian

On 01/01/2015 04:25 PM, Daniel Borkmann wrote:
> 
> /me wondering (haven't tried that though) ... have you considered f.e.
> building a library using a raw packet socket with a BPF filter to capture
> SYN packets and then TCP_REPAIR [1] to build a full-blown TCP socket out
> of it in case of a correct authentication from the ISN?
> 
> Thanks,
> Daniel


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [PATCH] TCP: Add support for TCP Stealth
  2014-12-31 21:54 [PATCH] TCP: Add support for TCP Stealth Julian Kirsch
  2015-01-01 15:25 ` Daniel Borkmann
@ 2015-01-01 19:06 ` Stephen Hemminger
  2015-01-01 19:10 ` Stephen Hemminger
  2015-01-02 10:36 ` Hagen Paul Pfeifer
  3 siblings, 0 replies; 9+ messages in thread
From: Stephen Hemminger @ 2015-01-01 19:06 UTC (permalink / raw)
  To: Julian Kirsch; +Cc: netdev, Christian Grothoff, Jacob Appelbaum

On Wed, 31 Dec 2014 22:54:59 +0100
Julian Kirsch <kirschju@sec.in.tum.de> wrote:

> +#ifdef CONFIG_TCP_STEALTH
> +/* Stealth TCP socket configuration */
> +	struct {
> +		#define TCP_STEALTH_MODE_AUTH		BIT(0)
> +		#define TCP_STEALTH_MODE_INTEGRITY	BIT(1)
> +		#define TCP_STEALTH_MODE_INTEGRITY_LEN	BIT(2)
> +		int mode;
> +		u8 secret[MD5_MESSAGE_BYTES];
> +		int integrity_len;
> +		u16 integrity_hash;
> +		struct skb_mstamp mstamp;
> +		bool saw_tsval;
> +	} stealth;
> +#endif

If you want a bitfield, why not use a bitfield for mode?
If you have to use masks, better to use u8 for mode.
Integrity length should be unsigned since obviously negative
values are not possible.

Rearrange structure to save space. Lots of holes here.

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

* Re: [PATCH] TCP: Add support for TCP Stealth
  2014-12-31 21:54 [PATCH] TCP: Add support for TCP Stealth Julian Kirsch
  2015-01-01 15:25 ` Daniel Borkmann
  2015-01-01 19:06 ` Stephen Hemminger
@ 2015-01-01 19:10 ` Stephen Hemminger
  2015-01-01 23:31   ` Julian Kirsch
  2015-01-02 10:36 ` Hagen Paul Pfeifer
  3 siblings, 1 reply; 9+ messages in thread
From: Stephen Hemminger @ 2015-01-01 19:10 UTC (permalink / raw)
  To: Julian Kirsch; +Cc: netdev, Christian Grothoff, Jacob Appelbaum

On Wed, 31 Dec 2014 22:54:59 +0100
Julian Kirsch <kirschju@sec.in.tum.de> wrote:

> +	memcpy(iv, (const __u8 *)daddr,
> +	       (daddr_size > sizeof(iv)) ? sizeof(iv) : daddr_size);
> +
> +#ifdef CONFIG_TCP_MD5SIG
> +	md5 = tp->af_specific->md5_lookup(sk, sk);
> +#else
> +	md5 = NULL;
> +#endif
> +	if (likely(sysctl_tcp_timestamps && !md5) || tp->stealth.saw_tsval)
> +		tsval = tp->stealth.mstamp.stamp_jiffies;
> +
> +	((__be16 *)iv)[2] ^= cpu_to_be16(tp->stealth.integrity_hash);

Cast unnecessary on memcpy arg since it takes void *

Would be clearer to use a real structure or union not assignment to cast to setup iv.

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

* Re: [PATCH] TCP: Add support for TCP Stealth
  2015-01-01 19:10 ` Stephen Hemminger
@ 2015-01-01 23:31   ` Julian Kirsch
  0 siblings, 0 replies; 9+ messages in thread
From: Julian Kirsch @ 2015-01-01 23:31 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev, Christian Grothoff, Jacob Appelbaum

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi Stephen,

thanks a lot for your input. I've reflected your suggestions in the
code: The mode member of the stealth struct is now a u8, integrity_len
is now unsigned (size_t), I've switched the integrity_len and
integrity_hash members in order to close the gaps in the struct (sorry
for wasting bits) and I removed the cast from the second parameter of
the memcopy you mentioned. While I totally agree with you that the
part of the iv-setup where we xor the hash, tsval and dport in is not
very readable, I'd argue that declaring and using a struct would make
the patch longer while the semantics of such a struct really are
needed only in context of a single function and therefore cannot be
reused. Do you think that accessing the elements with a macro (see
below) could be an alternative?

#define tcp_stealth_iv_integrity_hash(iv)	(((__be16 *)&iv)[2])

Best,
Julian

On 2015-01-01 20:10, Stephen Hemminger wrote:
> On Wed, 31 Dec 2014 22:54:59 +0100 Julian Kirsch
> <kirschju@sec.in.tum.de> wrote:
> 
>> +	memcpy(iv, (const __u8 *)daddr, +	       (daddr_size >
>> sizeof(iv)) ? sizeof(iv) : daddr_size); + +#ifdef
>> CONFIG_TCP_MD5SIG +	md5 = tp->af_specific->md5_lookup(sk, sk); 
>> +#else +	md5 = NULL; +#endif +	if (likely(sysctl_tcp_timestamps
>> && !md5) || tp->stealth.saw_tsval) +		tsval =
>> tp->stealth.mstamp.stamp_jiffies; + +	((__be16 *)iv)[2] ^=
>> cpu_to_be16(tp->stealth.integrity_hash);
> 
> Cast unnecessary on memcpy arg since it takes void *
> 
> Would be clearer to use a real structure or union not assignment to
> cast to setup iv. -- To unsubscribe from this list: send the line
> "unsubscribe netdev" in the body of a message to
> majordomo@vger.kernel.org More majordomo info at
> http://vger.kernel.org/majordomo-info.html
> 

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQEcBAEBAgAGBQJUpdjhAAoJENwkOWttRRA4ZFYIALs7gskvZqlCzFCuNTsJ4js9
7x5OTsuyY5caOIEcveVqYnW2dcOO2Jtwe1QUIOsRo7X6YOEA/8IT6+sJ0fxViLTD
TJAzU670Kcecn7+0cHPAj31yW+t9SHb5BBzMLCJlhSAboMs0YKmkwetqffg013uP
x81OI6kJy6pUCAeBeyyy20QafrIhs5vjEILGf9qSzeoIXRBdpnuH99FzoxEjOkUA
ka4QtrAUh3Uk0s6H8ezcpqvY2bKcz7te8+af5XF+Kz/+DLatoN2x58psxw3irBCw
x18FRVsbgmXY/m3leKilK4ieCyO1LzafRNa674fSW6QtHHMDZwSoYi0kDjSNMRk=
=ke3l
-----END PGP SIGNATURE-----

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

* Re: [PATCH] TCP: Add support for TCP Stealth
  2014-12-31 21:54 [PATCH] TCP: Add support for TCP Stealth Julian Kirsch
                   ` (2 preceding siblings ...)
  2015-01-01 19:10 ` Stephen Hemminger
@ 2015-01-02 10:36 ` Hagen Paul Pfeifer
  3 siblings, 0 replies; 9+ messages in thread
From: Hagen Paul Pfeifer @ 2015-01-02 10:36 UTC (permalink / raw)
  To: Julian Kirsch, Eric Dumazet; +Cc: netdev, Christian Grothoff, Jacob Appelbaum

On 31 December 2014 at 22:54, Julian Kirsch <kirschju@sec.in.tum.de> wrote:

Hey Jullian

> one year ago [0] we tried to convince you to add support for a new
> socket option to the linux kernel. Equipped with an improved version of
> our patch we're back to accomplish this task today. :-)

Nice, what is the difference from the previous version? There is no
changelog in the patch. Especially issues raised by Eric (cc'ed) one
year ago and TCPM.

Hagen

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

* Re: [PATCH] TCP: Add support for TCP Stealth
  2015-01-01 15:32   ` Christian Grothoff
@ 2015-01-02 12:50     ` Daniel Borkmann
  2015-01-02 14:06       ` Christian Grothoff
  0 siblings, 1 reply; 9+ messages in thread
From: Daniel Borkmann @ 2015-01-02 12:50 UTC (permalink / raw)
  To: Christian Grothoff
  Cc: Julian Kirsch, netdev, Jacob Appelbaum, Pavel Emelyanov

On 01/01/2015 04:32 PM, Christian Grothoff wrote:
...
> That approach is highly vulnerable to timing attacks, and doesn't answer
> how TCP clients without special capabilities could set the ISN correctly
> either. Playing with raw sockets is the kind of geeky hack that is

Right, for client/server side you'd need to have the capabilities and
then drop them later, which would make that approach less convenient
for user space applications (despite not having to have a port knocking
uapi in the TCP core itself). For the server, you might get away with a
central daemon spawning sockets via IPC, but for the unprivileged
client to e.g., let it set it's own ISN via setsockopt(2) would be a
bad idea.

> unlikely to give us the combination of usability and security required
> to significantly reduce the ongoing large-scale compromise of network
> equipment by spy agencies.

Out of curiosity, when you say you want to significantly reduce the
large-scale compromise of services by hiding ports, how do you solve
i) the pre-shared key distribution issue you need for your approach
(are you mostly targeting administrators for accessing their companies
router/firewall management interfaces?), and ii) the broad adoption of
this setsockopt(2) in applications? I think for ii) it would be great
not having to change and recompile every possible client _and_ server
application if they don't have the change upstreamed in their project.
It feels like a property that goes beyond the scope of a specific,
individual application, put differently, what about an additional
central configuration interface? Other than that, is there a plan for
key rotations in other words, to have a grace period for a key
transition as peers might not have synced clocks?

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

* Re: [PATCH] TCP: Add support for TCP Stealth
  2015-01-02 12:50     ` Daniel Borkmann
@ 2015-01-02 14:06       ` Christian Grothoff
  0 siblings, 0 replies; 9+ messages in thread
From: Christian Grothoff @ 2015-01-02 14:06 UTC (permalink / raw)
  To: Daniel Borkmann; +Cc: Julian Kirsch, netdev, Jacob Appelbaum, Pavel Emelyanov

[-- Attachment #1: Type: text/plain, Size: 3534 bytes --]

On 01/02/2015 01:50 PM, Daniel Borkmann wrote:
> On 01/01/2015 04:32 PM, Christian Grothoff wrote:
> ...
>> That approach is highly vulnerable to timing attacks, and doesn't answer
>> how TCP clients without special capabilities could set the ISN correctly
>> either. Playing with raw sockets is the kind of geeky hack that is
> 
> Right, for client/server side you'd need to have the capabilities and
> then drop them later, which would make that approach less convenient
> for user space applications (despite not having to have a port knocking
> uapi in the TCP core itself). For the server, you might get away with a
> central daemon spawning sockets via IPC, but for the unprivileged
> client to e.g., let it set it's own ISN via setsockopt(2) would be a
> bad idea.
> 
>> unlikely to give us the combination of usability and security required
>> to significantly reduce the ongoing large-scale compromise of network
>> equipment by spy agencies.
> 
> Out of curiosity, when you say you want to significantly reduce the
> large-scale compromise of services by hiding ports, how do you solve
> i) the pre-shared key distribution issue you need for your approach
> (are you mostly targeting administrators for accessing their companies
> router/firewall management interfaces?), 

Our assumption is that this solution will work if SSH access to the
system is limited to a small set of users that can easily agree on an
additional passphrase.  We do not claim to solve the key distribution
issue in general (the GNU Name System can solve it for some application
scenarios, but that's out of scope for Knock).  Like most security
solutions, this works for some scenarios, but not all.

> and ii) the broad adoption of
> this setsockopt(2) in applications? I think for ii) it would be great
> not having to change and recompile every possible client _and_ server
> application if they don't have the change upstreamed in their project.

Correct, for that we have libknockify, a library you can LD_PRELOAD,
setting the passphrase via an environment variable.  Now, this doesn't
work for applications that don't permit LD_PRELOAD (like openssh) or use
some TCP sockets where TCP Stealth should be active, and others where it
should not be.  But for tools like 'netcat', 'telnet', 'wget' and many
other small tools, libknockify will work.

> It feels like a property that goes beyond the scope of a specific,
> individual application, put differently, what about an additional
> central configuration interface?

With our patch for systemd support, we kind of have a 'central'
configuration interface for "next-generation" servers that support
systemd-style listening.  For clients, using libknockify works usually
pretty well as clients usually don't have many different types of TCP
sockets open.

> Other than that, is there a plan for
> key rotations in other words, to have a grace period for a key
> transition as peers might not have synced clocks?

I have no such plans, as it would complicate the system quite a bit and
thus also reduces usability.  It would way complicate the key
distribution issue you mentioned, and also the libknockify-style
integration where currently the PSK can simply be passed via an
environment variable would also have to be done differently (i.e.
contacting some kind of PSK-oracle service via IPC). The result would be
a huge increase in complexity for IMO a rather small gain in security
for possibly only a small set of users.


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

end of thread, other threads:[~2015-01-02 14:06 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-12-31 21:54 [PATCH] TCP: Add support for TCP Stealth Julian Kirsch
2015-01-01 15:25 ` Daniel Borkmann
2015-01-01 15:32   ` Christian Grothoff
2015-01-02 12:50     ` Daniel Borkmann
2015-01-02 14:06       ` Christian Grothoff
2015-01-01 19:06 ` Stephen Hemminger
2015-01-01 19:10 ` Stephen Hemminger
2015-01-01 23:31   ` Julian Kirsch
2015-01-02 10:36 ` Hagen Paul Pfeifer

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.