An SSL certificate that loads in a browser without a warning isn't proof of a secure configuration. It just means the basics didn't fail loudly. Plenty of sites with green padlocks still ship incomplete certificate chains, support TLS 1.0, leak through mixed content, or expose private keys via misconfigured subdomains.
If you maintain client sites or run your own infrastructure, you need a repeatable way to test what's actually happening during the TLS handshake. Here's how to do it properly, using free command-line tools, online scanners, and a few sanity checks most people skip.
What you're actually testing
"SSL configuration" is a bundle of things, not one setting. A thorough test covers:
- Certificate validity — issuer, expiry, SAN coverage, key size
- Chain of trust — intermediate certificates served in the right order
- Protocol versions — TLS 1.2 and 1.3 only; no SSLv3, TLS 1.0, TLS 1.1
- Cipher suites — modern AEAD ciphers, forward secrecy enabled
- HSTS — Strict-Transport-Security header set and ideally preloaded
- Mixed content — no HTTP assets loaded over HTTPS pages
- OCSP stapling — server provides revocation status
- Redirects — HTTP traffic forced to HTTPS without loops
Command-line tests with openssl
If you only have a terminal, openssl s_client is the fastest way to inspect a live certificate.
Inspect the served certificate
openssl s_client -connect example.com:443 -servername example.com < /dev/null | openssl x509 -noout -textLook for the Subject Alternative Name entries (every hostname you serve must be listed), the Not After date, and the Signature Algorithm — it should be sha256WithRSAEncryption or better, never SHA-1.
Check the certificate chain
openssl s_client -connect example.com:443 -servername example.com -showcertsYou should see at least two certificates: your leaf cert and one or more intermediates. If only the leaf appears, your server is missing intermediates and some clients (especially older Android devices and curl on minimal Docker images) will reject the connection. The Verify return code at the bottom should be 0 (ok).
Test a specific protocol version
openssl s_client -connect example.com:443 -tls1_1If this succeeds, your server still supports TLS 1.1 and needs to be hardened. Repeat with -tls1 and -ssl3 to confirm those are disabled. A correctly configured server returns handshake failure for anything below TLS 1.2.
Check expiry quickly
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -datesUseful in monitoring scripts. Alert if notAfter is within 14 days.
Browser-based checks
Browsers tell you more than you'd think if you know where to look.
- Click the padlock in Chrome or Firefox and view the certificate. Check the issuer, dates, and SAN list.
- Open DevTools → Security tab (Chrome). It will flag obsolete TLS, weak ciphers, and mixed content per request.
- Network tab — filter by
Mixed Contentor look for any request that doesn't start withhttps://. - Console — mixed content warnings and certificate errors show up here before they break anything visibly.
Online scanners
Command-line tools give you raw data; scanners give you a graded view across dozens of checks in one pass. The two most useful approaches:
SSL Labs
Qualys SSL Labs is the long-running standard for deep TLS analysis. It rates handshake simulation against real clients, scores cipher strength, and details every weakness. Worth running before any production launch.
Whole-site security scanners
SSL Labs only tests TLS. If you want to know whether your HSTS header, CSP, cookie flags, and redirect chain are also configured correctly, you need a broader scan. WebSentry grades sites A–F across SSL, security headers, CSP, cookies, DNS, and CORS in a single report, which is faster than running five separate tools when you're auditing multiple client sites.
Common configuration mistakes you'll catch
Missing intermediate certificates
The most common real-world issue. The site works in Chrome (which caches intermediates from prior visits) but fails in curl, Java clients, or fresh devices. Always serve the full chain — your CA provides a bundle file for exactly this purpose.
HSTS set without preload-ready values
A header like Strict-Transport-Security: max-age=3600 is technically present but useless. For preload eligibility you need:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preloadWildcards exposing too much
A *.example.com wildcard cert on a shared server means a compromise of any subdomain compromises all of them. Use targeted SANs or per-host certs where you can.
OCSP must-staple without stapling enabled
If your certificate has the must-staple flag but your server isn't actually stapling OCSP responses, browsers will refuse the connection. Test with:
openssl s_client -connect example.com:443 -status < /dev/null 2>&1 | grep -A 5 "OCSP response"You should see OCSP Response Status: successful.
Redirect chains that strip HSTS
A redirect from http://example.com to https://www.example.com is fine, but if the apex http:// request never sets HSTS, the first connection is always vulnerable to downgrade. Set HSTS on every HTTPS response, not just the canonical host.
A repeatable testing workflow
For each site you manage, run through this sequence. It takes about five minutes once you've done it a few times:
- Run
openssl s_clientagainst the apex andwwwhostnames. Confirm chain, expiry, and TLS version restriction. - Hit the site over plain HTTP and confirm a 301 to HTTPS.
- Open DevTools and reload — check the Security tab for warnings.
- Run a WebSentry scan at websentry.dev to catch header, cookie, and CSP issues the TLS-only tools won't surface.
- If anything scores below an A, fix the highest-impact issue first: protocol versions, then chain, then headers.
- Add expiry monitoring — either via your CA, a cron job running the
openssl x509 -datescheck, or an uptime service.
Automating the check in CI
For sites under active development, bake the test into your pipeline. A minimal bash check that fails the build on a bad chain or imminent expiry:
#!/bin/bash
HOST=example.com
EXPIRY=$(echo | openssl s_client -connect $HOST:443 -servername $HOST 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s)
NOW=$(date +%s)
DAYS_LEFT=$(( (EXPIRY_EPOCH - NOW) / 86400 ))
if [ $DAYS_LEFT -lt 21 ]; then
echo "Cert expires in $DAYS_LEFT days"
exit 1
fiPair that with a weekly scheduled scan of your production hostname so configuration drift — a load balancer swap, a CDN change, a renewed cert that didn't include the chain — gets caught before users do. Run a free scan at websentry.dev to see where your current configuration stands.
Check your own site
Run a free security scan and see if your site has the issues covered in this article. Results in under 30 seconds.