TCP Three-Way Handshake
Last updated:
Before a single byte of application data moves, TCP performs a three-packet exchange that synchronizes sequence numbers in both directions. Every web request, SSH session, and BGP peering starts exactly like this.
The exchange
Step by step:
- SYN — the client picks a random initial sequence number
xand asks to synchronize. It also advertises its window size and options (MSS, SACK, window scaling). - SYN-ACK — the server acknowledges
x+1("I have your number") and picks its own initial sequence numbery. - ACK — the client acknowledges
y+1. Both sides now agree on both sequence spaces, and the connection isESTABLISHED.
Why three packets and not two? Because reliability must work both ways: each side has to prove it received the other's initial sequence number. Two packets would only confirm one direction.
TCP flags cheat sheet
| Flag | Name | Set when… |
|---|---|---|
| SYN | Synchronize | Opening a connection (first two packets only) |
| ACK | Acknowledgment | Practically every packet after the first SYN |
| FIN | Finish | Graceful close — each side sends its own FIN |
| RST | Reset | Abort: closed port, half-open teardown, policy |
| PSH | Push | Deliver to the application without buffering |
| URG | Urgent | Rare today; urgent pointer is valid |
Seeing it in tcpdump
$ tcpdump -n -i en0 'tcp port 443 and host example.com'
IP 192.168.1.10.54321 > 93.184.216.34.443: Flags [S], seq 1201375243, win 65535, options [mss 1460,sackOK,TS], length 0
IP 93.184.216.34.443 > 192.168.1.10.54321: Flags [S.], seq 3630864200, ack 1201375244, win 65535, length 0
IP 192.168.1.10.54321 > 93.184.216.34.443: Flags [.], ack 3630864201, win 2058, length 0[S] is SYN, [S.] is SYN-ACK (tcpdump shows ACK as a dot), [.] is the final ACK. Note each ack value is the peer's seq + 1.
The full TCP state machine (expand)
The handshake is just the top of TCP's connection state machine:
TIME_WAIT lingering for 2×MSL (often 60s) is why a busy client can exhaust ephemeral ports — and why SO_REUSEADDR exists.
SYN floods
An attacker who sends SYNs and never completes step 3 fills the server's half-open connection queue — a classic DoS. Modern stacks mitigate with SYN cookies: the server encodes the connection state into its sequence number y instead of allocating memory, and only commits resources when the final ACK proves the client is real.