The TCP Three-Way Handshake, Explained
Introduction¶
Every TCP connection — an HTTPS request, an SSH session, a database query — starts with the same three packets. Understanding them turns a lot of vague "the connection hangs" problems into specific ones: is the SYN even arriving? Is something dropping the SYN-ACK? Is a firewall silently discarding packets instead of rejecting them?
This post shows what the three packets carry and how to watch a handshake happen on your own machine.
Concepts¶
TCP is connection-oriented: before any data moves, both sides agree on a starting sequence number and exchange options like the maximum segment size (MSS) and window scaling. That agreement is the handshake.
Client Server
| SYN seq=x |
| ------------------------------------> |
| SYN, ACK seq=y ack=x+1
| <----------------------------------- |
| ACK seq=x+1 ack=y+1 |
| ------------------------------------> |
| (connection ESTABLISHED) |
- SYN — the client picks a random initial sequence number
xand sets the SYN flag. It also advertises its MSS, window size, and whether it supports options like SACK and timestamps. - SYN-ACK — the server picks its own random sequence number
y, sets SYN and ACK, and acknowledges the client's sequence withack = x + 1. - ACK — the client acknowledges the server's sequence with
ack = y + 1. The connection is nowESTABLISHEDon both ends and data can flow.
The random initial sequence numbers matter for security — a predictable ISN lets an off-path attacker inject data. Modern stacks randomize them per RFC 6528.
Hands-on¶
Watch a handshake¶
In one terminal, capture just the handshake packets to example.com:443:
sudo tcpdump -ni any 'tcp port 443 and (tcp[tcpflags] & (tcp-syn|tcp-ack) != 0)'
In another, make a connection:
curl -sS -o /dev/null https://example.com
You'll see three lines like:
IP 10.0.0.5.51820 > 93.184.216.34.443: Flags [S], seq 1..., win 64240, options [mss 1460,sackOK,TS ...,nop,wscale 7]
IP 93.184.216.34.443 > 10.0.0.5.51820: Flags [S.], seq 2..., ack 1..., win 65535, options [mss 1440,sackOK,TS ...,nop,wscale 10]
IP 10.0.0.5.51820 > 93.184.216.34.443: Flags [.], ack 1...
[S] is SYN, [S.] is SYN-ACK, [.] is a bare ACK. curl adds --connect-timeout 5
if you want to bound how long it waits.
The connection lifecycle¶
# Every socket and its TCP state.
ss -tan
# Watch states change while you connect.
watch -n0.5 "ss -tanp | grep :443"
States you'll see: SYN-SENT (client sent SYN, waiting), SYN-RECV (server
got SYN, sent SYN-ACK), ESTABLISHED, then TIME-WAIT on the side that closed
first.
Verification and troubleshooting¶
Map the symptom to the missing packet:
curlhangs, thenConnection timed out— the SYN left but nothing came back.tcpdumpon the client shows repeated[S]retransmits (roughly at 1s, 2s, 4s, ...). Cause: a firewall or security group that drops (not rejects) the packet, a routing black hole, or the server isn't listening. Check the path withtraceroute -T -p 443 example.com.Connection refusedimmediately — the SYN arrived and the host sent aRSTbecause nothing is bound to that port. The service is down or bound to127.0.0.1only.ss -tlnpon the server.- Handshake completes, then the connection stalls on the first data packet —
almost always an MTU / MSS mismatch. A tunnel (VPN, PPPoE, GRE) lowers the
path MTU, the large packet gets dropped, and ICMP "fragmentation needed" is
filtered so PMTUD can't recover. Clamp the MSS on the router
(
iptables ... TCPMSS --clamp-mss-to-pmtu) or lower the interface MTU. - Intermittent
SYN-RECVpileup on the server — a SYN flood or a slow client.ss -tan state syn-recv | wc -l; enablenet.ipv4.tcp_syncookies. curlconnects but TLS fails — the TCP handshake is fine; the problem is the TLS layer. Check with the SSL/TLS checker.
Related tools and reading¶
- On-site: Port Checker, Ping, Traceroute, SSL/TLS Checker.
- Related posts: Understanding MTU and Path MTU Discovery, DNS resolution, step by step.
Stuck on something this site can't fix?Reach out to Prabath directly on LinkedIn.More in Network Protocols
DHCP DORA: How a Host Gets Its Address
The four DHCP packets, the renewal timers, why relays exist, and the tcpdump filter to watch it happen.
October 24, 2026SMB Versions and Signing, Demystified
SMB1 is a security liability, SMB3 encrypts and signs. Here's how dialect negotiation works and how to tell which one a connection actually used.
October 24, 2026DNS over TLS and DNS over HTTPS
Plain DNS is unencrypted and unauthenticated. DoT and DoH fix the transport — here's how each works, and the trade-off between privacy and network visibility.
October 24, 2026