Hi there! It's BOB.
Last time, we built our very own certificate authority. Everything was green padlocks and happy browsers.
And then one morning… a big red warning. Nothing changed! (Something changed.)
Certificates are like milk: they're great until they quietly aren't. The good news is that almost every certificate problem in a home lab is one of about six things. Let's meet them, and the tools that catch them.
Your Detective Kit
You only need a handful of tools. Keep these close.
certlm.msc # the computer's certificate stores (look for the little key icon!)
pkiview.msc # Enterprise PKI: health of your CA, its CRLs and AIA locations
certutil -verify -urlfetch web01.cer # check the whole chain AND fetch every CRL/AIA URL
certutil -store my # list certs in the computer's Personal store
certutil -crl # publish a fresh revocation list (run on the CA)
From a Linux box, a Mac, or a Proxmox host:
openssl s_client -connect web01.lab.contoso.com:443 -servername web01.lab.contoso.com -showcerts </dev/null
# what does the server ACTUALLY send?
openssl x509 -in web01.crt -noout -subject -issuer -dates -ext subjectAltName
# who, signed by whom, valid when, for which names
And don't forget the browser itself. Click the padlock (or the "Not secure" label) and open Certificate. It tells you a surprising amount.
💡 BOB's tip:
certutil -verify -urlfetchis my favorite tool in the whole box. It walks the entire chain, tries to download every revocation list, and tells you exactly which step failed. Export the certificate to a.cerfile and feed it in.
1. It Expired (or It Isn't Born Yet)
What you see: NET::ERR_CERT_DATE_INVALID, "This certificate has expired," or "not yet valid."
What to check:
- The certificate's dates.
openssl x509 -noout -datesor the Valid from / Valid to fields in the certificate viewer. - The clock! In a lab, this is sneaky. Restore a VM from an old snapshot, or boot one that's been off for a month, and its clock can be way off. A certificate issued "today" looks like it's from the future to a machine that thinks it's last March.
- The CA's own certificate. A certificate can't outlive the CA that signed it. If your root is about to expire, everything under it goes with it.
The fix: renew the certificate (autoenrolled ones renew themselves if the GPO is on; run certutil -pulse to hurry it), and fix the clock. Domain members get their time from the domain controllers, and Kerberos gets cranky too when clocks drift more than five minutes, so time problems rarely come alone.
2. The Name Doesn't Match (Hello, SAN!)
What you see: NET::ERR_CERT_COMMON_NAME_INVALID, or "The certificate is not valid for this name."
This is the number one home lab certificate problem. Here's why: browsers stopped looking at the certificate's Common Name (CN) years ago. Chrome dropped it back in version 58 (2017). Apple did the same in iOS 13 and macOS 10.15. They only look at the Subject Alternative Name (SAN) list.
So a certificate with CN=web01.lab.contoso.com and no SAN fails everywhere, even though the name looks right.
What to check: every name people type must be in the SAN.
| What you typed in the browser | Needs this in the SAN |
|---|---|
https://web01.lab.contoso.com |
DNS: web01.lab.contoso.com |
https://web01 |
DNS: web01 |
https://intranet.lab.contoso.com (an alias) |
DNS: intranet.lab.contoso.com |
https://192.168.50.20 |
IP Address: 192.168.50.20 |
The fix: request a new certificate with all the names in it (Get-Certificate -DnsName name1, name2, name3). Certificates can't be edited after they're issued. That's kind of the whole point of signing them!
💡 BOB's tip: Browsing your lab by IP address? Just… make a DNS record. Your future self, your certificates and your memory will all thank you.
3. Broken Chain: "Unknown Authority"
What you see: NET::ERR_CERT_AUTHORITY_INVALID, "The issuer of this certificate couldn't be found," or "unable to get local issuer certificate."
A certificate is trusted only if the client can build a chain: server certificate → (any intermediate CAs) → a root it already trusts. Break any link and the whole thing falls apart.
What to check:
- Does the client trust your root? Domain members get it automatically from an enterprise CA. Your phone, your Mac, your Linux VMs and that new Proxmox host do not. Install the root on them.
- Does the server send the intermediate? If you built a two-tier PKI, the server should send its certificate plus the issuing CA's certificate.
openssl s_client -showcertsshows exactly what's sent. Windows clients often find a missing intermediate on their own (using the certificate's AIA download link); Linux tools and many appliances won't. - Is it the right root? Rebuilt your CA from scratch? Even with the same name, it's a brand new root with a different key. Old certificates and old trusted roots don't mix with new ones.
The fix: install the root where it's missing; on appliances and Linux web servers, use a "full chain" file (server certificate first, then the intermediate).
4. Revocation Check Failed (The Lab Classic!)
What you see: "The revocation function was unable to check revocation because the revocation server was offline" (0x80092013), or apps like RDP, LDAPS or VPNs suddenly refusing a certificate that looks fine.
Clients check the CA's certificate revocation list (CRL) to make sure a certificate hasn't been cancelled. The CRL has an expiration date of its own. In the lab, the story usually goes like this:
- You turn off the CA VM to save power. (Very responsible!)
- Three weeks go by.
- The CRL expires, and nobody can publish a new one, because the CA is off.
- Things start failing in strange ways.
What to check: pkiview.msc on a domain machine shows every CA, CRL and download location, with red or yellow flags on anything expired or unreachable. certutil -verify -urlfetch shows which URL failed.
The fix: start the CA and run certutil -crl. To avoid round two, make the CRL last longer (see the settings in my AD CS article), or simply leave the CA running. It's a small VM.
⚠️ Heads up: Non-domain machines can't read the CRL from Active Directory (the
ldap://location). They need thehttp://location to actually work. If only your non-Windows devices complain about revocation, that's the reason.
5. "There's No Private Key"
What you see: IIS won't let you pick the certificate, an HTTPS binding fails, or certlm.msc shows the certificate without the little key icon.
A certificate is only half of the pair. The private key is the other half, and it lives on the machine that made the request. If you request on one server and import the .cer on another, the key never made the trip.
The fix:
- Request the certificate on the server that will use it, or
- Export it with the private key as a password-protected
.pfx(the template must allow export) and import that, or - If the key is there and the certificate just lost track of it,
certutil -repairstore my <serial number>reconnects them.
6. Right Certificate, Wrong Job
What you see: a certificate that's valid, trusted and named correctly… still gets rejected.
Every certificate lists what it's allowed to do, in its Enhanced Key Usage (EKU). A web server needs Server Authentication. A certificate made from a "User" template, or one meant only for Client Authentication, won't work for HTTPS.
Apple devices have a few extra house rules for TLS certificates, even ones from your own CA: a Server Authentication EKU, names in the SAN, a SHA-2 signature, RSA keys of 2048 bits or more, and a validity period of 825 days or fewer. A cute five-year lab certificate makes Safari very sad.
The fix: issue from a template made from Web Server or Computer, and keep lifetimes to two years or less.
Bonus Round: Quick Hits
| Symptom | Usual suspect |
|---|---|
| Template doesn't show up when requesting | Not published on the CA, or you lack Read + Enroll on it |
| Autoenrollment does nothing | GPO not applied, or template missing Autoenroll permission. Check Event Viewer → Application for CertificateServicesClient events |
| RDP still shows a warning | It's still using its self-signed certificate. Point the RDP template policy at your template |
| Works in Edge, fails in Firefox | Firefox has its own certificate store. Import the root, or let Firefox read the Windows store |
| New cert installed, old one still served | The app (IIS binding, service, appliance) is still pointed at the old one. Restart or re-bind |
Wrapping Up
When the red warning shows up, run down the list:
- Dates and clocks. Expired, or a time-traveling VM?
- Names. Is what you typed in the SAN?
- Chain. Does the client trust the root? Does the server send the intermediate?
- Revocation. Is the CRL fresh? Was the CA asleep?
- Private key. Is the little key icon there?
- Purpose. Server Authentication EKU, sensible lifetime?
Nine times out of ten, certutil -verify -urlfetch or openssl s_client points right at the culprit. The tenth time, it's the clock. It's always the clock.
See you next time!
— BOB
Sources
- Microsoft Learn: certutil
- Microsoft Learn: Enterprise PKI (pkiview.msc)
- Chromium security-dev: Intent to Remove: Support for commonName matching in certificates
- Apple Support: Requirements for trusted certificates in iOS 13 and macOS 10.15
- OpenSSL docs: openssl-s_client and openssl-x509
- Microsoft Learn: Maximum tolerance for computer clock synchronization (Kerberos)