TLS & Certificates How HTTPS works and how ProxyServer decrypts it
This guide explains TLS from first principles — what problem it solves, how certificates create trust, and how ProxyServer intercepts encrypted traffic by becoming a trusted man-in-the-middle.
The Problem HTTPS Solves
HTTP is plaintext. Anyone on the same network (a coffee shop, your ISP, a corporate firewall) can read your traffic:
HTTPS wraps HTTP inside TLS (Transport Layer Security), which provides two things:
- Encryption — The data is scrambled so only the intended recipient can read it
- Authentication — You can verify you're talking to the real server, not an impersonator
How TLS Certificates Work
What Is a Certificate?
A TLS certificate is an electronic document (X.509 format) that binds a public key to a hostname. When you connect to example.com, the server sends its certificate which says "I am example.com, and here is my public key." Your browser uses the public key to set up an encrypted channel.
A certificate contains:
| Field | Example | Purpose |
|---|---|---|
Subject | CN=example.com | Who this certificate belongs to |
Issuer | CN=DigiCert | Who vouches for this certificate |
Public Key | (2048-bit RSA) | Used to establish encrypted channel |
SAN | DNS:example.com, DNS:www.example.com | All hostnames this cert is valid for |
Validity | 2024-01-01 to 2026-01-01 | Expiration dates |
Signature | (SHA-256 with RSA) | Cryptographic proof the issuer approved this |
The Chain of Trust
How does your browser know to trust a certificate? Through a chain of trust:
- Your OS/browser ships with ~150 Root CAs pre-trusted
- The server's certificate says "DigiCert signed me"
- The browser finds DigiCert in its trusted root store
- It verifies the cryptographic signature to confirm DigiCert actually signed it
- If the chain is valid and the hostname matches, the browser shows the lock icon
The TLS Handshake (Simplified)
After the handshake, both sides have agreed on a shared secret key. All subsequent data is encrypted with this key.
How MITM Interception Works
ProxyServer intercepts HTTPS by creating two separate TLS sessions:
Step by Step
-
CONNECT tunnel
The browser sends
CONNECT example.com:443. This is the HTTP method used to establish a tunnel through a proxy. ProxyServer responds with200 Connection Established— the tunnel is open. -
Proxy generates a fake certificate
Instead of blindly tunneling bytes, ProxyServer intercepts the TLS handshake. It generates a certificate for
example.comon the fly, signed by its own CA (certs/ca.crt). Because you've trusted this CA, the browser accepts the fake cert. -
Client-side TLS session
The browser completes its TLS handshake with the proxy, thinking it's talking to
example.com. Data flows encrypted between browser and proxy. -
Server-side TLS session
The proxy opens a separate TLS connection to the real
example.com. It tries HTTP/2 first (via ALPN negotiation), falling back to HTTP/1.1. -
Plaintext in the middle
The proxy decrypts data from the browser, inspects it, logs it to TrafficStore, then re-encrypts and sends it to the real server (and vice versa for responses).
ProxyServer's Certificate System
CA Certificate Generation
On first run, CertManager generates a self-signed root CA:
| Property | Value |
|---|---|
| Algorithm | RSA 2048-bit |
| Common Name | ProxyServer CA |
| Validity | 10 years |
| Extensions | basicConstraints: CA=true, keyUsage: keyCertSign |
| Files | certs/ca.key (private key), certs/ca.crt (certificate) |
certs/ca.key can generate certificates trusted by your system. Never share it. If compromised, remove the CA from your trust store and delete the certs/ directory — a new CA will be generated on next run.
Per-Host Certificate Generation
When you visit example.com through the proxy for the first time:
CertManager.getHostCert("example.com")is called- It checks the memory cache (Map) — cache miss
- It checks the disk cache (
certs/hosts/example.com.key/.crt) — cache miss - It generates a new 2048-bit RSA key pair
- Creates a certificate with:
- Subject:
CN=example.com - Issuer: the CA certificate's subject
- SAN (Subject Alternative Name):
DNS:example.com - Validity: 2 years
- Subject:
- Signs it with the CA's private key
- Caches to disk and memory
Certificate Caching
The first request to a new host takes 200-500ms due to RSA key generation (done in pure JavaScript by node-forge). Subsequent requests are instant.
Trusting the CA Certificate
macOS
# Add to system keychain (covers Chrome + Safari + most apps)
sudo security add-trusted-cert -d -r trustRoot \
-k /Library/Keychains/System.keychain certs/ca.crt
# Verify it was added
security find-certificate -a -c "ProxyServer CA" /Library/Keychains/System.keychain
Firefox
Firefox uses its own certificate store and ignores the system keychain:
- Open Preferences > Privacy & Security
- Scroll to Certificates > click View Certificates
- Go to the Authorities tab
- Click Import and select
certs/ca.crt - Check "Trust this CA to identify websites"
Linux (Chrome/Chromium)
# Ubuntu/Debian
sudo cp certs/ca.crt /usr/local/share/ca-certificates/proxyserver-ca.crt
sudo update-ca-certificates
# For Chrome specifically
certutil -d sql:$HOME/.pki/nssdb -A -t "C,," \
-n "ProxyServer CA" -i certs/ca.crt
Removing the CA
# macOS — remove from system keychain
sudo security remove-trusted-cert -d certs/ca.crt
# Or delete everything and regenerate
rm -rf certs/
node server.js # generates a fresh CA
Troubleshooting
| Problem | Cause | Fix |
|---|---|---|
SEC_ERROR_UNKNOWN_ISSUER in Firefox |
Firefox uses its own cert store | Import ca.crt via Firefox preferences (see above) |
ERR_CERT_AUTHORITY_INVALID in Chrome |
CA not trusted in system keychain | Run the security add-trusted-cert command |
Certificate errors after deleting certs/ |
Old CA was trusted; new CA is different | Remove old CA from trust store, re-trust new one |
| Slow first HTTPS request per host | RSA key generation in pure JS | Normal — subsequent requests use cached cert |
| Certificate pinning errors (mobile apps) | App verifies specific cert, not just CA chain | MITM proxy cannot bypass pinning without app modification |