# HG changeset patch # User Pascal Bellard # Date 1526644053 -7200 # Node ID fa77ea692592f1632a69aa5ed283457c1fc6fb04 # Parent f215c72530a6343ef4884f279331d785bfc04e67 linux, openssh: add tcp_stealth patch diff -r f215c72530a6 -r fa77ea692592 linux/receipt --- a/linux/receipt Thu May 17 10:47:21 2018 +0200 +++ b/linux/receipt Fri May 18 13:47:33 2018 +0200 @@ -219,6 +219,7 @@ $PACKAGE-freeinitrd.u $PACKAGE-subroot.u $PACKAGE-romfs.u +$PACKAGE-tcp_stealth.u aufs3-base.patch aufs3-standalone.patch aufs3-loopback.patch diff -r f215c72530a6 -r fa77ea692592 linux/stuff/linux-tcp_stealth.u --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linux/stuff/linux-tcp_stealth.u Fri May 18 13:47:33 2018 +0200 @@ -0,0 +1,630 @@ +From https://gnunet.org/knock : +https://gnunet.org/sites/default/files/tcp_stealth_3.16_1.diff +Signed-off-by: Julian Kirsch +--- +diff -Nurp linux-3.16/include/linux/tcp.h linux-3.16-knock/include/linux/tcp.h +--- linux-3.16/include/linux/tcp.h 2014-08-03 18:25:02.000000000 -0400 ++++ linux-3.16-knock/include/linux/tcp.h 2014-08-19 06:15:42.329509665 -0400 +@@ -20,6 +20,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -325,6 +326,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; ++ u32 tsval; ++ 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.16/include/net/secure_seq.h linux-3.16-knock/include/net/secure_seq.h +--- linux-3.16/include/net/secure_seq.h 2014-08-03 18:25:02.000000000 -0400 ++++ linux-3.16-knock/include/net/secure_seq.h 2014-08-19 05:52:22.389447048 -0400 +@@ -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.16/include/net/tcp.h linux-3.16-knock/include/net/tcp.h +--- linux-3.16/include/net/tcp.h 2014-08-03 18:25:02.000000000 -0400 ++++ linux-3.16-knock/include/net/tcp.h 2014-08-11 07:16:15.968418122 -0400 +@@ -442,6 +442,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.16/include/uapi/linux/tcp.h linux-3.16-knock/include/uapi/linux/tcp.h +--- linux-3.16/include/uapi/linux/tcp.h 2014-08-03 18:25:02.000000000 -0400 ++++ linux-3.16-knock/include/uapi/linux/tcp.h 2014-08-11 07:16:15.968418122 -0400 +@@ -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.16/net/core/secure_seq.c linux-3.16-knock/net/core/secure_seq.c +--- linux-3.16/net/core/secure_seq.c 2014-08-03 18:25:02.000000000 -0400 ++++ linux-3.16-knock/net/core/secure_seq.c 2014-08-19 06:19:31.241519904 -0400 +@@ -8,7 +8,11 @@ + #include + #include + #include ++#include ++#include ++#include + ++#include + #include + + #if IS_ENABLED(CONFIG_IPV6) || IS_ENABLED(CONFIG_INET) +@@ -39,6 +43,102 @@ 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.tsval; ++ ++ ((__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.tsval, 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.16/net/ipv4/Kconfig linux-3.16-knock/net/ipv4/Kconfig +--- linux-3.16/net/ipv4/Kconfig 2014-08-03 18:25:02.000000000 -0400 ++++ linux-3.16-knock/net/ipv4/Kconfig 2014-08-11 07:16:15.968418122 -0400 +@@ -618,3 +618,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.16/net/ipv4/tcp.c linux-3.16-knock/net/ipv4/tcp.c +--- linux-3.16/net/ipv4/tcp.c 2014-08-03 18:25:02.000000000 -0400 ++++ linux-3.16-knock/net/ipv4/tcp.c 2014-08-19 06:17:19.497514011 -0400 +@@ -2443,6 +2443,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. + */ +@@ -2473,6 +2510,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]; ++ ++ if (optlen < MD5_MESSAGE_BYTES) ++ return -EINVAL; ++ ++ val = copy_from_user(secret, optval, 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.tsval = 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; +@@ -2717,6 +2815,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.16/net/ipv4/tcp_input.c linux-3.16-knock/net/ipv4/tcp_input.c +--- linux-3.16/net/ipv4/tcp_input.c 2014-08-03 18:25:02.000000000 -0400 ++++ linux-3.16-knock/net/ipv4/tcp_input.c 2014-08-18 13:08:23.956054243 -0400 +@@ -76,6 +76,9 @@ + #include + + 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; +@@ -3666,6 +3669,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 +@@ -4337,6 +4381,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) + { + const struct tcphdr *th = tcp_hdr(skb); +@@ -4347,6 +4416,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, th->doff * 4); + +@@ -5171,6 +5248,15 @@ void tcp_rcv_established(struct sock *sk + int copied_early = 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->copied_seq == tp->rcv_nxt && + len - tcp_header_len <= tp->ucopy.len) { + #ifdef CONFIG_NET_DMA +diff -Nurp linux-3.16/net/ipv4/tcp_ipv4.c linux-3.16-knock/net/ipv4/tcp_ipv4.c +--- linux-3.16/net/ipv4/tcp_ipv4.c 2014-08-03 18:25:02.000000000 -0400 ++++ linux-3.16-knock/net/ipv4/tcp_ipv4.c 2014-08-19 05:50:27.217441897 -0400 +@@ -76,6 +76,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -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. ++ */ ++ tp->stealth.tsval = tcp_time_stamp; ++ ++ 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, +@@ -1546,6 +1562,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; + #ifdef CONFIG_TCP_MD5SIG + /* +@@ -1576,6 +1594,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.16/net/ipv4/tcp_output.c linux-3.16-knock/net/ipv4/tcp_output.c +--- linux-3.16/net/ipv4/tcp_output.c 2014-08-03 18:25:02.000000000 -0400 ++++ linux-3.16-knock/net/ipv4/tcp_output.c 2014-08-11 07:29:32.776405670 -0400 +@@ -2486,10 +2486,22 @@ int __tcp_retransmit_skb(struct sock *sk + + tcp_retrans_try_collapse(sk, skb, cur_mss); + ++#ifdef CONFIG_TCP_STEALTH ++ if (unlikely(TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN && ++ tp->stealth.mode & TCP_STEALTH_MODE_AUTH)) { ++ /* If TCP stealth is active, reuse the timestamp from the first ++ * SYN. ++ */ ++ TCP_SKB_CB(skb)->when = tp->stealth.tsval; ++ } else { ++ TCP_SKB_CB(skb)->when = tcp_time_stamp; ++ } ++#else + /* Make a copy, if the first transmission SKB clone we made + * is still in somebody's hands, else make a clone. + */ + TCP_SKB_CB(skb)->when = tcp_time_stamp; ++#endif + + /* make sure skb->data is aligned on arches that require it + * and check if ack-trimming & collapsing extended the headroom +@@ -3094,7 +3106,15 @@ int tcp_connect(struct sock *sk) + return -ENOBUFS; + + tcp_init_nondata_skb(buff, tp->write_seq++, TCPHDR_SYN); ++#ifdef CONFIG_TCP_STEALTH ++ /* The timetamp was already set at the time the ISN was generated ++ * as we need to know its value in the stealth_tcp_sequence_number() ++ * function. ++ */ ++ tp->retrans_stamp = TCP_SKB_CB(buff)->when = tp->stealth.tsval; ++#else + tp->retrans_stamp = TCP_SKB_CB(buff)->when = tcp_time_stamp; ++#endif + tcp_connect_queue_skb(sk, buff); + TCP_ECN_send_syn(sk, buff); + +diff -Nurp linux-3.16/net/ipv6/tcp_ipv6.c linux-3.16-knock/net/ipv6/tcp_ipv6.c +--- linux-3.16/net/ipv6/tcp_ipv6.c 2014-08-03 18:25:02.000000000 -0400 ++++ linux-3.16-knock/net/ipv6/tcp_ipv6.c 2014-08-19 06:24:12.497532484 -0400 +@@ -64,6 +64,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -294,6 +295,21 @@ static int tcp_v6_connect(struct sock *s + if (err) + goto late_failure; + ++#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. ++ */ ++ tp->stealth.tsval = tcp_time_stamp; ++ ++ 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, +@@ -1343,7 +1359,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, +@@ -1407,6 +1424,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) diff -r f215c72530a6 -r fa77ea692592 openssh-pam/receipt --- a/openssh-pam/receipt Thu May 17 10:47:21 2018 +0200 +++ b/openssh-pam/receipt Fri May 18 13:47:33 2018 +0200 @@ -21,6 +21,7 @@ # Rules to configure and make the package. compile_rules() { + patch -p1 < ../$SOURCE/stuff/knock.u unset LD # for cross compiling with --disable-strip ./configure \ --prefix=/usr \ diff -r f215c72530a6 -r fa77ea692592 openssh/receipt --- a/openssh/receipt Thu May 17 10:47:21 2018 +0200 +++ b/openssh/receipt Fri May 18 13:47:33 2018 +0200 @@ -21,6 +21,7 @@ # Rules to configure and make the package. compile_rules() { + patch -p1 < $stuff/knock.u unset LD # for cross compiling with --disable-strip ./configure \ --prefix=/usr \ diff -r f215c72530a6 -r fa77ea692592 openssh/stuff/knock.u --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/openssh/stuff/knock.u Fri May 18 13:47:33 2018 +0200 @@ -0,0 +1,504 @@ +From https://gnunet.org/knock : +https://gnunet.org/sites/default/files/openssh-linux-knock-patch.diff +--- a/readconf.c ++++ b/readconf.c +@@ -172,6 +172,9 @@ + oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys, + oFingerprintHash, oUpdateHostkeys, oHostbasedKeyTypes, + oPubkeyAcceptedKeyTypes, oProxyJump, ++#ifdef TCP_STEALTH ++ oTCPStealthSecret, ++#endif + oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported + } OpCodes; + +@@ -305,6 +308,9 @@ + { "pubkeyacceptedkeytypes", oPubkeyAcceptedKeyTypes }, + { "ignoreunknown", oIgnoreUnknown }, + { "proxyjump", oProxyJump }, ++#ifdef TCP_STEALTH ++ { "tcpstealthsecret", oTCPStealthSecret }, ++#endif + + { NULL, oBadOption } + }; +@@ -1669,6 +1675,23 @@ + charptr = &options->identity_agent; + goto parse_string; + ++#ifdef TCP_STEALTH ++ case oTCPStealthSecret: ++ charptr = &options->tcp_stealth_secret; ++ ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", ++ filename, linenum); ++ ++ if (*activep && *charptr == NULL) { ++ *charptr = xmalloc(TCP_STEALTH_SECRET_SIZE + 1); ++ memset(*charptr, 0x00, TCP_STEALTH_SECRET_SIZE + 1); ++ strncpy(*charptr, arg, TCP_STEALTH_SECRET_SIZE); ++ } ++ ++ break; ++#endif + case oDeprecated: + debug("%s line %d: Deprecated option \"%s\"", + filename, linenum, keyword); +@@ -1869,6 +1892,9 @@ + options->update_hostkeys = -1; + options->hostbased_key_types = NULL; + options->pubkey_key_types = NULL; ++#ifdef TCP_STEALTH ++ options->tcp_stealth_secret = NULL; ++#endif + } + + /* +--- a/readconf.h ++++ b/readconf.h +@@ -164,6 +164,10 @@ + char *jump_extra; + + char *ignored_unknown; /* Pattern list of unknown tokens to ignore */ ++ ++#ifdef TCP_STEALTH ++ char *tcp_stealth_secret; ++#endif + } Options; + + #define SSH_CANONICALISE_NO 0 +--- a/servconf.c ++++ b/servconf.c +@@ -165,6 +165,9 @@ + options->fingerprint_hash = -1; + options->disable_forwarding = -1; + options->expose_userauth_info = -1; ++#ifdef TCP_STEALTH ++ options->tcp_stealth_secret = NULL; ++#endif + } + + /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ +@@ -422,6 +425,9 @@ + sStreamLocalBindMask, sStreamLocalBindUnlink, + sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding, + sExposeAuthInfo, ++#ifdef TCP_STEALTH ++ sTCPStealthSecret, ++#endif + sDeprecated, sIgnore, sUnsupported + } ServerOpCodes; + +@@ -566,6 +572,9 @@ + { "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL }, + { "disableforwarding", sDisableForwarding, SSHCFG_ALL }, + { "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL }, ++#ifdef TCP_STEALTH ++ { "tcpstealthsecret", sTCPStealthSecret }, ++#endif + { NULL, sBadOption, 0 } + }; + +@@ -1883,6 +1892,23 @@ + intptr = &options->expose_userauth_info; + goto parse_flag; + ++#ifdef TCP_STEALTH ++ case sTCPStealthSecret: ++ charptr = &options->tcp_stealth_secret; ++ ++ arg = strdelim(&cp); ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: Missing argument.", ++ filename, linenum); ++ ++ if (*activep && *charptr == NULL) { ++ *charptr = xmalloc(TCP_STEALTH_SECRET_SIZE + 1); ++ memset(*charptr, 0x00, TCP_STEALTH_SECRET_SIZE + 1); ++ strncpy(*charptr, arg, TCP_STEALTH_SECRET_SIZE); ++ } ++ ++ break; ++#endif + case sDeprecated: + case sIgnore: + case sUnsupported: +--- a/servconf.h ++++ b/servconf.h +@@ -198,6 +198,10 @@ + + int fingerprint_hash; + int expose_userauth_info; ++ ++#ifdef TCP_STEALTH ++ char *tcp_stealth_secret; ++#endif + } ServerOptions; + + /* Information about the incoming connection as used by Match */ +@@ -219,6 +223,11 @@ + * NB. an option must appear in servconf.c:copy_set_server_options() or + * COPY_MATCH_STRING_OPTS here but never both. + */ ++#ifdef TCP_STEALTH ++#define M_CP_STEALTHSCRT(X) M_CP_STROPT(X); ++#else ++#define M_CP_STEALTHSCRT(X) ++#endif + #define COPY_MATCH_STRING_OPTS() do { \ + M_CP_STROPT(banner); \ + M_CP_STROPT(trusted_user_ca_keys); \ +@@ -238,6 +247,7 @@ + M_CP_STRARRAYOPT(accept_env, num_accept_env); \ + M_CP_STRARRAYOPT(auth_methods, num_auth_methods); \ + M_CP_STRARRAYOPT_ALLOC(permitted_opens, num_permitted_opens); \ ++ M_CP_STEALTHSCRT(tcp_stealth_secret); \ + } while (0) + + struct connection_info *get_connection_info(int, int); +--- a/ssh.c ++++ b/ssh.c +@@ -191,6 +191,14 @@ + extern int muxserver_sock; + extern u_int muxclient_command; + ++#ifdef TCP_STEALTH ++#define OPT_STEALTH "[-z tcp_stealth_secret] " ++#define GETOPT_STEALTH "z:" ++#else ++#define OPT_STEALTH "" ++#define GETOPT_STEALTH "" ++#endif ++ + /* Prints a help message to the user. This function never returns. */ + + static void +@@ -203,7 +211,7 @@ + " [-J [user@]host[:port]] [-L address] [-l login_name] [-m mac_spec]\n" + " [-O ctl_cmd] [-o option] [-p port] [-Q query_option] [-R address]\n" + " [-S ctl_path] [-W host:port] [-w local_tun[:remote_tun]]\n" +-" [user@]hostname [command]\n" ++" " OPT_STEALTH "[user@]hostname [command]\n" + ); + exit(255); + } +@@ -612,7 +620,7 @@ + + again: + while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx" +- "ACD:E:F:GI:J:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) { ++ "ACD:E:F:GI:J:KL:MNO:PQ:R:S:TVw:W:XYy" GETOPT_STEALTH)) != -1) { + switch (opt) { + case '1': + fatal("SSH protocol v.1 is no longer supported"); +@@ -921,6 +929,14 @@ + case 'F': + config = optarg; + break; ++#ifdef TCP_STEALTH ++ case 'z': ++ options.tcp_stealth_secret = ++ xcalloc(TCP_STEALTH_SECRET_SIZE + 1, sizeof(u_int8_t)); ++ strncpy(options.tcp_stealth_secret, optarg, ++ TCP_STEALTH_SECRET_SIZE); ++ break; ++#endif + default: + usage(); + } +--- a/sshd.c ++++ b/sshd.c +@@ -896,6 +896,14 @@ + return (r < p) ? 1 : 0; + } + ++#ifdef TCP_STEALTH ++#define OPT_STEALTH " [-z tcp_stealth_secret]" ++#define GETOPT_STEALTH "z:" ++#else ++#define OPT_STEALTH "" ++#define GETOPT_STEALTH "" ++#endif ++ + static void + usage(void) + { +@@ -911,6 +919,7 @@ + "usage: sshd [-46DdeiqTt] [-C connection_spec] [-c host_cert_file]\n" + " [-E log_file] [-f config_file] [-g login_grace_time]\n" + " [-h host_key_file] [-o option] [-p port] [-u len]\n" ++" " OPT_STEALTH "\n" + ); + exit(1); + } +@@ -1057,6 +1066,15 @@ + if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, + &on, sizeof(on)) == -1) + error("setsockopt SO_REUSEADDR: %s", strerror(errno)); ++#ifdef TCP_STEALTH ++ if (options.tcp_stealth_secret != NULL) { ++ if (setsockopt(listen_sock, IPPROTO_TCP, TCP_STEALTH, ++ options.tcp_stealth_secret, ++ TCP_STEALTH_SECRET_SIZE) == -1) ++ error("setsockopt TCP_STEALTH: %s", ++ strerror(errno)); ++ } ++#endif + + /* Only communicate in IPv6 over AF_INET6 sockets. */ + if (ai->ai_family == AF_INET6) +@@ -1404,7 +1422,7 @@ + + /* Parse command-line arguments. */ + while ((opt = getopt(ac, av, +- "C:E:b:c:f:g:h:k:o:p:u:46DQRTdeiqrt")) != -1) { ++ GETOPT_STEALTH "C:E:b:c:f:g:h:k:o:p:u:46DQRTdeiqrt")) != -1) { + switch (opt) { + case '4': + options.address_family = AF_INET; +@@ -1512,6 +1530,14 @@ + exit(1); + free(line); + break; ++#ifdef TCP_STEALTH ++ case 'z': ++ options.tcp_stealth_secret = ++ xcalloc(TCP_STEALTH_SECRET_SIZE + 1, sizeof(u_int8_t)); ++ strncpy(options.tcp_stealth_secret, optarg, ++ TCP_STEALTH_SECRET_SIZE); ++ break; ++#endif + case '?': + default: + usage(); +--- a/ssh_config.5 ++++ b/ssh_config.5 +@@ -1509,6 +1509,15 @@ + .Pp + To disable TCP keepalive messages, the value should be set to + .Cm no . ++.It Cm TCPStealthSecret ++Specifies the shared secret which is needed to connect to a stealth SSH TCP ++Server. Any string specified will be truncated to or padded with zeroes to 64 ++bytes. This option needs kernel support and is therefore only available if the ++required ++.Xr setsockopt 2 ++call is available. ++.Pp ++See http://datatracker.ietf.org/doc/draft-kirsch-ietf-tcp-stealth/ for details. + .It Cm Tunnel + Request + .Xr tun 4 +--- a/sshd_config.5 ++++ b/sshd_config.5 +@@ -1444,6 +1444,18 @@ + .Pp + To disable TCP keepalive messages, the value should be set to + .Cm no . ++.It Cm TCPStealthSecret ++Turns this SSH server into a stealth SSH TCP server. This configuration option ++specifies the shared secret needed by the clients in order to be able to connect ++to the port the SSH server is listening on. This means that port scanners will ++receive a TCP RST and thus will not recognize this TCP port being open. Any ++string specified will be truncated or padded with zeroes to 64 bytes. This ++option needs kernel support and is therefore only available if the required ++.Xr setsockopt 2 ++call is available. ++.Pp ++See http://datatracker.ietf.org/doc/draft-kirsch-ietf-tcp-stealth/ for details. ++ + .It Cm TrustedUserCAKeys + Specifies a file containing public keys of certificate authorities that are + trusted to sign user certificates for authentication, or +--- a/sshd.0 ++++ b/sshd.0 +@@ -7,6 +7,7 @@ + sshd [-46DdeiqTt] [-C connection_spec] [-c host_certificate_file] + [-E log_file] [-f config_file] [-g login_grace_time] + [-h host_key_file] [-o option] [-p port] [-u len] ++ [-z tcp_stealth_secret] + + DESCRIPTION + sshd (OpenSSH Daemon) is the daemon program for ssh(1). Together these +@@ -121,6 +122,20 @@ + from="pattern-list" option in a key file. Configuration options + that require DNS include using a USER@HOST pattern in AllowUsers + or DenyUsers. ++ -z tcp_stealth_secret ++ Turns this SSH server into a Stealth SSH TCP Server. This option ++ specifies the shared secret which is needed by the clients in order ++ to be able to connect to the port the SSH server is listening on. ++ Any string specified will be truncated or padded with zeroes to 64 ++ bytes. This option needs kernel support and is therefore only ++ available if the required setsockopt() call is available. ++ See http://datatracker.ietf.org/doc/draft-kirsch-ietf-tcp-stealth/ ++ for details. ++ ++ IMPORTANT: This option should only be used for the purpose of ++ testing as other users could easily read out the secret from the ++ command line arguments. The TCPStealthSecret configuration option ++ is the preferred way of specifying the TCP Stealth secret. + + AUTHENTICATION + The OpenSSH SSH daemon supports SSH protocol 2 only. Each host has a +--- openssh-6.7p1/ssh.0 2014-10-05 23:39:37.000000000 -0400 ++++ openssh-6.7p1-knock/ssh.0 2014-11-05 20:35:44.216514377 -0500 +@@ -425,6 +425,20 @@ DESCRIPTION + -y Send log information using the syslog(3) system module. By + default this information is sent to stderr. + ++ -z tcp_stealth_secret ++ Specifies the shared secret which is needed to connect to a stealth ++ SSH TCP server. Any string specified will be truncated to or padded ++ with zeroes to 64 bytes. This option needs kernel support and is ++ therefore only available if the required setsockopt() call is ++ available. ++ See http://datatracker.ietf.org/doc/draft-kirsch-ietf-tcp-stealth/ ++ for details. ++ ++ IMPORTANT: This option should only be used for the purpose of ++ testing as other users could easily read out the secret from the ++ command line arguments. The TCPStealthSecret configuration option ++ is the preferred way of specifying the TCP Stealth secret. ++ + ssh may additionally obtain configuration data from a per-user + configuration file and a system-wide configuration file. The file format + and configuration options are described in ssh_config(5). +--- openssh-6.7p1/ssh.1 2014-07-29 22:32:28.000000000 -0400 ++++ openssh-6.7p1-knock/ssh.1 2014-11-07 13:56:02.022226289 -0500 +@@ -64,6 +64,7 @@ + .Op Fl S Ar ctl_path + .Op Fl W Ar host : Ns Ar port + .Op Fl w Ar local_tun Ns Op : Ns Ar remote_tun ++.Op Fl z Ar tcp_stealth_secret + .Oo Ar user Ns @ Oc Ns Ar hostname + .Op Ar command + .Ek +@@ -528,6 +529,7 @@ For full details of the options listed b + .It StreamLocalBindUnlink + .It StrictHostKeyChecking + .It TCPKeepAlive ++.It TCPStealthSecret + .It Tunnel + .It TunnelDevice + .It UpdateHostKeys +@@ -777,6 +779,21 @@ Send log information using the + .Xr syslog 3 + system module. + By default this information is sent to stderr. ++.It Fl z Ar tcp_stealth_secret ++Specifies the shared secret which is needed to connect to a stealth SSH TCP ++server. Any string specified will be truncated to or padded with zeroes to 64 ++bytes. This option needs kernel support and is therefore only available if the ++required ++.Xr setsockopt 2 ++call is available. ++.Pp ++See http://datatracker.ietf.org/doc/draft-kirsch-ietf-tcp-stealth/ for details. ++.Pp ++.Cm IMPORTANT: ++This option should only be used for the purpose of testing as other users could ++easily read out the secret from the command line arguments. The ++.Cm TCPStealthSecret ++configuration option is the preferred way of specifying the TCP Stealth secret. + .El + .Pp + .Nm +--- openssh-6.7p1/ssh_config.0 2014-10-05 23:39:38.000000000 -0400 ++++ openssh-6.7p1-knock/ssh_config.0 2014-11-05 20:48:17.064514377 -0500 +@@ -919,6 +919,15 @@ DESCRIPTION + + To disable TCP keepalive messages, the value should be set to no. + ++ TCPStealthSecret ++ Specifies the shared secret which is needed to connect to a stealth ++ SSH TCP Server. Any string specified will be truncated to or padded ++ with zeroes to 64 bytes. This option needs kernel support and is ++ therefore only available if the required setsockopt() call is ++ available. ++ See http://datatracker.ietf.org/doc/draft-kirsch-ietf-tcp-stealth/ ++ for details. ++ + Tunnel Request tun(4) device forwarding between the client and the + server. The argument must be yes, point-to-point (layer 3), + ethernet (layer 2), or no (the default). Specifying yes requests +--- openssh-6.7p1/sshconnect.c 2014-07-18 00:11:26.000000000 -0400 ++++ openssh-6.7p1-knock/sshconnect.c 2014-11-07 14:07:11.342196835 -0500 +@@ -286,6 +286,18 @@ ssh_create_socket(int privileged, struct + } + fcntl(sock, F_SETFD, FD_CLOEXEC); + ++#ifdef TCP_STEALTH ++ if (options.tcp_stealth_secret) { ++ if (setsockopt(sock, IPPROTO_TCP, TCP_STEALTH, ++ options.tcp_stealth_secret, ++ TCP_STEALTH_SECRET_SIZE) == -1) { ++ error("setsockopt TCP_STEALTH: %s", strerror(errno)); ++ close(sock); ++ return -1; ++ } ++ } ++#endif ++ + /* Bind the socket to an alternative local IP address */ + if (options.bind_address == NULL && !privileged) + return sock; +--- openssh-6.7p1/sshd.8 2014-07-03 19:00:04.000000000 -0400 ++++ openssh-6.7p1-knock/sshd.8 2014-11-07 14:00:14.506215178 -0500 +@@ -53,6 +53,7 @@ + .Op Fl o Ar option + .Op Fl p Ar port + .Op Fl u Ar len ++.Op Fl z Ar tcp_stealth_secret + .Ek + .Sh DESCRIPTION + .Nm +@@ -243,6 +244,24 @@ USER@HOST pattern in + .Cm AllowUsers + or + .Cm DenyUsers . ++.It Fl z Ar tcp_stealth_secret ++Turns this SSH server into a stealth SSH TCP server. This option specifies the ++shared secret which is needed by the clients in order to be able to connect to ++the port the SSH server is listening on. Any string specified will be truncated ++or padded with zeroes to 64 bytes. This option needs kernel support and is ++therefore only available if the required ++.Xr setsockopt 2 ++call is available. ++.Pp ++See http://datatracker.ietf.org/doc/draft-kirsch-ietf-tcp-stealth/ for details. ++ ++.Cm IMPORTANT: ++This option should only be used for the purpose of ++testing as other users could easily read out the secret from the ++command line arguments. The ++.Cm TCPStealthSecret ++configuration option ++is the preferred way of specifying the TCP Stealth secret. + .El + .Sh AUTHENTICATION + The OpenSSH SSH daemon supports SSH protocol 2 only. +--- openssh-6.7p1/sshd_config.0 2014-10-05 23:39:38.000000000 -0400 ++++ openssh-6.7p1-knock/sshd_config.0 2014-11-07 14:01:07.530212845 -0500 +@@ -872,6 +872,19 @@ DESCRIPTION + + To disable TCP keepalive messages, the value should be set to no. + ++ TCPStealthSecret ++ Turns this SSH server into a stealth SSH TCP server. This ++ configuration option specifies the shared secret needed by the ++ clients in order to be able to connect to the port the SSH server ++ is listening on. This means that port scanners will receive a ++ TCP RST and thus will not recognize this TCP port being open. ++ ++ Any string specified will be truncated or padded with zeroes to 64 ++ bytes. This option needs kernel support and is therefore only ++ available if the required setsockopt() call is available. ++ See http://datatracker.ietf.org/doc/draft-kirsch-ietf-tcp-stealth/ ++ for details. ++ + TrustedUserCAKeys + Specifies a file containing public keys of certificate + authorities that are trusted to sign user certificates for diff -r f215c72530a6 -r fa77ea692592 tazlito/receipt --- a/tazlito/receipt Thu May 17 10:47:21 2018 +0200 +++ b/tazlito/receipt Fri May 18 13:47:33 2018 +0200 @@ -1,7 +1,7 @@ # SliTaz package receipt. PACKAGE="tazlito" -VERSION="498" +VERSION="500" CATEGORY="base-system" SHORT_DESC="SliTaz Live Tool." MAINTAINER="pascal.bellard@slitaz.org"