wok view linux/stuff/linux-tcp_stealth.u @ rev 24958
updated nbd (3.20 -> 3.24)
author | Hans-G?nter Theisgen |
---|---|
date | Sat Apr 23 16:50:32 2022 +0100 (2022-04-23) |
parents | |
children |
line source
1 From https://gnunet.org/knock :
2 https://gnunet.org/sites/default/files/tcp_stealth_3.16_1.diff
3 Signed-off-by: Julian Kirsch <kirschju@sec.in.tum.de>
4 ---
5 diff -Nurp linux-3.16/include/linux/tcp.h linux-3.16-knock/include/linux/tcp.h
6 --- linux-3.16/include/linux/tcp.h 2014-08-03 18:25:02.000000000 -0400
7 +++ linux-3.16-knock/include/linux/tcp.h 2014-08-19 06:15:42.329509665 -0400
8 @@ -20,6 +20,7 @@
10 #include <linux/skbuff.h>
11 #include <linux/dmaengine.h>
12 +#include <linux/cryptohash.h>
13 #include <net/sock.h>
14 #include <net/inet_connection_sock.h>
15 #include <net/inet_timewait_sock.h>
16 @@ -325,6 +326,21 @@ struct tcp_sock {
17 struct tcp_md5sig_info __rcu *md5sig_info;
18 #endif
20 +#ifdef CONFIG_TCP_STEALTH
21 +/* Stealth TCP socket configuration */
22 + struct {
23 + #define TCP_STEALTH_MODE_AUTH BIT(0)
24 + #define TCP_STEALTH_MODE_INTEGRITY BIT(1)
25 + #define TCP_STEALTH_MODE_INTEGRITY_LEN BIT(2)
26 + int mode;
27 + u8 secret[MD5_MESSAGE_BYTES];
28 + int integrity_len;
29 + u16 integrity_hash;
30 + u32 tsval;
31 + bool saw_tsval;
32 + } stealth;
33 +#endif
34 +
35 /* TCP fastopen related information */
36 struct tcp_fastopen_request *fastopen_req;
37 /* fastopen_rsk points to request_sock that resulted in this big
38 diff -Nurp linux-3.16/include/net/secure_seq.h linux-3.16-knock/include/net/secure_seq.h
39 --- linux-3.16/include/net/secure_seq.h 2014-08-03 18:25:02.000000000 -0400
40 +++ linux-3.16-knock/include/net/secure_seq.h 2014-08-19 05:52:22.389447048 -0400
41 @@ -14,5 +14,10 @@ u64 secure_dccp_sequence_number(__be32 s
42 __be16 sport, __be16 dport);
43 u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
44 __be16 sport, __be16 dport);
45 +#ifdef CONFIG_TCP_STEALTH
46 +u32 tcp_stealth_do_auth(struct sock *sk, struct sk_buff *skb);
47 +u32 tcp_stealth_sequence_number(struct sock *sk, __be32 *daddr,
48 + u32 daddr_size, __be16 dport);
49 +#endif
51 #endif /* _NET_SECURE_SEQ */
52 diff -Nurp linux-3.16/include/net/tcp.h linux-3.16-knock/include/net/tcp.h
53 --- linux-3.16/include/net/tcp.h 2014-08-03 18:25:02.000000000 -0400
54 +++ linux-3.16-knock/include/net/tcp.h 2014-08-11 07:16:15.968418122 -0400
55 @@ -442,6 +442,12 @@ void tcp_parse_options(const struct sk_b
56 struct tcp_options_received *opt_rx,
57 int estab, struct tcp_fastopen_cookie *foc);
58 const u8 *tcp_parse_md5sig_option(const struct tcphdr *th);
59 +#ifdef CONFIG_TCP_STEALTH
60 +const bool tcp_parse_tsval_option(u32 *tsval, const struct tcphdr *th);
61 +int tcp_stealth_integrity(u16 *hash, u8 *secret, u8 *payload, int len);
62 +#define be32_isn_to_be16_av(x) (((__be16 *)&x)[0])
63 +#define be32_isn_to_be16_ih(x) (((__be16 *)&x)[1])
64 +#endif
66 /*
67 * TCP v4 functions exported for the inet6 API
68 diff -Nurp linux-3.16/include/uapi/linux/tcp.h linux-3.16-knock/include/uapi/linux/tcp.h
69 --- linux-3.16/include/uapi/linux/tcp.h 2014-08-03 18:25:02.000000000 -0400
70 +++ linux-3.16-knock/include/uapi/linux/tcp.h 2014-08-11 07:16:15.968418122 -0400
71 @@ -112,6 +112,9 @@ enum {
72 #define TCP_FASTOPEN 23 /* Enable FastOpen on listeners */
73 #define TCP_TIMESTAMP 24
74 #define TCP_NOTSENT_LOWAT 25 /* limit number of unsent bytes in write queue */
75 +#define TCP_STEALTH 26
76 +#define TCP_STEALTH_INTEGRITY 27
77 +#define TCP_STEALTH_INTEGRITY_LEN 28
79 struct tcp_repair_opt {
80 __u32 opt_code;
81 diff -Nurp linux-3.16/net/core/secure_seq.c linux-3.16-knock/net/core/secure_seq.c
82 --- linux-3.16/net/core/secure_seq.c 2014-08-03 18:25:02.000000000 -0400
83 +++ linux-3.16-knock/net/core/secure_seq.c 2014-08-19 06:19:31.241519904 -0400
84 @@ -8,7 +8,11 @@
85 #include <linux/ktime.h>
86 #include <linux/string.h>
87 #include <linux/net.h>
88 +#include <linux/socket.h>
89 +#include <linux/ip.h>
90 +#include <linux/ipv6.h>
92 +#include <net/tcp.h>
93 #include <net/secure_seq.h>
95 #if IS_ENABLED(CONFIG_IPV6) || IS_ENABLED(CONFIG_INET)
96 @@ -39,6 +43,102 @@ static u32 seq_scale(u32 seq)
97 }
98 #endif
100 +#ifdef CONFIG_TCP_STEALTH
101 +u32 tcp_stealth_sequence_number(struct sock *sk, __be32 *daddr,
102 + u32 daddr_size, __be16 dport)
103 +{
104 + struct tcp_sock *tp = tcp_sk(sk);
105 + struct tcp_md5sig_key *md5;
106 +
107 + __u32 sec[MD5_MESSAGE_BYTES / sizeof(__u32)];
108 + __u32 i;
109 + __u32 tsval = 0;
110 +
111 + __be32 iv[MD5_DIGEST_WORDS] = { 0 };
112 + __be32 isn;
113 +
114 + memcpy(iv, (const __u8 *)daddr,
115 + (daddr_size > sizeof(iv)) ? sizeof(iv) : daddr_size);
116 +
117 +#ifdef CONFIG_TCP_MD5SIG
118 + md5 = tp->af_specific->md5_lookup(sk, sk);
119 +#else
120 + md5 = NULL;
121 +#endif
122 + if (likely(sysctl_tcp_timestamps && !md5) || tp->stealth.saw_tsval)
123 + tsval = tp->stealth.tsval;
124 +
125 + ((__be16 *)iv)[2] ^= cpu_to_be16(tp->stealth.integrity_hash);
126 + iv[2] ^= cpu_to_be32(tsval);
127 + ((__be16 *)iv)[6] ^= dport;
128 +
129 + for (i = 0; i < MD5_DIGEST_WORDS; i++)
130 + iv[i] = le32_to_cpu(iv[i]);
131 + for (i = 0; i < MD5_MESSAGE_BYTES / sizeof(__le32); i++)
132 + sec[i] = le32_to_cpu(((__le32 *)tp->stealth.secret)[i]);
133 +
134 + md5_transform(iv, sec);
135 +
136 + isn = cpu_to_be32(iv[0]) ^ cpu_to_be32(iv[1]) ^
137 + cpu_to_be32(iv[2]) ^ cpu_to_be32(iv[3]);
138 +
139 + if (tp->stealth.mode & TCP_STEALTH_MODE_INTEGRITY)
140 + be32_isn_to_be16_ih(isn) =
141 + cpu_to_be16(tp->stealth.integrity_hash);
142 +
143 + return be32_to_cpu(isn);
144 +}
145 +EXPORT_SYMBOL(tcp_stealth_sequence_number);
146 +
147 +u32 tcp_stealth_do_auth(struct sock *sk, struct sk_buff *skb)
148 +{
149 + struct tcp_sock *tp = tcp_sk(sk);
150 + struct tcphdr *th = tcp_hdr(skb);
151 + __be32 isn = th->seq;
152 + __be32 hash;
153 + __be32 *daddr;
154 + u32 daddr_size;
155 +
156 + tp->stealth.saw_tsval = tcp_parse_tsval_option(&tp->stealth.tsval, th);
157 +
158 + if (tp->stealth.mode & TCP_STEALTH_MODE_INTEGRITY_LEN)
159 + tp->stealth.integrity_hash =
160 + be16_to_cpu(be32_isn_to_be16_ih(isn));
161 +
162 + switch (tp->inet_conn.icsk_inet.sk.sk_family) {
163 +#if IS_ENABLED(CONFIG_IPV6)
164 + case PF_INET6:
165 + daddr_size = sizeof(ipv6_hdr(skb)->daddr.s6_addr32);
166 + daddr = ipv6_hdr(skb)->daddr.s6_addr32;
167 + break;
168 +#endif
169 + case PF_INET:
170 + daddr_size = sizeof(ip_hdr(skb)->daddr);
171 + daddr = &ip_hdr(skb)->daddr;
172 + break;
173 + default:
174 + pr_err("TCP Stealth: Unknown network layer protocol, stop!\n");
175 + return 1;
176 + }
177 +
178 + hash = tcp_stealth_sequence_number(sk, daddr, daddr_size, th->dest);
179 + cpu_to_be32s(&hash);
180 +
181 + if (tp->stealth.mode & TCP_STEALTH_MODE_AUTH &&
182 + tp->stealth.mode & TCP_STEALTH_MODE_INTEGRITY_LEN &&
183 + be32_isn_to_be16_av(isn) == be32_isn_to_be16_av(hash))
184 + return 0;
185 +
186 + if (tp->stealth.mode & TCP_STEALTH_MODE_AUTH &&
187 + !(tp->stealth.mode & TCP_STEALTH_MODE_INTEGRITY_LEN) &&
188 + isn == hash)
189 + return 0;
190 +
191 + return 1;
192 +}
193 +EXPORT_SYMBOL(tcp_stealth_do_auth);
194 +#endif
195 +
196 #if IS_ENABLED(CONFIG_IPV6)
197 __u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr,
198 __be16 sport, __be16 dport)
199 diff -Nurp linux-3.16/net/ipv4/Kconfig linux-3.16-knock/net/ipv4/Kconfig
200 --- linux-3.16/net/ipv4/Kconfig 2014-08-03 18:25:02.000000000 -0400
201 +++ linux-3.16-knock/net/ipv4/Kconfig 2014-08-11 07:16:15.968418122 -0400
202 @@ -618,3 +618,13 @@ config TCP_MD5SIG
203 on the Internet.
205 If unsure, say N.
206 +
207 +config TCP_STEALTH
208 + bool "TCP: Stealth TCP socket support"
209 + default n
210 + ---help---
211 + This option enables support for stealth TCP sockets. If you do not
212 + know what this means, you do not need it.
213 +
214 + If unsure, say N.
215 +
216 diff -Nurp linux-3.16/net/ipv4/tcp.c linux-3.16-knock/net/ipv4/tcp.c
217 --- linux-3.16/net/ipv4/tcp.c 2014-08-03 18:25:02.000000000 -0400
218 +++ linux-3.16-knock/net/ipv4/tcp.c 2014-08-19 06:17:19.497514011 -0400
219 @@ -2443,6 +2443,43 @@ static int tcp_repair_options_est(struct
220 return 0;
221 }
223 +#ifdef CONFIG_TCP_STEALTH
224 +int tcp_stealth_integrity(__be16 *hash, u8 *secret, u8 *payload, int len)
225 +{
226 + struct scatterlist sg[2];
227 + struct crypto_hash *tfm;
228 + struct hash_desc desc;
229 + __be16 h[MD5_DIGEST_WORDS * 2];
230 + int i;
231 + int err = 0;
232 +
233 + tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC);
234 + if (IS_ERR(tfm)) {
235 + err = -PTR_ERR(tfm);
236 + goto out;
237 + }
238 + desc.tfm = tfm;
239 + desc.flags = 0;
240 +
241 + sg_init_table(sg, 2);
242 + sg_set_buf(&sg[0], secret, MD5_MESSAGE_BYTES);
243 + sg_set_buf(&sg[1], payload, len);
244 +
245 + if (crypto_hash_digest(&desc, sg, MD5_MESSAGE_BYTES + len, (u8 *)h)) {
246 + err = -EFAULT;
247 + goto out;
248 + }
249 +
250 + *hash = be16_to_cpu(h[0]);
251 + for (i = 1; i < MD5_DIGEST_WORDS * 2; i++)
252 + *hash ^= be16_to_cpu(h[i]);
253 +
254 +out:
255 + crypto_free_hash(tfm);
256 + return err;
257 +}
258 +#endif
259 +
260 /*
261 * Socket option code for TCP.
262 */
263 @@ -2473,6 +2510,67 @@ static int do_tcp_setsockopt(struct sock
264 release_sock(sk);
265 return err;
266 }
267 +#ifdef CONFIG_TCP_STEALTH
268 + case TCP_STEALTH: {
269 + u8 secret[MD5_MESSAGE_BYTES];
270 +
271 + if (optlen < MD5_MESSAGE_BYTES)
272 + return -EINVAL;
273 +
274 + val = copy_from_user(secret, optval, MD5_MESSAGE_BYTES);
275 + if (val != 0)
276 + return -EFAULT;
277 +
278 + lock_sock(sk);
279 + memcpy(tp->stealth.secret, secret, MD5_MESSAGE_BYTES);
280 + tp->stealth.mode = TCP_STEALTH_MODE_AUTH;
281 + tp->stealth.tsval = 0;
282 + tp->stealth.saw_tsval = false;
283 + release_sock(sk);
284 + return err;
285 + }
286 + case TCP_STEALTH_INTEGRITY: {
287 + u8 *payload;
288 +
289 + lock_sock(sk);
290 +
291 + if (!(tp->stealth.mode & TCP_STEALTH_MODE_AUTH)) {
292 + err = -EOPNOTSUPP;
293 + goto stealth_integrity_out_1;
294 + }
295 +
296 + if (optlen < 1 || optlen > USHRT_MAX) {
297 + err = -EINVAL;
298 + goto stealth_integrity_out_1;
299 + }
300 +
301 + payload = vmalloc(optlen);
302 + if (!payload) {
303 + err = -ENOMEM;
304 + goto stealth_integrity_out_1;
305 + }
306 +
307 + val = copy_from_user(payload, optval, optlen);
308 + if (val != 0) {
309 + err = -EFAULT;
310 + goto stealth_integrity_out_2;
311 + }
312 +
313 + err = tcp_stealth_integrity(&tp->stealth.integrity_hash,
314 + tp->stealth.secret, payload,
315 + optlen);
316 + if (err)
317 + goto stealth_integrity_out_2;
318 +
319 + tp->stealth.mode |= TCP_STEALTH_MODE_INTEGRITY;
320 +
321 +stealth_integrity_out_2:
322 + vfree(payload);
323 +stealth_integrity_out_1:
324 + release_sock(sk);
325 + return err;
326 + }
327 +#endif
328 default:
329 /* fallthru */
330 break;
331 @@ -2717,6 +2815,18 @@ static int do_tcp_setsockopt(struct sock
332 tp->notsent_lowat = val;
333 sk->sk_write_space(sk);
334 break;
335 +#ifdef CONFIG_TCP_STEALTH
336 + case TCP_STEALTH_INTEGRITY_LEN:
337 + if (!(tp->stealth.mode & TCP_STEALTH_MODE_AUTH)) {
338 + err = -EOPNOTSUPP;
339 + } else if (val < 1 || val > USHRT_MAX) {
340 + err = -EINVAL;
341 + } else {
342 + tp->stealth.integrity_len = val;
343 + tp->stealth.mode |= TCP_STEALTH_MODE_INTEGRITY_LEN;
344 + }
345 + break;
346 +#endif
347 default:
348 err = -ENOPROTOOPT;
349 break;
350 diff -Nurp linux-3.16/net/ipv4/tcp_input.c linux-3.16-knock/net/ipv4/tcp_input.c
351 --- linux-3.16/net/ipv4/tcp_input.c 2014-08-03 18:25:02.000000000 -0400
352 +++ linux-3.16-knock/net/ipv4/tcp_input.c 2014-08-18 13:08:23.956054243 -0400
353 @@ -76,6 +76,9 @@
354 #include <net/netdma.h>
356 int sysctl_tcp_timestamps __read_mostly = 1;
357 +#ifdef CONFIG_TCP_STEALTH
358 +EXPORT_SYMBOL(sysctl_tcp_timestamps);
359 +#endif
360 int sysctl_tcp_window_scaling __read_mostly = 1;
361 int sysctl_tcp_sack __read_mostly = 1;
362 int sysctl_tcp_fack __read_mostly = 1;
363 @@ -3666,6 +3669,47 @@ static bool tcp_fast_parse_options(const
364 return true;
365 }
367 +#ifdef CONFIG_TCP_STEALTH
368 +/* Parse only the TSVal field of the TCP Timestamp option header.
369 + */
370 +const bool tcp_parse_tsval_option(u32 *tsval, const struct tcphdr *th)
371 +{
372 + int length = (th->doff << 2) - sizeof(*th);
373 + const u8 *ptr = (const u8 *)(th + 1);
374 +
375 + /* If the TCP option is too short, we can short cut */
376 + if (length < TCPOLEN_TIMESTAMP)
377 + return false;
378 +
379 + while (length > 0) {
380 + int opcode = *ptr++;
381 + int opsize;
382 +
383 + switch (opcode) {
384 + case TCPOPT_EOL:
385 + return false;
386 + case TCPOPT_NOP:
387 + length--;
388 + continue;
389 + case TCPOPT_TIMESTAMP:
390 + opsize = *ptr++;
391 + if (opsize != TCPOLEN_TIMESTAMP || opsize > length)
392 + return false;
393 + *tsval = get_unaligned_be32(ptr);
394 + return true;
395 + default:
396 + opsize = *ptr++;
397 + if (opsize < 2 || opsize > length)
398 + return false;
399 + }
400 + ptr += opsize - 2;
401 + length -= opsize;
402 + }
403 + return false;
404 +}
405 +EXPORT_SYMBOL(tcp_parse_tsval_option);
406 +#endif
407 +
408 #ifdef CONFIG_TCP_MD5SIG
409 /*
410 * Parse MD5 Signature option
411 @@ -4337,6 +4381,31 @@ err:
412 return -ENOMEM;
413 }
415 +#ifdef CONFIG_TCP_STEALTH
416 +static int __tcp_stealth_integrity_check(struct sock *sk, struct sk_buff *skb)
417 +{
418 + struct tcphdr *th = tcp_hdr(skb);
419 + struct tcp_sock *tp = tcp_sk(sk);
420 + u16 hash;
421 + __be32 seq = cpu_to_be32(TCP_SKB_CB(skb)->seq - 1);
422 + char *data = skb->data + th->doff * 4;
423 + int len = skb->len - th->doff * 4;
424 +
425 + if (len < tp->stealth.integrity_len)
426 + return 1;
427 +
428 + if (tcp_stealth_integrity(&hash, tp->stealth.secret, data,
429 + tp->stealth.integrity_len))
430 + return 1;
431 +
432 + if (be32_isn_to_be16_ih(seq) != cpu_to_be16(hash))
433 + return 1;
434 +
435 + tp->stealth.mode &= ~TCP_STEALTH_MODE_INTEGRITY_LEN;
436 + return 0;
437 +}
438 +#endif
439 +
440 static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
441 {
442 const struct tcphdr *th = tcp_hdr(skb);
443 @@ -4347,6 +4416,14 @@ static void tcp_data_queue(struct sock *
444 if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq)
445 goto drop;
447 +#ifdef CONFIG_TCP_STEALTH
448 + if (unlikely(tp->stealth.mode & TCP_STEALTH_MODE_INTEGRITY_LEN) &&
449 + __tcp_stealth_integrity_check(sk, skb)) {
450 + tcp_reset(sk);
451 + goto drop;
452 + }
453 +#endif
454 +
455 skb_dst_drop(skb);
456 __skb_pull(skb, th->doff * 4);
458 @@ -5171,6 +5248,15 @@ void tcp_rcv_established(struct sock *sk
459 int copied_early = 0;
460 bool fragstolen = false;
462 +#ifdef CONFIG_TCP_STEALTH
463 + if (unlikely(tp->stealth.mode &
464 + TCP_STEALTH_MODE_INTEGRITY_LEN) &&
465 + __tcp_stealth_integrity_check(sk, skb)) {
466 + tcp_reset(sk);
467 + goto discard;
468 + }
469 +#endif
470 +
471 if (tp->copied_seq == tp->rcv_nxt &&
472 len - tcp_header_len <= tp->ucopy.len) {
473 #ifdef CONFIG_NET_DMA
474 diff -Nurp linux-3.16/net/ipv4/tcp_ipv4.c linux-3.16-knock/net/ipv4/tcp_ipv4.c
475 --- linux-3.16/net/ipv4/tcp_ipv4.c 2014-08-03 18:25:02.000000000 -0400
476 +++ linux-3.16-knock/net/ipv4/tcp_ipv4.c 2014-08-19 05:50:27.217441897 -0400
477 @@ -76,6 +76,7 @@
478 #include <net/secure_seq.h>
479 #include <net/tcp_memcontrol.h>
480 #include <net/busy_poll.h>
481 +#include <net/secure_seq.h>
483 #include <linux/inet.h>
484 #include <linux/ipv6.h>
485 @@ -235,6 +236,21 @@ int tcp_v4_connect(struct sock *sk, stru
486 sk->sk_gso_type = SKB_GSO_TCPV4;
487 sk_setup_caps(sk, &rt->dst);
489 +#ifdef CONFIG_TCP_STEALTH
490 + /* If CONFIG_TCP_STEALTH is defined, we need to know the timestamp as
491 + * early as possible and thus move taking the snapshot of tcp_time_stamp
492 + * here.
493 + */
494 + tp->stealth.tsval = tcp_time_stamp;
495 +
496 + if (!tp->write_seq && likely(!tp->repair) &&
497 + unlikely(tp->stealth.mode & TCP_STEALTH_MODE_AUTH))
498 + tp->write_seq = tcp_stealth_sequence_number(sk,
499 + &inet->inet_daddr,
500 + sizeof(inet->inet_daddr),
501 + usin->sin_port);
502 +#endif
503 +
504 if (!tp->write_seq && likely(!tp->repair))
505 tp->write_seq = secure_tcp_sequence_number(inet->inet_saddr,
506 inet->inet_daddr,
507 @@ -1546,6 +1562,8 @@ static struct sock *tcp_v4_hnd_req(struc
508 */
509 int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
510 {
511 + struct tcp_sock *tp = tcp_sk(sk);
512 + struct tcphdr *th = tcp_hdr(skb);
513 struct sock *rsk;
514 #ifdef CONFIG_TCP_MD5SIG
515 /*
516 @@ -1576,6 +1594,15 @@ int tcp_v4_do_rcv(struct sock *sk, struc
517 if (skb->len < tcp_hdrlen(skb) || tcp_checksum_complete(skb))
518 goto csum_err;
520 +#ifdef CONFIG_TCP_STEALTH
521 + if (sk->sk_state == TCP_LISTEN && th->syn && !th->fin &&
522 + unlikely(tp->stealth.mode & TCP_STEALTH_MODE_AUTH) &&
523 + tcp_stealth_do_auth(sk, skb)) {
524 + rsk = sk;
525 + goto reset;
526 + }
527 +#endif
528 +
529 if (sk->sk_state == TCP_LISTEN) {
530 struct sock *nsk = tcp_v4_hnd_req(sk, skb);
531 if (!nsk)
532 diff -Nurp linux-3.16/net/ipv4/tcp_output.c linux-3.16-knock/net/ipv4/tcp_output.c
533 --- linux-3.16/net/ipv4/tcp_output.c 2014-08-03 18:25:02.000000000 -0400
534 +++ linux-3.16-knock/net/ipv4/tcp_output.c 2014-08-11 07:29:32.776405670 -0400
535 @@ -2486,10 +2486,22 @@ int __tcp_retransmit_skb(struct sock *sk
537 tcp_retrans_try_collapse(sk, skb, cur_mss);
539 +#ifdef CONFIG_TCP_STEALTH
540 + if (unlikely(TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN &&
541 + tp->stealth.mode & TCP_STEALTH_MODE_AUTH)) {
542 + /* If TCP stealth is active, reuse the timestamp from the first
543 + * SYN.
544 + */
545 + TCP_SKB_CB(skb)->when = tp->stealth.tsval;
546 + } else {
547 + TCP_SKB_CB(skb)->when = tcp_time_stamp;
548 + }
549 +#else
550 /* Make a copy, if the first transmission SKB clone we made
551 * is still in somebody's hands, else make a clone.
552 */
553 TCP_SKB_CB(skb)->when = tcp_time_stamp;
554 +#endif
556 /* make sure skb->data is aligned on arches that require it
557 * and check if ack-trimming & collapsing extended the headroom
558 @@ -3094,7 +3106,15 @@ int tcp_connect(struct sock *sk)
559 return -ENOBUFS;
561 tcp_init_nondata_skb(buff, tp->write_seq++, TCPHDR_SYN);
562 +#ifdef CONFIG_TCP_STEALTH
563 + /* The timetamp was already set at the time the ISN was generated
564 + * as we need to know its value in the stealth_tcp_sequence_number()
565 + * function.
566 + */
567 + tp->retrans_stamp = TCP_SKB_CB(buff)->when = tp->stealth.tsval;
568 +#else
569 tp->retrans_stamp = TCP_SKB_CB(buff)->when = tcp_time_stamp;
570 +#endif
571 tcp_connect_queue_skb(sk, buff);
572 TCP_ECN_send_syn(sk, buff);
574 diff -Nurp linux-3.16/net/ipv6/tcp_ipv6.c linux-3.16-knock/net/ipv6/tcp_ipv6.c
575 --- linux-3.16/net/ipv6/tcp_ipv6.c 2014-08-03 18:25:02.000000000 -0400
576 +++ linux-3.16-knock/net/ipv6/tcp_ipv6.c 2014-08-19 06:24:12.497532484 -0400
577 @@ -64,6 +64,7 @@
578 #include <net/secure_seq.h>
579 #include <net/tcp_memcontrol.h>
580 #include <net/busy_poll.h>
581 +#include <net/secure_seq.h>
583 #include <linux/proc_fs.h>
584 #include <linux/seq_file.h>
585 @@ -294,6 +295,21 @@ static int tcp_v6_connect(struct sock *s
586 if (err)
587 goto late_failure;
589 +#ifdef CONFIG_TCP_STEALTH
590 + /* If CONFIG_TCP_STEALTH is defined, we need to know the timestamp as
591 + * early as possible and thus move taking the snapshot of tcp_time_stamp
592 + * here.
593 + */
594 + tp->stealth.tsval = tcp_time_stamp;
595 +
596 + if (!tp->write_seq && likely(!tp->repair) &&
597 + unlikely(tp->stealth.mode & TCP_STEALTH_MODE_AUTH))
598 + tp->write_seq = tcp_stealth_sequence_number(sk,
599 + sk->sk_v6_daddr.s6_addr32,
600 + sizeof(sk->sk_v6_daddr),
601 + inet->inet_dport);
602 +#endif
603 +
604 if (!tp->write_seq && likely(!tp->repair))
605 tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32,
606 sk->sk_v6_daddr.s6_addr32,
607 @@ -1343,7 +1359,8 @@ out:
608 static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
609 {
610 struct ipv6_pinfo *np = inet6_sk(sk);
611 - struct tcp_sock *tp;
612 + struct tcp_sock *tp = tcp_sk(sk);
613 + struct tcphdr *th = tcp_hdr(skb);
614 struct sk_buff *opt_skb = NULL;
616 /* Imagine: socket is IPv6. IPv4 packet arrives,
617 @@ -1407,6 +1424,13 @@ static int tcp_v6_do_rcv(struct sock *sk
618 if (skb->len < tcp_hdrlen(skb) || tcp_checksum_complete(skb))
619 goto csum_err;
621 +#ifdef CONFIG_TCP_STEALTH
622 + if (sk->sk_state == TCP_LISTEN && th->syn && !th->fin &&
623 + tp->stealth.mode & TCP_STEALTH_MODE_AUTH &&
624 + tcp_stealth_do_auth(sk, skb))
625 + goto reset;
626 +#endif
627 +
628 if (sk->sk_state == TCP_LISTEN) {
629 struct sock *nsk = tcp_v6_hnd_req(sk, skb);
630 if (!nsk)