HTTPS returns the wrong site's certificate — diagnose the SNI mismatch
Users of shop.example.com hit a certificate-mismatch error, but only some clients. Many HTTPS sites share this one IP. You probe it with and without SNI. Explain why the wrong certificate is served to some clients, and give the fix.
# Probe WITHOUT SNI (raw IP, no -servername) — old client / health check:
$ openssl s_client -connect 203.0.113.10:443 </dev/null 2>/dev/null \
| openssl x509 -noout -subject
subject=CN=default.example.com # WRONG cert served
# Probe WITH SNI:
$ openssl s_client -connect 203.0.113.10:443 -servername shop.example.com </dev/null 2>/dev/null \
| openssl x509 -noout -subject
subject=CN=shop.example.com # correct cert IS present
$ curl -v https://shop.example.com/
* SSL: no alternative certificate subject name matches target host name 'shop.example.com'
Diagnose the cause and give the fix.
Many HTTPS sites share one IP and port, so the server picks the certificate from the TLS SNI field (the hostname in the client hello). A request with no SNI (old client, raw-IP) gets the default vhost's certificate, so only those clients see the mismatch. Fix: ensure SNI is sent, and make the intended site the default server block.
- ✗Blaming DNS or an expired cert instead of SNI-based selection
- ✗Assuming one IP forces a single shared certificate for all sites
- ✗Forgetting SNI-less clients fall back to the default virtual host
- →Why can a raw-IP or very old client trigger this while browsers do not?
- →How does the server's default server block change the fallback certificate?
Solution
1. Why some clients get the wrong cert
Many sites share this one IP:443, so the web server decides which certificate to send from the SNI field (the hostname in the TLS client hello). The probe shows the fork:
without -servername → CN=default.example.com (wrong cert)
with -servername → CN=shop.example.com (correct cert IS present)
So the config is fine — the correct cert exists. The problem is that some clients send no SNI (a raw-IP connection, a very old client, a health check), and they receive the default virtual host's certificate — default.example.com. Hence subjectAltName does NOT match.
2. Fix
SNI-less request gets a sane cert instead of a foreign one.
- Make sure the client sends SNI (connect by hostname, upgrade old clients).
- Set
shop.example.comas the default server block (default_server), so even an - Or give the offending paths their own listener/certificate.
SNI is visible before encryption (in the cleartext client hello), which is exactly why certificate selection by it is possible.