Updated 9 hours ago
Every TCP connection begins with a problem: two machines that have never met need to agree on a shared starting point before they can communicate reliably. The Internet between them is hostile—packets get lost, duplicated, reordered, and delayed. How do you establish trust in an untrustworthy medium?
The answer is the three-way handshake.
Why the Handshake Exists
TCP guarantees that data arrives in order, without gaps, with errors detected. To deliver on this promise, TCP assigns a sequence number to every byte of data. When packets arrive out of order, the receiver reorders them. When packets go missing, the receiver knows exactly which bytes to request again.
But sequence numbers only work if both sides agree on where to start counting. If the client thinks the sequence starts at 100 and the server thinks it starts at 5000, they'll never agree on what's been received.
The three-way handshake synchronizes these starting points. It's the minimum number of exchanges required for both sides to confirm they're working from the same numbers.
The Three Steps
Step 1: SYN (Synchronize)
The client sends a packet with the SYN flag set, announcing: "I want to connect. My sequence numbers will start at X."
The starting number (called the Initial Sequence Number, or ISN) is chosen randomly. Why random? Because old packets from previous connections might still be floating around the Internet. If every connection started at zero, a delayed packet from an old connection could be mistaken for data in the new one. Random starting points make this collision astronomically unlikely.
The SYN packet also includes the client's maximum segment size (how large packets can be) and window size (how much data it can buffer).
Step 2: SYN-ACK (Synchronize-Acknowledge)
The server responds with a packet that does two things at once:
- Acknowledges the client's SYN: "I received your starting number X. I'm ready for X+1."
- Sends its own SYN: "My sequence numbers will start at Y."
Combining these into one packet is why it's a three-way handshake instead of four. The server could send separate "I acknowledge you" and "Here's my number" packets, but merging them saves a round trip.
Step 3: ACK (Acknowledge)
The client completes the handshake by acknowledging the server's sequence number: "I received your starting number Y. I'm ready for Y+1."
Now both sides have synchronized. The client knows where the server is counting from; the server knows where the client is counting from. Data transfer can begin.
What the Handshake Looks Like
The acknowledgment number is always "your sequence number plus one"—meaning "I've received everything up to that point and I'm ready for the next byte."
When Handshakes Fail
No one's listening. If no application is bound to the requested port, the server sends a RST (reset) packet: "There's nothing here. Go away." The connection attempt ends immediately.
The SYN gets lost. The client sends SYN, but it never arrives. After a timeout (typically 3 seconds), the client tries again. Most systems retry several times with exponentially increasing waits before giving up. This is why connection timeouts can take 30+ seconds—the system is being patient with an unreliable network.
A firewall silently drops the packet. From the client's perspective, this looks identical to packet loss. The SYN disappears into the void. No response ever comes. The client waits, retries, waits longer, retries again, and eventually gives up. Some firewalls send RST packets instead, which at least fails fast.
The client disappears mid-handshake. The server receives SYN, responds with SYN-ACK, and waits for ACK. But the client has crashed, lost network connectivity, or simply vanished. The server sits there with resources allocated for a connection that will never complete. TCP's keepalive mechanisms eventually detect and clean up these half-open connections, but it takes time.
The SYN Flood Attack
The handshake has a vulnerability, and attackers exploit it ruthlessly.
Here's the problem: when a server receives a SYN, it allocates memory to track the pending connection—storing the client's sequence number, the port, and other state. The server does this before the handshake completes, because it needs to remember the client's information to send the SYN-ACK.
An attacker exploits this by sending thousands of SYN packets with fake source addresses. The server dutifully responds to each one with SYN-ACK, allocating resources for connections that will never complete. The acknowledgments fly off to spoofed addresses that either don't exist or didn't ask for them. The server waits for final ACKs that will never arrive.
Eventually the server's connection queue fills up. When legitimate users try to connect, there's no room for them. The server is overwhelmed not by traffic, but by its own politeness—allocating resources for every stranger who knocks.
The defense is clever. SYN cookies let the server avoid storing anything until the final ACK arrives. Instead of remembering the client's information, the server encodes it cryptographically in the sequence number it sends back. When the client returns the ACK, the server can decode the original connection parameters from the acknowledgment. If the ACK never comes, the server has lost nothing—it never allocated resources in the first place.
The server stops remembering visitors and instead writes the entry ticket on their forehead. Only those who return with a valid ticket get in.
Frequently Asked Questions About the TCP Three-Way Handshake
Was this page helpful?