How the internet works · Lesson 7 · 35 min

TLS & certificates

The padlock in the browser stands for TLS, the layer that turns HTTP into HTTPS. It does two jobs: it encrypts everything, so nobody on the way can read or change it, and it proves who you're talking to, so a fake site can't pretend to be your bank. That second job is all about certificates, and it's where almost every "SSL error" comes from.

You will learn

  • What a certificate says, and who vouches for it (the chain of trust)
  • What happens in a TLS handshake
  • Reading certificates with curl -v, openssl s_client and openssl x509
  • The four classic errors (expired, wrong name, self-signed, missing intermediate) and how to fix each
  • Trusting your own company's certificate authority, on each family

A certificate is a signed ID card

A certificate says "this public key belongs to good.example.com", plus a few facts:

The chain of trust

Your computer can't know every website, so it trusts a small set of root CAs, kept in the system's trust store. Roots don't sign websites directly: they sign an intermediate certificate, and the intermediate signs the site.

ISRG Root X1             # root: already in your trust store
  └─ R11 (Let's Encrypt) # intermediate: the server must send this one
       └─ good.example.com

The server sends its own certificate and the intermediates. Your side checks each signature up to a root it trusts, checks the dates, and checks that the name you asked for is in the SANs. One failed check and the connection stops.

The handshake, briefly

  1. Client hello: "I speak TLS 1.3, these ciphers, and I want good.example.com" (that name is the SNI, so one server can host many HTTPS sites).
  2. Server hello + certificate: the server picks the settings and sends its chain.
  3. The client verifies the chain, both sides agree on a secret key, and from then on everything is encrypted.

curl -v https://… prints every step. The line that matters most is SSL certificate verify ok.

Tools for looking

TryTo…
curl -v https://SITEwatch the handshake and the verdict
openssl s_client -connect SITE:443 -servername SITE </dev/nullsee the whole chain the server sends, and the Verify return code
… -showcertsprint every certificate the server sends (not just the first)
… | openssl x509 -noout -subject -issuer -datesread the site's certificate
openssl x509 -noout -ext subjectAltNamethe names it's valid for
openssl x509 -noout -checkend 2592000"will it expire in the next 30 days?" (perfect for monitoring)

The four classic errors

curl saysOpenSSL codeMeansFix (on the server)
certificate has expired10Past its not after dateRenew it, and make renewal automatic (certbot renew via a timer)
no alternative certificate subject name matches62Valid certificate, but for a different nameGet one with the right name in its SANs (or use the right URL)
self-signed certificate18Signed by itself; nobody vouches for itUse a real CA, or trust your own CA on purpose (below)
unable to get local issuer certificate20The chain can't be built: an intermediate is missing, or the root isn't trustedSend the full chain (fullchain.pem, not cert.pem), or add your CA to the trust store
Don't fix it with -k

curl -k (or verify=False in code) skips the checks. It's handy for one quick look, but it turns off the very thing that stops someone pretending to be the server. Never leave it in a script.

A sneaky one: a missing intermediate often works in a browser (browsers can go and fetch it) but fails in curl, scripts and apps. If "it works for me in Chrome" but not from a server, check the chain with -showcerts.

Trusting your own CA

Companies and clubs often run their own CA for internal sites (like wiki.club.lan), because public CAs won't sign private names. To make a server trust it, add the CA's certificate to the system trust store. This is very Linux-specific:

TaskRocky / RHELUbuntu / Debian
Put the CA certificate in/etc/pki/ca-trust/source/anchors//usr/local/share/ca-certificates/ (the name must end in .crt)
Rebuild the trust storesudo update-ca-trustsudo update-ca-certificates
The bundle apps read/etc/pki/tls/certs/ca-bundle.crt/etc/ssl/certs/ca-certificates.crt
Where private keys usually live/etc/pki/tls/private//etc/ssl/private/

Only add CAs you really trust: a CA in your trust store can vouch for any website, including fake ones.

Try it: the certificate clinic 🔏

Five club websites, five HTTPS problems. Diagnose each one, fix the one you can fix from this server, and set up an early warning for the one that's about to expire.

Quick check

1. A site works in your browser, but curl on a server says "unable to get local issuer certificate". The certificate isn't expired. Most likely?

2. Which part of a certificate does a browser check against the name in the address bar?

3. A colleague "fixes" an HTTPS error in a script by adding -k. What's the problem?

Finished the missions and the quiz? Mark it done to track your progress.