hop 21 of 32 · 6 min
Opening and closing a connection
TCP is connection oriented, which means both ends agree to start before any data moves, and agree to stop afterwards.
Three way handshake
client server
|------- SYN, seq=x --------->| I want to talk, my numbering starts at x
|<-- SYN-ACK, seq=y, ack=x+1 -| agreed, mine starts at y, I got yours
|------- ACK, ack=y+1 ------->| I got yours
| connected |Three messages, not two, because both directions need their starting sequence number acknowledged and each direction is numbered independently.
The initial sequence numbers are random, not zero. Predictable numbers allow an attacker to inject data into a connection without seeing it, which was a real attack in the 1990s.
The cost is one full round trip before any data. On a 150ms link that is 150ms before the first byte, which is why connection reuse matters so much and why QUIC combines the transport and encryption handshakes into one.
Four way close
|------- FIN ------->| I am finished sending
|<------ ACK --------| acknowledged
|<------ FIN --------| so am I
|------- ACK ------->| acknowledgedFour rather than three, because a connection is two independent streams. One side can stop sending while still receiving, which is a half close, and is what a shell pipeline relies on.
TIME_WAIT
After closing, the initiating side waits about two minutes in TIME_WAIT before releasing the port.
It looks like waste and is not. It exists so that a delayed packet from the old connection cannot arrive and be accepted by a new connection reusing the same port pair, and so a lost final acknowledgement can be resent.
$ netstat -an | grep TIME_WAIT | wc -l
28431A busy server shows thousands, which is normal. Running out of ports because of it is a real failure, and the fixes are connection reuse and SO_REUSEADDR rather than disabling the wait, which reintroduces the problem it prevents.
SYN flood
An attacker sends many SYNs and never completes the handshake. Each one makes the server allocate state for a half open connection, and the table fills.
SYN cookies are the defence: encode the connection state into the sequence number itself and allocate nothing until the final ACK returns carrying it back. No state, nothing to exhaust.