Bridge SSL

SSL checker explained: what each check tests, and how to run it yourself

9 min readUpdated

An SSL checker connects to a hostname the way a visitor would and reports on the certificate and the connection it gets back. This page is a guide, not a checker: it is one of the explainers in the SSL tools section, and it shows how to run the same certificate check yourself with OpenSSL, one command per question, and how to read each answer.

Online SSL checker services run these checks from outside your network. The commands below run from any machine you choose, including one inside a network that no online service can reach. A browser shows a certificate faster; this page tests what the server sends.

Checks
names, expiry, chain and trust, protocol versions, OCSP stapling
Commands
openssl s_client to connect, openssl x509 to read what came back [1]
Output on this page
from this site, bridge-ssl.com, with OpenSSL 3.0.13
Run from
a machine other than the server, so the test sees what visitors see
Not needed
an account, an upload, or your private key

What an SSL checker tests, and the command for each

Each row is one test an SSL checker tool runs, the command that runs it here, and the answer that means it passed. Replace example.com with your hostname.

What an SSL checker tests, the command that runs each test, and what a pass looks like
TestAdd to openssl s_client -connect example.com:443 -servername example.comPass looks like
Trust and chain-briefVerification: OK
Names| openssl x509 -noout -ext subjectAltNameevery hostname visitors use is listed
A specific name-verify_hostname www.example.comVerify return code: 0 (ok)
Expiry| openssl x509 -noout -checkend 1209600Certificate will not expire
Chain as sent-showcertseach issuer is the subject of the next certificate
Protocol versions-tls1_2, then -tls1_3both complete a handshake
OCSP stapling-statusa stapled response, or no OCSP address in the certificate

Run them against every address the name resolves to, not only the first one. The flags are documented in the OpenSSL 3.0 manual [1].

Before you start: which name, which address

Use the hostname visitors type, and send it. -servername puts that name into the handshake as SNI, which a server hosting several sites uses to pick the certificate. OpenSSL takes the name from -connect when you connect by name, but connect by address without -servername and you may be shown a different certificate, or none at all [1]: bridge-ssl.com ends such a connection with an alert and sends no certificate.

A name can resolve to more than one address, and something in front of the server, such as a load balancer or a CDN, can present its own certificate. To test each address separately, connect to it and keep the name:

$ openssl s_client -connect <address>:443 -servername example.com </dev/null

Port 443 is the default port for HTTPS [2]. Add </dev/null so the command closes the connection after the handshake instead of waiting for input.

Reading each result

The outputs below were produced against bridge-ssl.com with OpenSSL 3.0.13. Your own host will print its own values in the same form.

Trust and chain

$ openssl s_client -connect bridge-ssl.com:443 -servername bridge-ssl.com -brief </dev/null 2>&1 | grep -E 'Protocol version|Peer certificate|Verification'
Protocol version: TLSv1.3
Peer certificate: CN = bridge-ssl.com
Verification: OK

Verification: OK means OpenSSL built a path from the server's certificate to a root in your machine's trust store. Without -brief, the same result appears near the end as Verify return code: 0 (ok). s_client finishes the connection even when verification fails, so read the code rather than trusting that a printed certificate is a valid one [1].

-showcerts prints the certificates exactly as the server sent them, in the order it sent them, and the manual stresses that this is not a verified chain [1]. If the list stops at the site's own certificate, the server is not sending its intermediates: browsers may hide that by filling the gap from their cache, while scripts fail with unable to get local issuer certificate. Other verify return codes are listed on this site's page of OpenSSL commands for checking certificates.

Names

$ openssl s_client -connect bridge-ssl.com:443 -servername bridge-ssl.com </dev/null 2>/dev/null | openssl x509 -noout -ext subjectAltName
X509v3 Subject Alternative Name: 
    DNS:bridge-ssl.com

Browsers match the hostname against this list only. To test one name directly, -verify_hostname checks it against the certificate the server sent [1]. This site's certificate lists the bare domain and no www name, so asking for www fails:

$ openssl s_client -connect bridge-ssl.com:443 -servername bridge-ssl.com -verify_hostname www.bridge-ssl.com </dev/null 2>/dev/null | grep -E '^Verify return code'
Verify return code: 62 (hostname mismatch)

Code 62 is OpenSSL's hostname mismatch error [3]. In Chrome the same fault shows as ERR_CERT_COMMON_NAME_INVALID behind the warning "Your connection is not private".

Expiry

$ openssl s_client -connect bridge-ssl.com:443 -servername bridge-ssl.com </dev/null 2>/dev/null | openssl x509 -noout -checkend 1209600
Certificate will not expire

-checkend asks whether the certificate expires within the given number of seconds, and it exits with a nonzero status if it will [1]. 1209600 seconds is 14 days. The answer Certificate will expire, or a status of 1, means renewal is due or failed; once the end date has passed, browsers show ERR_CERT_DATE_INVALID.

Protocol versions

$ openssl s_client -connect bridge-ssl.com:443 -servername bridge-ssl.com -tls1_2 </dev/null 2>/dev/null | grep -E '^ +Protocol'
    Protocol  : TLSv1.2

Each flag offers a single version, so a completed handshake proves the server accepts it. Run it again with -tls1_3; on this site that line reads TLSv1.3. RFC 9325 requires TLS 1.2, recommends TLS 1.3, and rules out TLS 1.0 and 1.1 [4]. A server that refuses both current versions fails in browsers with ERR_SSL_VERSION_OR_CIPHER_MISMATCH. What changed between the versions is part of how TLS works.

OCSP stapling

$ openssl s_client -connect bridge-ssl.com:443 -servername bridge-ssl.com -status </dev/null 2>/dev/null | grep -E '^OCSP'
OCSP response: no response sent

-status asks the server to staple an OCSP response, the authority's signed answer on whether the certificate is revoked [1]. Stapling is optional on both sides in RFC 6066 §8 [5], and an OCSP address in the certificate is optional too under the CA/Browser Forum Baseline Requirements §7.1.2.7.7 [6]. So read no response sent together with the certificate:

$ openssl s_client -connect bridge-ssl.com:443 -servername bridge-ssl.com </dev/null 2>/dev/null | openssl x509 -noout -ext authorityInfoAccess,crlDistributionPoints

On bridge-ssl.com the output lists a CA Issuers address and a CRL address and no OCSP address, so there is nothing to staple. A certificate that is not short-lived and has no OCSP address must carry a CRL address (§7.1.2.11.2) [6]. How clients use either is a question of certificate revocation, not of this check.

When a check fails

  1. Verification fails, or the chain stops at position 0. The server is missing its intermediates or the certificate comes from an authority your machine does not trust. Start with the error unable to get local issuer certificate.

  2. A name is missing. The certificate was issued for the wrong set of names. Reissue with every hostname visitors use, the bare domain and www included.

  3. Expiry is within your margin. Renewal has not run or has not reached this address. If one address passes and another fails, the stale certificate sits on the second machine.

  4. The handshake fails before any certificate is shown. Compare protocol versions first. If the server starts and then refuses every connection after a certificate change, check that the certificate and key belong together.

The browser codes these failures produce, from ERR_CERT_DATE_INVALID to ERR_SSL_VERSION_OR_CIPHER_MISMATCH, are explained with their fixes among the SSL certificate errors.

Online checkers and the command line

An online SSL checker connects from outside your network, so it sees what visitors see, and it reports the certificate, the chain the server sends, the protocol versions and ciphers it accepts, and known configuration problems. It may also grade the result. The commands on this page grade nothing; they answer one question each, and the answer can go into a script or a monitor.

Use an online check after the first installation of a public site. Use the commands for hosts an online service cannot reach, for checking each address behind a name, and for a scheduled expiry test after every renewal. Reading a certificate file rather than a live host is a separate job for a certificate viewer, and what each field in website certificates means is covered under website certificates.

FAQ

How do I verify an SSL certificate?

Connect with openssl s_client -connect example.com:443 -servername example.com -brief and look for Verification: OK. That confirms the chain reaches a trusted root. Then confirm the name with -verify_hostname and the expiry with openssl x509 -checkend.

How do I test an SSL certificate?

Run the commands in the table above from a machine outside the server. They cover the same names, dates, chain and protocol tests as an online checker, and they also work on internal hosts that online services cannot reach.

How do I validate an SSL certificate in one command?

Add -verify_hostname with your hostname and -verify_return_error to openssl s_client. OpenSSL then stops at the first verification error instead of carrying on, and the exit status says which happened: on this site it is 0 for bridge-ssl.com and 1 for www.bridge-ssl.com, a name the certificate does not list. [1]

Sources

  1. OpenSSL 3.0 manual: openssl-s_client (-connect, -servername, -brief, -verify_hostname, -verify_return_error, -showcerts, -tls1_2, -tls1_3, -status) and openssl-x509 (-ext, -checkend).

  2. RFC 9110, HTTP Semantics, §4.2.2: the https URI scheme and TCP port 443.

  3. OpenSSL source, include/openssl/x509_vfy.h: X509_V_OK 0, X509_V_ERR_HOSTNAME_MISMATCH 62.

  4. RFC 9325, Recommendations for Secure Use of TLS and DTLS, §3.1.1.

  5. RFC 6066, TLS Extensions, §8 Certificate Status Request.

  6. CA/Browser Forum Baseline Requirements, version 2.3.1, §7.1.2.7.7 and §7.1.2.11.2.