Where TLS lives
TLS (Transport Layer Security, RFC 8446 for 1.3) is the layer between TCP and the application:
Application (HTTP, IMAP, SMTP, ...)
│
TLS (encryption + authentication)
│
TCP (reliability)
│
IP / Ethernet
HTTPS is HTTP inside TLS. When a browser opens https://...:
- DNS resolution (see dns-resolution)
- TCP tcp-handshake to port 443
- TLS handshake (see below): new packets inside the TCP connection
- After the handshake, ordinary HTTP exchange with an encrypted payload
TLS 1.3 handshake (simplified)
TLS 1.3 is a one-roundtrip handshake:
Client Server
│ │
│ ── ClientHello ───────────────► │
│ • TLS-versions supported │
│ • cipher-suites supported │
│ • SNI: hostname │
│ • client key share (X25519) │
│ │
│ ◄── ServerHello │
│ • chosen cipher (TLS_AES_256...)│
│ • server key share │
│ ◄── Encrypted Extensions │ (after this everything encrypted)
│ ◄── Certificate │
│ ◄── CertificateVerify │
│ ◄── Finished │
│ │
│ ── Finished ─────────────────► │
│ │
│ ◄═════════════ HTTP data ════════►│
TLS 1.2 required 3 roundtrips and was slower. TLS 1.3 uses 1 roundtrip plus 0-RTT for session resumption.
What happens in the handshake
- Version and cipher negotiation: which encryption algorithm to use (TLS_AES_256_GCM_SHA384, ChaCha20-Poly1305, and others)
- Key exchange: exchange of key material via ECDH (X25519, secp256r1)
- Server authentication: the server presents an x509 certificate; the client verifies the chain up to a known CA
- (Optional) Client authentication: mTLS: the client also sends a certificate
- Derive keys: both sides compute shared keys for encrypting data
- Finished: mutual confirmation that everything completed without MITM
SNI (Server Name Indication)
Server certificates are tied to a domain name. When one IP hosts several sites (virtual hosting), the server does not know which domain to serve until the HTTP request arrives, and HTTP only arrives after the handshake.
The fix is SNI: the client writes the server name in plaintext inside ClientHello. The server picks the correct certificate. This means the hostname is visible to a network observer even in HTTPS, which motivated the development of Encrypted Client Hello (ECH) in newer versions.
Seeing it live
openssl s_client -connect example.com:443 -servername example.com < /dev/null
The output shows the negotiated cipher, the certificate chain, and the verification result.
In [[#cmd-tcpdump|tcpdump]] on port 443 you can see the TLS handshake packets, but the payload is encrypted from ServerHello onward.