SSL Troubleshooting¶
Common SSL Errors¶
| Error | Cause | Fix |
|---|---|---|
NET::ERR_CERT_COMMON_NAME_INVALID |
Domain doesn't match certificate | Re-issue cert with correct domain |
NET::ERR_CERT_DATE_INVALID |
Certificate expired | Renew certificate |
NET::ERR_CERT_AUTHORITY_INVALID |
Untrusted issuer | Install intermediate cert |
SSL: error:0A000086 |
Wrong key/cert pair | Verify key matches cert |
ssl_stapling errors |
OCSP responder unreachable | Check OCSP URL in cert |
Check Certificate Details¶
# View cert info
openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -text -noout
# Check expiry
openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -noout -enddate
# Check subject/issuer
openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -noout -subject -issuer
# Check domains (SAN)
openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -noout -ext subjectAltName
Verify Key Matches Certificate¶
# Compare modulus (must match)
openssl x509 -noout -modulus -in /etc/letsencrypt/live/example.com/fullchain.pem | openssl md5
openssl rsa -noout -modulus -in /etc/letsencrypt/live/example.com/privkey.pem | openssl md5
Check Certificate Chain¶
# View full chain
openssl crl2pkcs7 -nocrl -certfile /etc/letsencrypt/live/example.com/fullchain.pem | openssl pkcs7 -print_certs -text -noout | grep "Subject:\|Issuer:"
# Verify chain
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt /etc/letsencrypt/live/example.com/fullchain.pem
Test SSL from Outside¶
# Using openssl
openssl s_client -connect example.com:443 -servername example.com
# Test with specific protocol
openssl s_client -connect example.com:443 -tls1_2
openssl s_client -connect example.com:443 -tls1_3
# Using curl
curl -vI https://example.com 2>&1 | grep -i "ssl\|certificate"
# Using ssllabs (online)
# https://www.ssllabs.com/ssltest/analyze.html?d=example.com
Renew Certificate¶
# Dry run
certbot renew --dry-run
# Force renew
certbot renew --force-renewal
# Renew specific domain
certbot certonly --force-renewal -d example.com
# Reload web server
nginx -t && systemctl reload nginx
Install Intermediate Certificate¶
Nginx config must include full chain:
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # Cert + intermediates
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # Private key
fullchain.pem = server cert + intermediates.
NEVER use cert.pem alone (browsers will show untrusted).
Mixed Content Issues¶
HTTPS page loading HTTP resources:
# Find mixed content
curl -s https://example.com | grep -i "http://"
# Fix with WP-CLI
wp search-replace "http://example.com" "https://example.com" --all-tables
# Or force HTTPS in wp-config
define('FORCE_SSL_ADMIN', true);
# Cloudflare automatic HTTPS rewrites
# Dashboard → SSL/TLS → Edge Certificates → Automatic HTTPS Rewrites → ON
Cloudflare SSL Settings¶
| Mode | Description |
|---|---|
| Off | No encryption |
| Flexible | Browser→CF encrypted, CF→server plain |
| Full | End-to-end encrypted, but CF trusts any origin cert |
| Full (strict) | End-to-end encrypted, CF validates origin cert |
Recommended: Full (strict)
Check OCSP Stapling¶
# Test OCSP
openssl ocsp -issuer /etc/letsencrypt/live/example.com/chain.pem \
-cert /etc/letsencrypt/live/example.com/cert.pem \
-url $(openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem -noout -ocsp_uri) \
-header "Host" $(openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem -noout -ocsp_uri | awk -F/ '{print $3}')
# Check Nginx OCSP stapling
openssl s_client -connect example.com:443 -tls1_2 -servername example.com -status 2>&1 | grep -i "OCSP response"
Certificate Revocation¶
# If private key compromised
certbot revoke --cert-path /etc/letsencrypt/live/example.com/cert.pem
# Generate new cert
certbot certonly -d example.com
Quick Diagnostic Script¶
#!/bin/bash
DOMAIN="example.com"
echo "=== Certificate Expiry ==="
openssl x509 -in /etc/letsencrypt/live/$DOMAIN/fullchain.pem -noout -enddate
echo "=== Subject ==="
openssl x509 -in /etc/letsencrypt/live/$DOMAIN/fullchain.pem -noout -subject
echo "=== SAN Domains ==="
openssl x509 -in /etc/letsencrypt/live/$DOMAIN/fullchain.pem -noout -ext subjectAltName | grep DNS
echo "=== SSL Test ==="
echo | openssl s_client -connect $DOMAIN:443 -servername $DOMAIN 2>/dev/null | openssl x509 -noout -dates
echo "=== Mixed Content Check ==="
curl -s https://$DOMAIN | grep -c "http://"
echo "=== HTTP Status ==="
curl -o /dev/null -s -w "%{http_code}" https://$DOMAIN