Mental model
TCP is connection-oriented. Before either side can send any data, they have to agree they’re talking to each other and synchronize state — specifically, the sequence numbers each side will use to label its bytes. This agreement is the 3-way handshake.
Three packets. About 1.5 round-trip times. Then ESTABLISHED — actual data can flow.
This is why a fresh TCP connection over a 100 ms link takes ~150 ms before the first byte of HTTP request even leaves the client. Cumulative effect explains why opening a fresh HTTPS page (TCP + TLS handshakes) over satellite or distant transcontinental links feels sluggish.
The three packets
Client Server
│ │
│ ── SYN (seq=100) ───────────────► │ client picks initial seq
│ │
│ ◄── SYN-ACK (seq=500, ack=101) ── │ server picks its own, ACKs client+1
│ │
│ ── ACK (ack=501) ──────────────► │ client ACKs server+1
│ │
│ ◄══════ ESTABLISHED ═══════════► │ data flows both ways
What each flag means:
- SYN (Synchronize): “I want to start a connection. My initial sequence number is X.”
- SYN-ACK (both flags set): “OK. Also, my initial sequence is Y.”
- ACK: “Confirmed.”
Why is the server’s reply called SYN-ACK and not just ACK? Because both directions of the connection need synchronization — server sends its own SYN at the same time as ACKing the client’s.
Sequence numbers — what’s really happening
TCP labels every byte of payload with a sequence number. The handshake establishes the starting point for each direction.
- Client picks ISN_C (Initial Sequence Number) randomly — say 100.
- Server picks ISN_S randomly — say 500.
- After the handshake: client will start its payload at 101, server at 501. Both sides know what to expect.
ISNs are random for security. If they were predictable (early TCP implementations used a simple counter), attackers could inject packets into existing connections without seeing them. Modern stacks use ISN randomization.
Half-open connections and SYN flood attacks
After step 1 (client sends SYN), the server reserves resources (a TCB — Transmission Control Block) for this potential connection. The server is now in SYN_RECV state.
If the client never sends the final ACK (step 3), the server’s reserved resources sit there until a timeout (~60 seconds). This is half-open.
SYN flood attack: an attacker sends thousands of SYN packets from spoofed source IPs. Server reserves a TCB for each. Real clients can’t get connections because the server’s resources are exhausted.
Defense: SYN cookies. Server doesn’t reserve a TCB until step 3 — it encodes connection state into the SYN-ACK’s sequence number, then verifies it when the client’s ACK comes back. No memory used until handshake completes.
R1(config)# tcp synwait-time 10 ! shorter SYN_RECV timeout
Most modern OS stacks enable SYN cookies under attack automatically. Mostly a server-side defense.
Connection teardown — the 4-way (FIN-ACK)
Closing is similar but uses FIN instead of SYN. Each side sends its own FIN — so four packets total in a graceful close:
Client → Server: FIN
Server → Client: ACK
Server → Client: FIN
Client → Server: ACK
Half of the connection can stay open if one side is still sending. RST (reset) is the rude alternative — slams the door, no acknowledgment, no graceful exit. Used when something’s gone wrong.
Capturing it — what Wireshark shows
Filter tcp.flags.syn == 1 && tcp.flags.ack == 0 to find SYN packets only. Look for the three-packet sequence:
| # | Source | Dest | Flags | Seq | Ack |
|---|---|---|---|---|---|
| 1 | client | server | SYN | 100 | — |
| 2 | server | client | SYN, ACK | 500 | 101 |
| 3 | client | server | ACK | 101 | 501 |
| 4 | client | server | PSH, ACK | 101 | 501 |
Open Chrome’s DevTools network tab and you’ll see “Initial connection” timing — that’s the handshake. Add “SSL” timing for the TLS layer on top.
Latency penalty — why fresh connections feel slow
Each round-trip is one full latency cycle. The handshake adds 1.5 RTT (one full RTT for client SYN → server SYN-ACK, plus a half RTT for client ACK). Then:
- HTTP: payload can hitchhike on the ACK → no extra RTT
- HTTPS: TLS adds 1-2 more RTT for the TLS handshake
On a 100 ms link:
| Step | Cumulative time |
|---|---|
| TCP handshake | 150 ms |
| TLS handshake (TLS 1.2) | 350 ms |
| First request / response | 500 ms |
That’s why a fresh HTTPS page on a slow link feels sluggish even when bandwidth is fine. Reusing connections (HTTP keep-alive, TLS session resumption, HTTP/2 multiplexing, QUIC) is how modern protocols dodge this.
Commands — observing TCP state on Cisco
R1# show tcp brief
R1# show tcp brief all ! includes LISTEN ports
R1# show ip sockets
R1# show tcp statistics
Useful for verifying which TCP services are listening on the router (SSH, NETCONF, RESTCONF) and what state existing connections are in.
Common mistakes
-
Thinking TCP guarantees delivery instantly. TCP guarantees eventual delivery (or notifies of failure). Under packet loss, it retransmits — which adds latency. Real-time apps prefer UDP for this reason.
-
Confusing SYN flood with DDoS. SYN flood is one specific kind of DoS. Modern DDoS uses many vectors (HTTP floods, DNS amplification, etc.) — SYN flood is one of the oldest.
-
Assuming RST means hostility. RST happens for many legitimate reasons — packet to a closed port, application restart, firewall rule. Don’t assume malice.
-
Filtering RST/FIN at the firewall thinking it “protects” servers. Drops break TCP teardown — clients can’t tell connections are closed cleanly. Worse experience.
-
Half-open monitoring as “throughput.” Half-open connections aren’t sending data — they’re stuck. Don’t include them in throughput math.
-
Sequence number wrap-around. TCP seq is 32-bit (~4 GB). On 10 Gbps links you can wrap in seconds. TCP timestamps (RFC 7323) handle the wrap; ancient stacks broke under high-speed long-distance links.
Lab to try tonight
- Open Wireshark on your laptop. Start capture.
- Visit any HTTPS site. Stop capture.
- Filter
tcp.flags.syn == 1. Find the SYN packet. - Right-click → “Follow TCP Stream.” See the full conversation.
- Look at the first 3 packets — SYN, SYN-ACK, ACK. Note the seq numbers.
- Find the FIN packets at the end — verify the 4-packet graceful close.
- Compare timing: time between packet 1 (SYN) and packet 2 (SYN-ACK) ≈ your RTT to the server.
Cheat strip
| Concept | Plain English |
|---|---|
| SYN | ”I want to talk” + my starting seq number |
| SYN-ACK | ”OK” + my starting seq number |
| ACK | Final confirmation |
| ESTABLISHED | Both sides synced, data can flow |
| FIN | ”I’m done” (one direction) |
| RST | ”Close immediately” (no graceful exit) |
| ISN | Initial Sequence Number — random for security |
| SYN flood | DoS attack via half-open connections |
| SYN cookies | Defense — don’t reserve resources until step 3 |
| 1.5 RTT | Handshake latency. Plus 1-2 RTT for TLS. |