iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

TLS / HTTPS

TLS encrypts + authenticates connections between client and server. Modern TLS 1.3 is fast, simpler, secure by default. The piece you actually configure: ciphers, certs, HSTS, mutual TLS.

TLS 1.3, certificates, HSTS, mTLS

EXAMPLE
# 1) TLS in brief
# Two parties exchange:
#   1. Cipher suite negotiation (TLS 1.3 simplified this)
#   2. Server certificate (signed by a CA the client trusts)
#   3. Key exchange (ECDHE — ephemeral, forward-secret)
#   4. Symmetric session key — used to encrypt the rest
#
# Result: authenticated channel, confidential, integrity-protected.

# 2) nginx — modern HTTPS config (TLS 1.2 + 1.3)
server {
    listen 443 ssl http2;
    server_name app.example.com;

    ssl_certificate         /etc/letsencrypt/live/app.example.com/fullchain.pem;
    ssl_certificate_key     /etc/letsencrypt/live/app.example.com/privkey.pem;

    # Protocols
    ssl_protocols           TLSv1.2 TLSv1.3;

    # Cipher suites — Mozilla 'intermediate' (broad compat)
    ssl_ciphers             'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
    ssl_prefer_server_ciphers on;

    # Session cache + tickets
    ssl_session_cache       shared:SSL:50m;
    ssl_session_timeout     4h;
    ssl_session_tickets     off;        # rotated tickets are tricky; off is safe default

    # OCSP stapling (faster client validation)
    ssl_stapling            on;
    ssl_stapling_verify     on;
    resolver                1.1.1.1 8.8.8.8 valid=60s;

    # HSTS — force HTTPS for 1 year
    add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload' always;

    location / { proxy_pass http://app:3000; }
}

# 3) Free certificates — Let's Encrypt (certbot)
sudo certbot --nginx -d app.example.com -d www.app.example.com
# Auto-renewal:
sudo systemctl enable --now certbot.timer

# Wildcard via DNS-01 challenge
sudo certbot certonly --manual --preferred-challenges dns -d '*.example.com'
# Or with provider plugin (Route53, Cloudflare, etc.) for automation

# 4) Cert-manager (Kubernetes) — automated certs via Let's Encrypt
# Install cert-manager + define a ClusterIssuer + annotate Ingress.
# Result: automatic issuance + renewal, declarative.

# 5) Test your TLS configuration
#   - https://www.ssllabs.com/ssltest/        — comprehensive grade A-F
#   - testssl.sh                              — local CLI scanner
#   - https://observatory.mozilla.org         — broader security audit

# 6) Modern Node.js HTTPS server
import https from 'node:https';
import fs from 'node:fs';

const server = https.createServer({
    key:  fs.readFileSync('./server.key'),
    cert: fs.readFileSync('./server.crt'),
    ca:   fs.readFileSync('./chain.crt'),   // intermediate certs
    minVersion: 'TLSv1.2',
    maxVersion: 'TLSv1.3',
}, app);

server.listen(443);

# 7) Client — fetch HTTPS in Node
const response = await fetch('https://api.example.com/data');
# Verifies cert by default via system trust store.

# Override trust store (mTLS, self-signed in dev)
import { Agent } from 'undici';
const agent = new Agent({
    connect: {
        ca: fs.readFileSync('./ca.crt'),
        cert: fs.readFileSync('./client.crt'),
        key:  fs.readFileSync('./client.key'),
    },
});
await fetch('https://internal.example.com/', { dispatcher: agent });

# 8) curl with mTLS
curl --cacert ca.crt --cert client.crt --key client.key https://api.example.com

# 9) Mutual TLS (mTLS)
# Both server AND client present + verify certs.
# Use cases:
#   - Service-to-service in zero-trust networks
#   - Sensitive APIs (payment, healthcare)
#   - Industrial / IoT device authentication

# nginx — require client cert
ssl_client_certificate  /etc/ssl/client-ca.crt;
ssl_verify_client       on;
ssl_verify_depth        2;

location /api {
    # Read client cert info
    proxy_set_header X-Client-DN $ssl_client_s_dn;
    proxy_set_header X-Client-Verify $ssl_client_verify;
    proxy_pass http://app:3000;
}

# 10) HSTS — HTTP Strict Transport Security
# Tells browsers: 'Always use HTTPS for this domain; never HTTP'
#
# Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
#
# preload — submit to https://hstspreload.org for browser-baked-in HSTS.
# Once preloaded, even FIRST visit is HTTPS-only.
# WARNING: hard to undo. Test extensively first.

# 11) Common misconfigurations
#   ❌ Weak ciphers: 3DES, RC4, MD5, SHA1
#   ❌ TLS 1.0 / 1.1 enabled (deprecated; PCI requires TLS 1.2+)
#   ❌ Self-signed certs in production
#   ❌ Expired certs (monitor!)
#   ❌ Mismatched CN vs hostname
#   ❌ HSTS without first ensuring HTTPS works everywhere
#   ❌ HTTPS-only header without redirecting HTTP → HTTPS
#   ❌ Wildcard cert reused across teams without rotation

# 12) Modern best practices (2025+)
#   • TLS 1.3 + 1.2 (drop 1.0 + 1.1)
#   • ECDHE + AEAD ciphers (GCM, ChaCha20-Poly1305)
#   • ECDSA P-256 or P-384 certs (smaller, faster than RSA)
#   • OCSP stapling enabled
#   • HSTS with preload
#   • HTTP/2 + HTTP/3 (QUIC) for performance
#   • Forward secrecy ALWAYS (ECDHE — never plain RSA key exchange)
#   • Certificate transparency (CT) — monitor logs (Cert Spotter, crt.sh)
#   • Automatic cert rotation (cert-manager, certbot)

# 13) Performance tips
#   • TLS 1.3 handshake = 1 RTT (vs 2 in 1.2)
#   • Session resumption (tickets / cache) further reduces RTTs
#   • HTTP/2 + 3 reduce connection overhead
#   • CDN at the edge handles TLS termination — origin sees plaintext (or mTLS internally)
#   • Hardware acceleration (AES-NI) on modern CPUs — TLS is essentially free

# 14) Cert renewal monitoring
#   - Alert 30 days before expiry
#   - Alert 7 days before expiry (urgent)
#   - Alert on revocation
# Use: Datadog SSL checks, Pingdom, UptimeRobot, cert-monitor.com

# 15) Certificate Transparency (CT)
# All certs issued by trusted CAs are logged publicly.
# Monitor for unexpected certs in YOUR name:
#   - crt.sh — search by domain
#   - Cert Spotter — alerts on new certs for your domains
# Why: detect rogue CA issuance / phishing infrastructure setup

# 16) Post-quantum readiness
# NIST has selected: ML-KEM (Kyber) for KEM, ML-DSA (Dilithium) for signatures
# Hybrid key exchange (X25519 + ML-KEM) rolling out in TLS 1.3
# Plan: migrate long-term-signed artifacts (PDFs, contracts) first

# 17) Trust store
# What CAs your system trusts: /etc/ssl/certs (Linux), Keychain (macOS), Windows certificate store
# Don't add untrusted CAs — every cert that CA issues becomes valid for you
# Audit periodically

# 18) Common pen-test findings
#   • SSLv3 / TLS 1.0 still enabled
#   • Weak ciphers (3DES, RC4)
#   • Self-signed or expired internal certs
#   • Cert valid for wildcard but app only uses one host (over-broad)
#   • Missing HSTS (browser may downgrade silently)
#   • Heartbleed (CVE-2014-0160) — old OpenSSL still on perimeter devices
#   • CRIME / BREACH compression attacks — TLS compression should be off (default in 1.3)
#   • Predictable cookie / session token — orthogonal to TLS but often paired

# 19) Best practices summary
#   ✅ TLS 1.3 + 1.2 only; ECDHE + AEAD
#   ✅ Let's Encrypt or ACME-based cert issuance
#   ✅ Cert auto-renewal; expiry alerts
#   ✅ HSTS + preload (only after thorough testing)
#   ✅ OCSP stapling
#   ✅ mTLS for service-to-service in zero-trust
#   ✅ Block weak ciphers in CI / runtime config
#   ✅ Monitor CT logs for your domains
#   ✅ Periodic external scans (SSL Labs A+ target)
#   ✅ Plan for post-quantum migration

Why it matters

Let’s Encrypt + TLS 1.3 + HSTS + modern ciphers is the modern web’s default. Pair with cert-manager (Kubernetes) or certbot (servers) for automatic renewal. Aim for SSL Labs A+ — the misconfig costs less than a minute to fix.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
// Run TLS 1.3 only. Auto-renew via certbot / cert-manager / ACME.
// Pin via DNS CAA records. HSTS preload your apex domain.
// Test config at ssllabs.com or testssl.sh.
Try it Yourself »

Discussion

Loading…