Reading — step 1 of 5
Read
TLS Termination
HTTPS has to be decrypted somewhere. Where you put that boundary is an architecture decision, and the LB is the usual answer:
Client ---HTTPS---> Load Balancer ---HTTP---> Backend Pool
(decrypt here)
Terminate at the LB and you centralize the hard parts: one place to install and renew certificates, one place to enforce TLS versions and cipher policy, and — critically for this course — the LB can see the plaintext request, which is what makes every L7 feature (path routing, header rules, sticky cookies) possible. The costs: LB-to-backend traffic is cleartext (keep it on a private network, or re-encrypt), and the LB's private keys become your crown jewels.
The alternatives you'll meet in production: TLS passthrough (an L4 balancer forwards encrypted bytes untouched; backends terminate — no L7 features possible), and end-to-end with mTLS, where the LB terminates client TLS but speaks mutual TLS to backends — both sides present certificates. Service meshes (Istio, Linkerd) run mTLS between every pair of services as the basis of zero-trust networking.
SNI: many certificates, one IP
A TLS server must present its certificate before any HTTP bytes flow — so how does one IP serve example.com and other.io with different certs? SNI (Server Name Indication): the client puts the hostname it wants, in cleartext, inside the very first handshake message.
ClientHello: server_name = "api.example.com"
LB: look up cert for "api.example.com" -> present it -> handshake completes
Every LB therefore maintains exactly the data structure you're about to build: a table from hostname patterns to certificates, consulted once per handshake. (Cleartext SNI leaks which site you're visiting; Encrypted ClientHello (ECH) is the in-progress fix — good to know, out of scope here.)
Wildcard rules — the part with sharp edges
Certificates may cover *.example.com, but a wildcard matches exactly one label, only the left-most one (RFC 6125 and CA/Browser Forum rules):
*.example.commatchesapi.example.com✔- it does NOT match
a.b.example.com(two labels) ✘ - it does NOT match the bare apex
example.com✘
That's why real deployments hold both an apex cert and a wildcard, and why "just get a wildcard" doesn't cover v1.api.example.com unless it's literally *.api.example.com. Match priority is: exact hostname first, then wildcard, then a default certificate (what nginx serves from its default_server block when nothing matches — clients then see a hostname-mismatch warning, but the handshake completes).
Your exercise
Implement lookup() in the starter's CertTable. CERT <pattern> <name> registers (or replaces) a pattern; LOOKUP <hostname> resolves: exact match first, else the one-level wildcard *.<everything after the first label>, else the literal string default. LIST prints <pattern> -> <name> sorted by pattern (note * sorts before letters, so wildcards list first).
Grader traps, all from real tests:
- One level only. With
*.example.comregistered,LOOKUP a.example.com→wildbutLOOKUP a.b.example.com→default. If you match any suffix, you fail. - Wildcards don't cover the apex. With only
*.api.example.comregistered,LOOKUP v1.api.example.com→api_wild, butLOOKUP api.example.com→default. - Exact beats wildcard. With both
*.example.com -> wildandapi.example.com -> exact,LOOKUP api.example.com→exact, andweb.example.comstill getswild. - Re-registration replaces.
CERT a.com firstthenCERT a.com second: lookups returnsecondandLISTshows one line,a.com -> second.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…