user@techdebt:~/blog$_
$ cd ..

Anatomy of an HTTPS Request

Client CLOSED :49152 Server LISTEN :443 SYN SYN-ACK ACK ✓ Connection ESTABLISHED Client Server network
$ packet inspector
click Step or Play to inspect packets
$ simulation.log

why does TCP need a handshake?

UDP fires packets and hopes for the best. TCP can’t do that. It guarantees delivery, ordering, and flow control. Before any of that works, both sides need to agree on a few things:

  • “Are you there?” the client needs to confirm the server is listening
  • Sequence numbers each side picks a random starting number to track packets (protects against stale connections and spoofing)
  • Receive window how much data the receiver can buffer

The handshake solves all three in exactly three packets. No more, no less.

step by step

1. SYN (Client → Server)

The client picks a random initial sequence number (ISN), say seq=100, and sends a SYN (synchronize) packet. The client moves to SYN_SENT state and starts a retransmission timer.

2. SYN-ACK (Server → Client)

The server receives the SYN, picks its own ISN (seq=300), and acknowledges the client’s sequence number by setting ack=101 (client’s seq + 1). It sends this back as a SYN-ACK and moves to SYN_RCVD.

3. ACK (Client → Server)

The client receives the SYN-ACK, confirms the server’s sequence number with ack=301, and sends the final ACK. Both sides move to ESTABLISHED.

Data can now flow in both directions.

sequence numbers matter

The ISN isn’t 0. It’s a random 32-bit number, and that’s deliberate:

  1. Stale segments. If a previous connection used seq=0, a delayed packet from that connection could be misinterpreted. Random ISNs make collisions astronomically unlikely.
  2. Spoofing protection. An attacker who can’t see the traffic can’t guess the sequence number to inject packets into the stream.

Modern OS kernels use time-based or cryptographic ISN generation (RFC 6528) to make prediction infeasible.

after the handshake

Once TCP is established, the simulation shows what comes next. For HTTPS, two more layers stack on top:

TLS 1.3 negotiates encryption. Client and server exchange cryptographic parameters (ClientHello / ServerHello), verify the server’s identity with a certificate, and derive shared session keys. TLS 1.3 does this in a single round-trip, half of what TLS 1.2 needed.

HTTP/1.1 then carries your actual request: GET /, headers, cookies, all encrypted inside TLS, which is segmented inside TCP. Each layer wraps the one above it. The packet inspector in the simulation shows this encapsulation. Click any HTTP step and you’ll see all three layers at once.