SSL/TLS powers secure connections across the internet. But when things break—handshakes fail, certificates misbehave, or browsers throw cryptic errors—it can be frustrating. This post helps you quickly identify and fix common SSL/TLS issues using real examples and tools.
Common SSL/TLS Errors
1. Cipher Mismatch (SSL_ERROR_NO_CYPHER_OVERLAP)
Client and server don’t agree on encryption algorithms.
Fix
ssl_ciphers
in Nginx) and ensure modern protocols like TLS 1.2/1.3 are enabled and prioritized.2. Port Misuse (SSL_ERROR_RX_RECORD_TOO_LONG)
HTTPS connection attempted on a port not configured for SSL/TLS (often HTTP port 80).
Fix
3. Invalid Certificate (SSL_ERROR_BAD_CERT_DOMAIN)
The certificate presented by the server does not match the domain name the client is trying to access.
Fix
4. Incomplete Chain (unable to get local issuer certificate)
The server is not presenting the necessary intermediate certificates that allow the client to trace the server's certificate back to a trusted root CA.
Fix
fullchain.pem
).Useful Commands & Tools
Check with OpenSSL:
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com
Provides detailed SSL handshake information and certificate details.
Debug with Curl:
curl -v https://yourdomain.com
Shows verbose output of the connection attempt, including SSL handshake steps.
Browser Developer Tools:
- Chrome: DevTools → Security tab (shows certificate details, connection status, and errors).
- Firefox: Click the 🔒 icon in the address bar → "Connection secure" → "More information" → "View Certificate".
Server Logs:
- Apache: Typically
/var/log/apache2/error.log
or similar. - Nginx: Typically
/var/log/nginx/error.log
or similar.
Check these for specific error messages related to SSL/TLS failures.
Basic SSL Configurations
Nginx Example
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name ssldoctor.in www.ssldoctor.in;
ssl_certificate /etc/nginx/ssl/ssldoctor.in/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/ssldoctor.in/privkey.pem;
# Modern SSL Settings
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# Add HSTS header
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# ... other Nginx configurations (root, location blocks, etc.)
}
Apache Example
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerAdmin webmaster@ssldoctor.in
ServerName ssldoctor.in
ServerAlias www.ssldoctor.in
DocumentRoot /var/www/ssldoctor.in/html
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/ssldoctor.in/certificate.crt
SSLCertificateKeyFile /etc/apache2/ssl/ssldoctor.in/private.key
SSLCertificateChainFile /etc/apache2/ssl/ssldoctor.in/ca_bundle.crt
# Modern SSL Settings
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder off
SSLSessionTickets off
# HSTS Header
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
# ... other Apache configurations
</VirtualHost>
</IfModule>