How HTTPS and TLS Really Work: A Practical Guide
You've seen the padlock icon in your browser and know HTTPS is important. But do you really understand what happens when a browser connects to an HTTPS site? Many developers treat TLS as a black box—configure it once and forget it. That works until something breaks, performance suffers, or a security audit reveals misconfigurations.
This guide explains HTTPS and TLS in practical terms. You'll learn the handshake process, how certificates establish trust, and the steps to implement TLS correctly on your servers. No jargon overload—just the concepts you need to debug issues and make informed decisions.
What HTTPS Actually Is
HTTPS is HTTP layered on top of TLS (Transport Layer Security). It provides three guarantees:
- Encryption: Data exchanged between client and server is unreadable to eavesdroppers.
- Authentication: The client verifies it's talking to the legitimate server, not an impostor.
- Integrity: Data cannot be modified in transit without detection.
TLS is the protocol that makes this possible. SSL is its predecessor—you'll still see "SSL certificates" in marketing, but modern systems use TLS (currently TLS 1.3 is the latest).
The TLS Handshake: Step by Step
Before any HTTP data flows, the client and server perform a handshake to agree on encryption parameters and verify identities. Here's the simplified flow for TLS 1.3, the modern standard:
- Client Hello: The browser sends a list of supported cipher suites, TLS versions, and a random value (client random).
- Server Hello: The server picks a cipher suite, sends its own random value (server random), and provides its certificate chain.
- Key Exchange: Using ephemeral Diffie-Hellman (or similar), both parties derive a shared secret without transmitting it directly. This provides forward secrecy—compromising the server's private key later won't decrypt past sessions.
- Certificate Verification: The client checks the certificate against trusted root CAs, validates the domain name, and checks expiration and revocation status.
- Finished: Both sides send a MAC (message authentication code) to confirm the handshake wasn't tampered with. Encrypted HTTP traffic begins.
TLS 1.3 reduced the handshake to one round trip (1-RTT) and supports 0-RTT resumption for repeat visitors, improving latency. TLS 1.2 required two round trips.
Certificates: The Trust Anchor
A TLS certificate binds a public key to a domain name and is signed by a Certificate Authority (CA). When your browser connects to example.com, it checks that the certificate:
- Is signed by a CA in its trust store (or chains up to one).
- Matches the domain name (via Subject Alternative Names).
- Is within its validity period.
- Hasn't been revoked (via OCSP or CRL, though enforcement varies).
You can obtain certificates for free from Let's Encrypt, which issues 90-day certificates via the ACME protocol. Automation tools like Certbot handle renewal. For internal services, you can run your own CA, but clients must trust it explicitly.
Configuring TLS on Your Server
Proper configuration balances security, compatibility, and performance. Here's a checklist:
- Use TLS 1.2 and 1.3 only. Disable TLS 1.0 and 1.1—they're deprecated and vulnerable.
- Choose strong cipher suites. Prefer AEAD ciphers like AES-GCM or ChaCha20-Poly1305. Avoid CBC mode and RC4.
- Enable forward secrecy. Use ECDHE key exchange.
- Enable OCSP stapling. The server includes a cached OCSP response, reducing client-side latency and privacy leaks.
- Set HSTS headers. Force browsers to use HTTPS for future visits.
- Redirect HTTP to HTTPS. Ensure no plaintext traffic is served.
For Nginx, a minimal secure configuration looks like this:
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8;
add_header Strict-Transport-Security "max-age=63072000" always;
location / {
proxy_pass http://localhost:3000;
}
}
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
Test your configuration with tools like SSL Labs' SSL Test or testssl.sh. Aim for an A grade, but don't chase perfect scores at the cost of breaking older clients if you must support them.
Common Pitfalls and How to Avoid Them
- Expired certificates: Automate renewal and monitor expiration. A single expired cert can take your site down.
- Mixed content: Loading HTTP resources on an HTTPS page triggers warnings and breaks functionality. Use relative URLs or HTTPS everywhere.
- Weak protocols: TLS 1.0/1.1 are deprecated. Update your configuration.
- Missing intermediate certificates: The server must send the full chain (except the root). Missing intermediates cause trust errors on some clients.
- Improper redirects: Redirect HTTP to HTTPS before serving any content, and use 301 for permanent redirects.
FAQ
What's the difference between HTTPS and TLS?
HTTPS is HTTP over TLS. TLS is the cryptographic protocol that provides encryption, authentication, and integrity. You can't have HTTPS without TLS.
Do I need a separate certificate for www and non-www?
You can include both in the Subject Alternative Names (SAN) field of a single certificate. Most CAs issue certificates covering both by default or with a simple configuration.
How often should I rotate my TLS certificates?
Follow the CA's validity period—90 days for Let's Encrypt. Automate renewal with a cron job or systemd timer. Rotate immediately if a private key is compromised.
Ready to inspect your web traffic? Use the Nginx Log Analyzer to parse access logs and verify HTTPS requests, status codes, and potential issues.