TCP 3-Way Handshake: How Every Connection Begins [Under the Hood]

hafeez@unixshadow: ~/capture.pcap
hafeez@unixshadow:~$ sudo tcpdump -i eth0 ‘tcp port 443’ # the 3-way handshake, live

TCP 3-Way Handshake
How Every Connection Begins

before a single byte of data moves, both sides synchronize sequence numbers — and prove each direction works.

# the handshake — three packets // 10:24:01
CLOSEDCLIENT
SYN
seq = x
LISTENSERVER

SYN_SENTCLIENT
SYN + ACK
seq = y · ack = x+1
SYN_RCVDSERVER

ESTABLISHEDCLIENT
ACK
ack = y+1
ESTABLISHEDSERVER

both sides proved they can send and receive — data flows now.

# on the wire // what tcpdump actually shows
10:24:01.102431 IP 192.168.1.10.54321 > 203.0.113.7.443: Flags [S], seq 1000, win 64240
10:24:01.143882 IP 203.0.113.7.443 > 192.168.1.10.54321: Flags [S.], seq 5000, ack 1001, win 65160
10:24:01.144005 IP 192.168.1.10.54321 > 203.0.113.7.443: Flags [.], ack 5001, win 502
# [S]=SYN   [S.]=SYN+ACK   [.]=ACK — 42ms round trip, connection ready.
# why three steps?
Two-way sequence sync. Each side picks its own ISN (x and y); both must be acknowledged — a SYN each way plus a final ACK.
Kills stale duplicates. A delayed old SYN can’t trick the server: no matching ACK, no connection.
Two steps leave one direction unverified; four are redundant. Three is the minimum that works.
# teardown — the 4-way goodbye // each direction closes alone
10:31:44.020311 client > server: Flags [F.] # i’m done sending
10:31:44.020709 server > client: Flags [.] # ack — server: CLOSE_WAIT
10:31:44.021105 server > client: Flags [F.] # i’m done too
10:31:44.021330 client > server: Flags [.] # ack — client: TIME_WAIT (2×MSL)
# TIME_WAIT lingers ~60s so stray duplicates can’t corrupt the next connection on the same port pair.
# see it live
# watch handshakes on your own box:
ss -tlnp — sockets and TCP states (SYN-SENT, ESTAB, TIME-WAIT)
sudo tcpdump 'tcp[tcpflags] & tcp-syn != 0' — SYN / SYN-ACK packets only
wireshark filter: tcp.flags.syn == 1, then follow the stream
# field guide // man tcp, condensed
SYN
synchronize — “i want to talk; my initial sequence number is x”
ACK
acknowledgment — “got it; next i expect y+1 from you”
FIN
finish — “i’m done sending” (teardown)
seq
sequence number of this segment’s first byte
ack
the next sequence number i expect from you
ISN
initial sequence number — randomized per connection
unixshadow.com  ·  VPS & hosting from the shadowshafeez@unixshadow:~$

Scroll to Top