HTTPS is HTTP over TLS — every byte between client and server is encrypted, authenticated, and integrity-checked. TLS (Transport Layer Security) replaced SSL 3.0 in 1999, yet the term "SSL" persists colloquially. As of 2024, over 95% of web traffic is encrypted via HTTPS according to Google's Transparency Report. TLS 1.3 (RFC 8446), finalized in 2018, reduced the handshake from 2 round-trips to 1 and removed all legacy cipher suites, making connections both faster and more secure.
What Is the Difference Between TLS and SSL?
SSL (Secure Sockets Layer) was developed by Netscape in the 1990s. SSL 3.0 was the last SSL version before it was superseded by TLS 1.0 in 1999. SSL 2.0 and 3.0 have known vulnerabilities (POODLE, DROWN) and are prohibited by RFC 7568. In practice, when someone says "SSL certificate" they mean a TLS certificate. Modern servers should support only TLS 1.2 and TLS 1.3.
| Protocol | Year | Status |
|---|---|---|
| SSL 2.0 | 1995 | Prohibited (insecure) |
| SSL 3.0 | 1996 | Prohibited (POODLE attack) |
| TLS 1.0 | 1999 | Deprecated (2020) |
| TLS 1.1 | 2006 | Deprecated (2020) |
| TLS 1.2 | 2008 | Supported — widely used |
| TLS 1.3 | 2018 | Recommended — current standard |
How Does the TLS Handshake Work?
The TLS handshake establishes a secure connection before any application data is exchanged. TLS 1.3 simplified this to a single round-trip (1-RTT), and supports 0-RTT resumption for repeat connections.
Client Server
│ │
│ ClientHello │
│ + supported cipher suites │
│ + key_share (ECDHE public key) │
│ + supported_versions: TLS 1.3 │
│ ──────────────────────────────────────► │
│ │
│ ServerHello │
│ + selected cipher suite │
│ + key_share (server ECDHE public key) │
│ {EncryptedExtensions} │
│ {Certificate} │
│ {CertificateVerify} │
│ {Finished} │
│ ◄────────────────────────────────────── │
│ │
│ {Finished} │
│ ──────────────────────────────────────► │
│ │
│ ═══ Application Data (encrypted) ═══ │After key exchange, both sides derive symmetric session keys using HKDF. All application data is encrypted with AEAD ciphers (AES-128-GCM, AES-256-GCM, or ChaCha20-Poly1305 in TLS 1.3).
What Are TLS Certificate Types?
Certificates are issued by Certificate Authorities (CAs) and come in three validation levels. The encryption strength is identical across all types — the difference is how thoroughly the CA verifies the applicant's identity.
| Type | Validation | Issuance time | Use case |
|---|---|---|---|
| DV (Domain Validation) | Domain ownership only | Minutes | Blogs, APIs, most websites |
| OV (Organization Validation) | Domain + organization check | Days | Business websites |
| EV (Extended Validation) | Domain + legal entity audit | Weeks | Banks, government portals |
| Wildcard (*.example.com) | Domain (any subdomain) | Minutes–Days | Multi-subdomain setups |
| SAN / Multi-domain | Multiple specific domains | Minutes–Days | Shared hosting, CDNs |
How Does Let's Encrypt Work?
Let's Encrypt is a free, automated CA that issues DV certificates using the ACME (Automatic Certificate Management Environment) protocol. It has issued over 4 billion certificates since launching in 2015. Certificates are valid for 90 days, encouraging automation.
# Install certbot
sudo apt install certbot python3-certbot-nginx
# Obtain and auto-configure for Nginx
sudo certbot --nginx -d example.com -d www.example.com
# Obtain certificate only (manual installation)
sudo certbot certonly --standalone -d example.com
# Auto-renewal (usually set up by default)
sudo certbot renew --dry-run
# Certificate files location
# /etc/letsencrypt/live/example.com/fullchain.pem (cert + intermediates)
# /etc/letsencrypt/live/example.com/privkey.pem (private key)What Is HSTS and Why Does It Matter?
HTTP Strict Transport Security (HSTS) tells browsers to only connect via HTTPS, even if the user types http://. This prevents SSL-stripping attacks where a man-in-the-middle downgrades the connection to plain HTTP.
Strict-Transport-Security: max-age=31536000; includeSubDomains; preloadThe preload directive lets you submit your domain to browser HSTS preload lists (hstspreload.org), hardcoding HTTPS enforcement before the first visit. Once preloaded, removal takes months — only enable this when you are certain all subdomains support HTTPS.
What Is Certificate Pinning?
Certificate pinning binds a host to a specific certificate or public key, rejecting connections even if a valid CA-signed certificate is presented by a different key. This defends against compromised CAs. However, HTTP Public Key Pinning (HPKP) was deprecated in 2018 because misconfiguration caused permanent site lockouts. Modern alternatives include Certificate Transparency (CT) logs and CAA DNS records.
CAA is a regular DNS record type — see DNS explained for how to publish it alongside your A/AAAA and MX records.
# Only Let's Encrypt and Cloudflare can issue certificates for this domain
example.com. CAA 0 issue "letsencrypt.org"
example.com. CAA 0 issue "digicert.com"
example.com. CAA 0 iodef "mailto:security@example.com"What Are Cipher Suites?
A cipher suite is a combination of algorithms used for key exchange, authentication, bulk encryption, and message authentication. TLS 1.3 drastically simplified the options to five secure suites.
TLS_AES_128_GCM_SHA256 # Most common, excellent performance
TLS_AES_256_GCM_SHA384 # 256-bit key, higher security margin
TLS_CHACHA20_POLY1305_SHA256 # Faster on devices without AES-NI
TLS_AES_128_CCM_SHA256 # Constrained IoT environments
TLS_AES_128_CCM_8_SHA256 # Minimal overhead IoT variantFor a full walkthrough of the surrounding directives (server blocks, reverse-proxy headers, gzip/brotli, rate limiting), see the Nginx configuration guide.
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-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}What Is mTLS (Mutual TLS)?
Mutual TLS (mTLS) extends the standard handshake so the client also presents a certificate, letting the server cryptographically verify caller identity instead of relying on bearer tokens or shared secrets. It is the default trust model for service meshes (Istio, Linkerd, Consul) and zero-trust platforms (Cloudflare Access, Tailscale) — every internal request is authenticated end-to-end. For public APIs, mTLS is a strong way to lock down high-value endpoints (banking, B2B webhooks) where you control the client.
server {
listen 443 ssl http2;
server_name api.example.com;
ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
# Trust anchor for client certs (your internal CA bundle)
ssl_client_certificate /etc/nginx/ca/clients-ca.pem;
ssl_verify_client on; # reject the connection if no valid client cert
ssl_verify_depth 2;
}What Are Common TLS Pitfalls?
- Mixed content. An HTTPS page that loads a script, image, or iframe over
http://is blocked by every modern browser. Always use protocol-relative or absolutehttps://URLs, and set aContent-Security-Policy: upgrade-insecure-requestsheader to silently rewrite legacy assets. - Expired certificates with no monitoring. Let's Encrypt certs are 90 days; many outages are simply "cron didn't run." Monitor expiry externally (uptime checks,
openssl s_client -servername host -connect host:443in CI) and alert at T-14 days, not T-0. - Missing intermediate chain. Serving only the leaf certificate works in Chrome (which fetches intermediates) but breaks curl, Java clients, and older mobile devices. Always serve
fullchain.pem, nevercert.pemalone. - Weak DH params. If you still use static DH key exchange, generate a 2048-bit (or larger) parameter file with
openssl dhparam -out dhparam.pem 2048and reference it viassl_dhparam. Better: drop static DH entirely and rely on ECDHE-only suites. ssl_prefer_server_ciphers onon TLS 1.3. The directive is meaningful for TLS 1.2 only; in TLS 1.3 cipher selection is fixed by the spec, so leaving it on does nothing useful and can mask a misconfigured 1.2 cipher list. Set it tooffon modern stacks.
References
- RFC 8446 — The Transport Layer Security (TLS) Protocol Version 1.3
- Mozilla SSL Configuration Generator
- Qualys SSL Labs — SSL Server Test
- Let's Encrypt — Documentation
- HSTS Preload List submission
- Cloudflare Learning Center — Transport Layer Security (TLS)
What's the Minimum TLS Setup for Production?
- • TLS replaced SSL decades ago — disable SSL 3.0 and TLS 1.0/1.1 on all servers
- • TLS 1.3 is the current standard: 1-RTT handshake, no legacy ciphers, forward secrecy by default
- • Use Let's Encrypt with automated renewal for DV certificates
- • Enable HSTS to prevent downgrade attacks; consider preloading for critical domains
- • Use CAA records instead of certificate pinning to restrict which CAs can issue for your domain
- • Test your TLS configuration at
ssllabs.com/ssltest— aim for an A+ rating