The core issue is that the SSL/TLS certificate presented by the server doesn’t match the hostname the client is trying to connect to, breaking the trust chain.
Common Causes and Fixes:
-
Incorrect
server_namedirective in Nginx:- Diagnosis: Check your Nginx configuration file (e.g.,
/etc/nginx/nginx.confor files in/etc/nginx/sites-available/). Look forserverblocks. Within aserverblock, you’ll find alistendirective and aserver_namedirective. For example:
If theserver { listen 443 ssl; server_name example.com www.example.com; # This is the key line ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # ... other ssl settings }server_namedoesn’t includewww.example.combut you’re accessinghttps://www.example.com, you’ll get a mismatch. - Fix: Add the missing hostname to the
server_namedirective.
Then reload Nginx:server { listen 443 ssl; server_name example.com www.example.com; # Ensure all expected hostnames are here # ... }sudo systemctl reload nginx. - Why it works: Nginx uses the
server_namedirective to determine whichserverblock to use for an incoming request. If the requested hostname isn’t listed, it falls back to a default or a mismatch occurs.
- Diagnosis: Check your Nginx configuration file (e.g.,
-
Wildcard Certificate Not Covering Subdomain:
- Diagnosis: If you’re using a wildcard certificate (e.g.,
*.example.com), it will only cover direct subdomains (likeapp.example.com,mail.example.com) but not the base domain (example.com) or multi-level subdomains (test.app.example.com). Check your certificate’s Subject Alternative Name (SAN) field. You can do this withopenssl x509 -in /path/to/your/certificate.pem -noout -text. Look forDNS:*.example.com. - Fix: Either add the base domain (
example.com) and any specific subdomains to your certificate request (if your CA supports it and you have a multi-domain certificate), or ensure your wildcard certificate is configured correctly in your web server. For Let’s Encrypt, you’d typically requestexample.comand*.example.comtogether.- Let’s Encrypt Example (Certbot): If you used Certbot, you might need to re-run it and select the correct domain names. For example, if you initially only got
*.example.comand now needexample.comtoo:
This will update your Nginx configuration and renew the certificate to include both.sudo certbot --nginx -d example.com -d *.example.com
- Let’s Encrypt Example (Certbot): If you used Certbot, you might need to re-run it and select the correct domain names. For example, if you initially only got
- Why it works: Wildcard certificates have specific rules about what they match. Explicitly including the base domain or ensuring the wildcard covers the correct level of subdomains is crucial.
- Diagnosis: If you’re using a wildcard certificate (e.g.,
-
IP Address Access Instead of Hostname:
- Diagnosis: Users are trying to access the server using its IP address (e.g.,
https://192.168.1.100) when the certificate is issued for a hostname (e.g.,example.com). Browsers will reject this because the IP address is not listed in the certificate’s SANs. - Fix: Instruct users to access the server using the configured hostname (e.g.,
https://example.com). If you must allow IP access with SSL, you’ll need to obtain a certificate that includes the IP address in its SANs, or set up a separate server block for IP access (though this is generally discouraged and often requires a self-signed certificate or a specific IP-address-based certificate from a CA). - Why it works: SSL/TLS relies on matching names. An IP address is not a name, and certificates are issued to names.
- Diagnosis: Users are trying to access the server using its IP address (e.g.,
-
Multiple
serverBlocks with Identicalserver_nameor Noserver_name:- Diagnosis: In Nginx, if multiple
serverblocks listen on the same IP address and port, and they have identicalserver_namedirectives (e.g., two blocks both sayingserver_name example.com;), or if one has aserver_nameand another has noserver_name(acting as a default), Nginx might pick the wrong one for a specific request. You can check for duplicate or conflictingserver_nameentries. - Fix: Ensure each
serverblock that handles SSL has a uniqueserver_namedirective that accurately reflects the hostname it’s supposed to serve. If a block is intended as a default, it should be the only block without a specificserver_namefor that IP/port combination.
Reload Nginx:# Corrected example server { listen 443 ssl; server_name example.com; # Specific for example.com ssl_certificate ...; # ... } server { listen 443 ssl; server_name www.example.com; # Specific for www.example.com ssl_certificate ...; # ... }sudo systemctl reload nginx. - Why it works: Nginx needs a clear, unambiguous way to route incoming requests to the correct virtual host configuration. Conflicting
server_namedirectives create this ambiguity.
- Diagnosis: In Nginx, if multiple
-
Stale/Cached Certificate or Configuration:
- Diagnosis: You’ve recently updated your certificate or Nginx configuration, but clients are still seeing the old one. This can happen if clients have cached the old certificate/session, or if Nginx wasn’t reloaded/restarted properly after changes. Use
curl -vI https://example.comand look for theServer certificate:section to see which certificate is being presented. - Fix:
- Reload Nginx: Ensure you’ve reloaded or restarted your web server after making changes. For Nginx:
sudo systemctl reload nginx. - Clear Browser Cache: Ask users to clear their browser’s cache or try an incognito/private browsing window.
- Check HSTS: If HTTP Strict Transport Security (HSTS) is enabled, browsers will enforce HTTPS and might stubbornly stick to a previously known secure connection. This is less about certificate mismatch and more about connection policy, but can be mistaken for it.
- Reload Nginx: Ensure you’ve reloaded or restarted your web server after making changes. For Nginx:
- Why it works: Changes to certificates or configurations only take effect once the web server is signaled to re-read them, and clients need to establish new connections to receive them.
- Diagnosis: You’ve recently updated your certificate or Nginx configuration, but clients are still seeing the old one. This can happen if clients have cached the old certificate/session, or if Nginx wasn’t reloaded/restarted properly after changes. Use
-
Certificate Issued for Wrong Domain/Subdomain:
- Diagnosis: The certificate was generated or renewed for
oldexample.comordev.example.combut you are trying to accessexample.com. Verify theSubjectandSubject Alternative Name(SAN) fields of your certificate usingopenssl x509 -in /path/to/your/certificate.pem -noout -text. - Fix: Obtain a new certificate that correctly lists all the hostnames you intend to use. For Let’s Encrypt, this means running Certbot again with the correct domain names specified.
Then reload Nginx:sudo certbot --nginx -d example.com -d www.example.com # Or your specific domainssudo systemctl reload nginx. - Why it works: The certificate must explicitly name or cover the hostname a client is trying to reach for the handshake to succeed.
- Diagnosis: The certificate was generated or renewed for
The next error you’ll likely hit if you fix hostname mismatches is related to cipher suite compatibility or protocol version negotiation if your SSL configuration is also outdated.