Two TLS errors, one message
A wrong name and an untrusted issuer look identical in a browser and in curl. One verify code tells them apart, and they have opposite fixes.
During the TLS stage the server hands over a certificate. It says, roughly, “I am shop.bamboo.example, and Bamboo Root CA vouches for me.” Your machine checks two separate things:
- The name. Does the certificate list the name you asked for? Certificates carry their names in a field called the Subject Alternative Name (SAN).
- The trust. Can it follow the chain of signatures up to a root certificate that your machine already trusts? Your operating system and browser ship with a list of trusted roots, the trust store.
- The server hands over its certificate: the names it is valid for, and who signed it.
- Check one: is the name you asked for in its name list? If not, OpenSSL reports 62. The fix is a new certificate.
- Check two follows the signatures upward. Real chains usually have an intermediate between the server and the root.
- The chain must end at a root already in your trust store. If it does not, you get 20. The fix is the trust store, or the chain the server sends.
Fail either one and you get the same scary browser page and the same curl exit code: 60. That sameness is the trap. The two failures have opposite fixes, and fixing the wrong one wastes an afternoon.
Same symptom, different code
OpenSSL’s s_client does tell them apart, with a numbered verify code:
| Verify code | Meaning | Fix |
|---|---|---|
| 62 hostname mismatch | the chain is trusted; the name isn’t on the certificate | edit the certificate: add the name |
| 20 unable to get local issuer certificate | the name is right; nothing you trust signed it | fix the trust store (or the chain the server sends) |
Codes 18 to 21 are the family of trust failures. 18, for example, is a self-signed certificate. The rule from tilt lab 04 is short: 62 means go edit the certificate; 18 to 21 mean go fix the trust store.
curl says exit 60 for your internal site. openssl s_client says 'Verify return code: 62 (hostname mismatch)'. What do you change?
62 means the chain verified, so trust is fine, but the certificate doesn't name the host you asked for. Installing more roots changes nothing. The certificate needs the name.
A brand-new laptop gets code 20 against a site that works on every other machine in the office. Most likely cause?
If the name were wrong, every machine would fail with 62. Failing only on the new laptop with 20 points at that laptop's trust store: it has never been told to trust the issuer.
Everything above ran in your browser. Now do it on a real cluster with tilt lab 04-break-tls (profile minimal). You need Docker, kind and Tilt, about 15 GB of free disk and 8 GB of spare RAM. Setup guide · Can my machine run it?
Tilt lab 04 does this for real, against a certificate that cert-manager issues on your cluster:
./labs/04-break-tls/break.sh mismatch
./labs/04-break-tls/probe.sh hello.localhost # Verify return code: 62
./labs/04-break-tls/fix.sh
./labs/04-break-tls/probe.sh hello.localhost --untrusted # Verify return code: 20
./scripts/platform.sh lab 04Without the platform, the public test site badssl.com has one host per failure:
openssl s_client -connect wrong.host.badssl.com:443 -servername wrong.host.badssl.com -verify_hostname wrong.host.badssl.com </dev/null | grep "Verify return"Sources
Missions and quizzes above earn their own XP. This marks the lesson done.