How to check certificate SAN

Print the extension: openssl x509 -noout -ext subjectAltName, fed from openssl s_client -connect host:443 -servername host </dev/null. The DNS: entries are the only names a modern client accepts. To test one hostname against them without reading the list, run openssl x509 -noout -checkhost www.example.com.

Why check this

Subject Alternative Name decides which hostnames the certificate covers, and a deployment that adds an alias without reissuing breaks every client on that alias while the main site stays green. Run this whenever a new hostname, a new region or a new environment alias appears in DNS, and before a release that moves traffic from app.example.com to www.app.example.com. The failure is total for the affected name: no retry, no partial content.

Renewal is the moment the list drifts. A certificate is reissued from whatever request the pipeline builds today, so a name that was added by hand to the previous one disappears without a warning anywhere: the new certificate is valid, the chain is intact, the expiry is fresh, and one hostname stops working. Nothing in a monitor that checks expiry alone will see it. That is why this check reads the list rather than the dates, and why the list belongs in the release ticket next to the hostnames the service is supposed to answer on.

Prerequisites

Steps

  1. Step 1.

    Print the names on a healthy certificate.

    openssl s_client -connect www.cloudflare.com:443 -servername www.cloudflare.com </dev/null 2>/dev/null | openssl x509 -noout -ext subjectAltName
    
    X509v3 Subject Alternative Name: 
      DNS:blog.api.www.cloudflare.com, DNS:www.cloudflare.com

    Two names, both exact. This certificate covers nothing else, wildcard or otherwise.

  2. Step 2.

    Save the certificate of the host under test once.

    openssl s_client -connect wrong.host.badssl.com:443 -servername wrong.host.badssl.com </dev/null 2>/dev/null | openssl x509 -outform PEM | tee badssl.pem | head -1
    
    -----BEGIN CERTIFICATE-----
  3. Step 3.

    Read the subject and the names side by side.

    openssl x509 -in badssl.pem -noout -subject -ext subjectAltName
    
    subject=CN = *.badssl.com
    X509v3 Subject Alternative Name: 
      DNS:*.badssl.com, DNS:badssl.com

    The wildcard is repeated in the subject, but only the DNS: line is consulted.

  4. Step 4.

    Test each hostname you serve against the saved file.

    for name in badssl.com www.badssl.com wrong.host.badssl.com a.b.badssl.com; do printf '%-24s ' "$name"; openssl x509 -in badssl.pem -noout -checkhost "$name"; done
    
    badssl.com               Hostname badssl.com does match certificate
    www.badssl.com           Hostname www.badssl.com does match certificate
    wrong.host.badssl.com    Hostname wrong.host.badssl.com does NOT match certificate
    a.b.badssl.com           Hostname a.b.badssl.com does NOT match certificate

    *.badssl.com covers one label and no more. Two labels below the domain fail.

  5. Step 5.

    Watch the same mismatch during a live handshake.

    openssl s_client -brief -connect wrong.host.badssl.com:443 -servername wrong.host.badssl.com -verify_hostname wrong.host.badssl.com </dev/null
    
    depth=0 CN = *.badssl.com
    verify error:num=62:hostname mismatch
    CONNECTION ESTABLISHED
    Peer certificate: CN = *.badssl.com
    Verification error: hostname mismatch
    DONE

    Without -verify_hostname, s_client reports the chain as valid and says nothing about the name.

  6. Step 6.

    Confirm that the name does not depend on the Common Name at all.

    openssl s_client -connect no-common-name.badssl.com:443 -servername no-common-name.badssl.com </dev/null 2>/dev/null | openssl x509 -noout -subject -ext subjectAltName
    
    subject=C = US, ST = California, L = Walnut Creek, O = Lucas Garron, OU = Multi-Domain SSL
    X509v3 Subject Alternative Name: 
      DNS:no-common-name.badssl.com

    No CN in the subject, and -checkhost no-common-name.badssl.com against this certificate still answers "does match". The name lives in the extension. This certificate also expired in 2020, so a browser rejects the host for a different reason.

How to read the result

| What you see | What it means | What to do | | --- | --- | --- | | Every hostname you serve appears as DNS: | The certificate covers the traffic | Pass. Keep the list in the release ticket. | | does NOT match certificate | That hostname fails for every client | Reissue with the name added. No server setting fixes it. | | verify error:num=62:hostname mismatch | The live handshake rejects the name | Same defect, observed end to end. | | A DNS: entry with two wildcards, such as *.*.example.com | openssl refuses to match a.b.example.com against it | Replace with explicit names or a single wildcard per level. | | IP Address: entries only | Name-based clients have nothing to match | Add the DNS names. An IP entry is used only when the client dials the IP. |

Common mistakes

Sign: The Common Name holds the right domain, and clients still reject the connection.Cause: Clients read the extension, not the subject. curl states it in the error itself: no alternative certificate subject name matches target hostname. RFC 6125 section 6.4.4 is the rule behind that wording, and step 6 shows a certificate with no Common Name that matches anyway.
Sign: A wildcard certificate covers the domain but one subdomain fails.Cause: A wildcard matches exactly one label. With *.badssl.com, www.badssl.com passes and a.b.badssl.com fails, as step 4 shows. The apex itself also needs its own entry, which is why the list holds badssl.com separately.
Sign: openssl reports the certificate as valid, yet the browser shows a name warning.Cause: s_client checks the chain by default and the hostname only when you pass -verify_hostname. Step 5 turns it on. Without it, a wrong-host certificate produces a clean transcript.

What to check next

FAQ

How to check subject alternative names in a certificate?

Step 1 for a live server, openssl x509 -in cert.pem -noout -ext subjectAltName for a file. Both print the extension verbatim, including IP Address: and email: entries when a certificate carries them.

Does a wildcard cover a sub-subdomain?

No. One label only, confirmed by step 4. *.example.com matches api.example.com and rejects v1.api.example.com. Nested coverage needs a second wildcard entry such as *.api.example.com.

Is the Common Name used by any client?

curl reports a failure as "no alternative certificate subject name matches target hostname", which names the extension and not the subject. Treat the SAN list as the answer, and treat a matching Common Name as decoration that costs nothing to keep.

How do I check the names before the certificate is issued?

Read them off the signing request: openssl req -in req.csr -noout -text | grep -A1 'Subject Alternative Name'. A request built without -addext subjectAltName carries no names, and the authority will add whatever its own form says.

Does the order of the DNS: entries matter?

No. A client scans the whole list and accepts a match anywhere in it, so the first entry has no special standing. The order you see is the order the authority wrote, and it can change between two renewals of the same certificate. Compare the entries as a set, not as a sequence, or a diff between two renewals reports a change that is not one.

Verified

Verified by Maks Vernyopenssl 3.1.1

Each output block is what the command above it printed on that date, on the host named in the step. Figures read from a live site move between runs. Compare the shape of the answer rather than the digits, and see the methodology for how a page is re-verified.

basic6 minpublished updated Maks Verny