I write a TCP client on a Linux 3.15 machine, which is able to use TCP Fast Open:
status = sendto(sd, (const void *) data, data_len, MSG_FASTOPEN,
(const struct sockaddr *) hostref->ai_addr,
sizeof(struct sockaddr_in));
if (status < 0) {
fprintf(stderr, "sendto: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
fprintf(stdout, "TFO connection successful to %s\n",
text_of(hostref->ai_addr));
Using tcpdump, I can check the sending of the TCP Fast Open option and that it does bypass the 3-way handshake (tested with Google's servers).
However, with servers which does not accept TCP fast open, sendto still succeeds, and the message "TFO connection successful" is displayed. Apparently, the Linux kernel code falls back to regular TCP if the server does not support TCP Fast Open (again, checked with tcpdump).
How to find out if my connection used TCP Fast Open or not?
TCP Fast Open is an extension to speed up the opening of successive TCP connections between two endpoints. It works by using a TFO cookie (a TCP option), which is a cryptographic cookie stored on the client and set upon the initial connection with the server.
TCP Fast Open (TFO) is an optional mechanism within TCP that lets endpoints that have established a full TCP connection in the past eliminate a round-trip of the handshake and send data right away.
The server generates a unique cookie and encrypts it using the IP address of the client so that each client has a unique cookie. In the options filed server sends the cookie to the client. So, using the options field client and server let each other know that they support TFO and share cookies.
The general consensus appears to be that TLS 1.3 in 0-RTT mode over TCP in Fast-Open mode (TFO) is secure in terms of CIA as long as you trust the CA system and treat the early data as being potentially part of a reply attack. In particular there are concerns regarding replayability for both TFO and TLS 1.3 0-RTT.
By looking at the patch set that added TCP fast open in the linux kernel, you notice that it wasn't added any external indication that fast open was used.
You can indirectly notice certain cases where fast open was not used and certain cases where fast open was definitely used.
The case that you are sure fast open was not used is when the value of the TCPFastOpenActive counter was not incremented in /proc/net/netstat after a successful sendto() connection:
+ if (tcp_transmit_skb(sk, syn_data, 0, sk->sk_allocation) == 0) {
+ NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPFASTOPENACTIVE);
+ goto done;
+ }
The case that you are sure fast open was used is when you have a non-blocking socket, you already have a fast open cookie and sendto() does not return EINPROGRESS:
For non-blocking socket, it returns the number of bytes queued (and transmitted in the SYN-data packet) if cookie is available. If cookie is not available, it transmits a data-less SYN packet with Fast Open cookie request option and returns -EINPROGRESS like connect().
For the remaining case, that is, you don't have a cookie, but you were able to connect and TCPFastOpenActive was incremented, you can't say if fast open was used (TCPFastOpenActive increment was caused by your fast open) or if fast open was not used (TCPFastOpenActive increment was not caused by your fast open).
http://kernelnewbies.org/Linux_3.6#head-ac78950a7b57d92d5835642926f0e147c680b99c
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=cf60af03ca4e71134206809ea892e49b92a88896
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/diff/net/ipv4/tcp_output.c?id=783237e8daf13481ee234997cbbbb823872ac388
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With