Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net-tcp: Fast Open client - cookie-less mode

In trusted networks, e.g., intranet, data-center, the client does not
need to use Fast Open cookie to mitigate DoS attacks. In cookie-less
mode, sendmsg() with MSG_FASTOPEN flag will send SYN-data regardless
of cookie availability.

Signed-off-by: Yuchung Cheng <ycheng@google.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Yuchung Cheng and committed by
David S. Miller
67da22d2 aab48743

+15 -3
+2
Documentation/networking/ip-sysctl.txt
··· 476 476 477 477 The values (bitmap) are: 478 478 1: Enables sending data in the opening SYN on the client 479 + 5: Enables sending data in the opening SYN on the client regardless 480 + of cookie availability. 479 481 480 482 Default: 0 481 483
+1
include/linux/tcp.h
··· 387 387 u8 repair_queue; 388 388 u8 do_early_retrans:1,/* Enable RFC5827 early-retransmit */ 389 389 early_retrans_delayed:1, /* Delayed ER timer installed */ 390 + syn_data:1, /* SYN includes data */ 390 391 syn_fastopen:1; /* SYN includes Fast Open option */ 391 392 392 393 /* RTT measurement */
+1
include/net/tcp.h
··· 214 214 215 215 /* Bit Flags for sysctl_tcp_fastopen */ 216 216 #define TFO_CLIENT_ENABLE 1 217 + #define TFO_CLIENT_NO_COOKIE 4 /* Data in SYN w/o cookie option */ 217 218 218 219 extern struct inet_timewait_death_row tcp_death_row; 219 220
+6 -2
net/ipv4/tcp_input.c
··· 5650 5650 struct tcp_fastopen_cookie *cookie) 5651 5651 { 5652 5652 struct tcp_sock *tp = tcp_sk(sk); 5653 - struct sk_buff *data = tcp_write_queue_head(sk); 5653 + struct sk_buff *data = tp->syn_data ? tcp_write_queue_head(sk) : NULL; 5654 5654 u16 mss = tp->rx_opt.mss_clamp; 5655 5655 bool syn_drop; 5656 5656 ··· 5664 5664 tcp_parse_options(synack, &opt, &hash_location, 0, NULL); 5665 5665 mss = opt.mss_clamp; 5666 5666 } 5667 + 5668 + if (!tp->syn_fastopen) /* Ignore an unsolicited cookie */ 5669 + cookie->len = -1; 5667 5670 5668 5671 /* The SYN-ACK neither has cookie nor acknowledges the data. Presumably 5669 5672 * the remote receives only the retransmitted (regular) SYNs: either ··· 5819 5816 5820 5817 tcp_finish_connect(sk, skb); 5821 5818 5822 - if (tp->syn_fastopen && tcp_rcv_fastopen_synack(sk, skb, &foc)) 5819 + if ((tp->syn_fastopen || tp->syn_data) && 5820 + tcp_rcv_fastopen_synack(sk, skb, &foc)) 5823 5821 return -1; 5824 5822 5825 5823 if (sk->sk_write_pending ||
+5 -1
net/ipv4/tcp_output.c
··· 2864 2864 struct sk_buff *syn_data = NULL, *data; 2865 2865 unsigned long last_syn_loss = 0; 2866 2866 2867 + tp->rx_opt.mss_clamp = tp->advmss; /* If MSS is not cached */ 2867 2868 tcp_fastopen_cache_get(sk, &tp->rx_opt.mss_clamp, &fo->cookie, 2868 2869 &syn_loss, &last_syn_loss); 2869 2870 /* Recurring FO SYN losses: revert to regular handshake temporarily */ ··· 2874 2873 goto fallback; 2875 2874 } 2876 2875 2877 - if (fo->cookie.len <= 0) 2876 + if (sysctl_tcp_fastopen & TFO_CLIENT_NO_COOKIE) 2877 + fo->cookie.len = -1; 2878 + else if (fo->cookie.len <= 0) 2878 2879 goto fallback; 2879 2880 2880 2881 /* MSS for SYN-data is based on cached MSS and bounded by PMTU and ··· 2919 2916 fo->copied = data->len; 2920 2917 2921 2918 if (tcp_transmit_skb(sk, syn_data, 0, sk->sk_allocation) == 0) { 2919 + tp->syn_data = (fo->copied > 0); 2922 2920 NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPFASTOPENACTIVE); 2923 2921 goto done; 2924 2922 }