The browser shows a red page and the user is stuck behind it. If all you see is "SSL error" and you don't know which of dozens of possible cases it is, this text was written for that exact moment. First you need to read the error code, because each code has a different cause and their treatments aren't the same.
Read the error code first, then touch the server
The browser never lies, but it says things very briefly. In Chrome, by clicking the "Advanced" button, or in Firefox with "Advanced," you'll see a line of code. Memorize these codes:
ERR_CERT_DATE_INVALIDmeans the certificate has expired or the server clock is wrong.ERR_CERT_COMMON_NAME_INVALIDmeans the domain name doesn't match the certificate.ERR_CERT_AUTHORITY_INVALIDmeans the certificate chain is incomplete or a self-signed certificate is installed.ERR_CERT_REVOKEDmeans the issuer has revoked the certificate.ERR_SSL_PROTOCOL_ERRORmeans TLS was never established at all, not that the certificate is bad.
The difference between these two categories matters. The first three are about the certificate itself; the last one is about web server configuration. If you mix these up, you'll waste hours.
Silent expiration; the most common SSL error on Iranian sites
Let's Encrypt certificates are ninety days, and their automatic renewal sometimes breaks silently. Your site was fine until yesterday, and this morning everything is red. The usual cause is one of these: the renewal cron job didn't run, port 80 is closed and the HTTP-01 challenge failed, or the DNS record changed and validation broke.
To see the expiration date from the server itself:
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -dates -subject -issuer
Look at the notAfter output. If the date has passed, that's the problem. If the date is correct but the browser still shows an error, move on to the chain.
Check the server clock
I once saw a server whose clock was 40 minutes behind treat a healthy certificate as expired. Check with timedatectl status, and if it says System clock synchronized: no, get systemd-timesyncd running. This error leaves no trace in the logs and only shows up in the browser.
Incomplete chain; an error that only appears in some browsers
This case is annoying. The site opens on your laptop, but a customer on an Android phone gets an error. The cause: you haven't installed the fullchain.pem file and have only put the server certificate. Desktop browsers pull the intermediate certificate from their own cache; fresh clients don't have this cache.
To see the chain:
openssl s_client -connect example.com:443 -showcerts
If you see only one -----BEGIN CERTIFICATE----- in the output, the chain is incomplete. In Nginx, ssl_certificate must point to the fullchain file, not the cert file:
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
In Apache, set SSLCertificateChainFile separately as well. If you use a panel, look for the "Install Chain" or "CA Bundle" option and paste the contents of chain.pem right there.
Name mismatch; when the certificate was issued for a different domain
The ERR_CERT_COMMON_NAME_INVALID error has three common causes. First, the certificate was issued only for example.com but the user opens www.example.com. Second, you've used a wildcard certificate that only covers one subdomain level; *.example.com includes shop.example.com but doesn't cover a.shop.example.com. Third, you've changed the domain and the old certificate is still on the server.
The correct solution is to issue a certificate with both names. With certbot:
certbot certonly --nginx -d example.com -d www.example.com
If the number of subdomains is large, get a wildcard, but be aware that it requires DNS-01 validation and you must add a temporary TXT record. This is where people make a mistake: they add the TXT record, validation succeeds, then they don't delete the record, and next month when renewal is supposed to run, it fails because the TXT value has changed. The sign is that manual renewal works but automatic doesn't.
Server-side SSL error; where the browser says nothing
Sometimes the site won't come up over HTTPS and the browser just times out. Here you need to look from the server side. With curl -vI https://example.com, see where the handshake stops. If you see the message no shared cipher, it means the server only accepts TLS 1.3 and the old client has nothing to agree on.
A balanced configuration for Nginx:
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
Let me tell you the cost: if you fully close TLS 1.0 and 1.1, users with Android 4 or Windows XP can no longer connect. For domestic sites with an older audience, this is a hard decision. On public sites, I set TLS 1.2 as the floor; only if the logs show a significant portion of traffic comes from old clients do I open 1.1 as well. For most of today's sites, closing old versions is the more correct choice.
Tools that save you time
Before any change, test from outside the server. DNS and network lookup tools show you which IP the A and AAAA records point to; if AAAA points to a server that has no certificate, IPv6 browsers get an error and you see nothing in the IPv4 logs. This is a common trap.
For continuous monitoring, write a simple script that checks the expiration date every hour and alerts if it's less than 14 days away. Don't wait for the browser. If your site is behind WordPress, some of these errors come from plugins that make insecure requests themselves; in WordPress security; from wp-config to plugins that are holes themselves these cases are listed.
If your server is behind a DDoS protection layer, make sure the certificate is installed on that edge, not just on the origin server. Otherwise the user sees the edge certificate, and if it isn't valid there, the error happens right there. DDoS protection without a proper certificate is just an extra layer that creates a new problem.
When the problem isn't yours
If your own certificate is healthy and everything is configured correctly but users still get errors, the problem is probably on the issuer's side or the user's network. First check live service status. If the service is healthy, ask the user to clear their browser cache and check their device clock. Root certificates have expired on some old devices, and there's nothing you can do from your side except change the issuer.
For sites with sensitive traffic, an extra layer like enterprise VPN for secure employee access makes sense, but this has nothing to do with a regular user's SSL error. Don't make the mistake of seeing these two as the same thing.
Frequently asked questions
Why did my site's SSL certificate expire on its own?
Because automatic renewal didn't run. Let's Encrypt issues a ninety-day certificate, and if the renewal cron job fails for any reason, you see no warning until the moment the browser throws an error. Test the renewal path with certbot renew --dry-run and save the output to a log.
What's the difference between ERR_CERT_DATE_INVALID and ERR_CERT_AUTHORITY_INVALID?
The first means the certificate has expired or the server clock is wrong. The second means the browser can't trace the certificate to a trusted authority, which usually means an incomplete chain or a self-signed certificate. The treatments for these two are completely different.
Can I bypass an SSL error by disabling the check in the browser?
Only for testing on your own system. This completely removes security, and if done on a server or in application code, it enables a man-in-the-middle attack. Never do this in a production environment.
Why does the site give an SSL error on mobile but not on laptop?
It's almost always due to an incomplete chain. The desktop browser has the intermediate certificate from a previous cache, but a fresh device that hasn't seen that domain before doesn't see the full chain and throws an error. Install the fullchain file.
The next step is simple: right now, run openssl s_client on the domain and look at the expiration date and the number of certificates in the chain. If less than 14 days remain or the chain is a single certificate, fix it right then. After these two cases, the rest of the errors almost always come back to web server configuration.
Comments 0
No comments yet — be the first!