Introduction
Cipher suite negotiation happens during the TLS handshake when client and server try to agree on which encryption algorithms to use. When no cipher suites overlap - the client's list doesn't match any of the server's supported ciphers - the handshake fails immediately. This is increasingly common as servers disable weak legacy ciphers while some clients still expect them.
Symptoms
- OpenSSL error:
error:14164064:SSL routines:tls_construct_client_hello:no ciphers available - Browser error:
ERR_SSL_VERSION_OR_CIPHER_MISMATCH - Connection fails immediately with no useful error message
- Works with some clients but not others
- Modern browsers fail, older clients work (or vice versa)
- SSL Labs shows cipher suite issues
openssl s_clientshowsno cipher match
Common Causes
- Server configured with only modern ciphers, client lacks support
- Client requires specific cipher server doesn't offer
- Certificate type mismatch (RSA cert with ECDSA-only ciphers)
- Cipher string syntax error in configuration
- OpenSSL/server version too old for modern ciphers
- Server cipher list too restrictive
- Disabled cipher still expected by client
Step-by-Step Fix
Step 1: Diagnose Cipher Mismatch
```bash # Check server's cipher suites nmap --script ssl-enum-ciphers -p 443 example.com
# List all ciphers server offers openssl s_client -connect example.com:443 -showcerts 2>&1 | grep "Cipher Suite"
# Test with specific cipher openssl s_client -connect example.com:443 -cipher 'ECDHE-RSA-AES128-GCM-SHA256'
# Test with cipher range openssl s_client -connect example.com:443 -cipher 'HIGH:!aNULL'
# Check what ciphers client supports openssl ciphers -v 'ALL' ```
Step 2: Check Certificate Type vs Ciphers
```bash # Certificate key type determines compatible ciphers openssl x509 -in /etc/ssl/certs/server.crt -noout -text | grep "Public Key Algorithm"
# RSA certificate - needs RSA cipher suites # ECDSA certificate - needs ECDSA cipher suites
# If mismatch, cipher negotiation will fail ```
Step 3: List Current Server Cipher Configuration
```nginx # Check Nginx cipher config grep ssl_ciphers /etc/nginx/sites-enabled/*
# Check Apache cipher config grep SSLCipherSuite /etc/apache2/sites-enabled/* ```
Step 4: Update Cipher Configuration
Nginx modern cipher configuration:
```nginx # Modern cipher suite (TLS 1.2+) ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384'; ssl_prefer_server_ciphers on;
# Intermediate compatibility (broader client support) ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256'; ```
```bash # Verify cipher string syntax openssl ciphers -v 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384'
# Should list valid ciphers, not error ```
Apache cipher configuration:
```apache # Modern cipher suite SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384 SSLHonorCipherOrder on
# Intermediate compatibility SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305 ```
Step 5: Handle Specific Client Requirements
```bash # If specific client needs specific cipher, test it openssl s_client -connect example.com:443 -cipher 'RSA-AES128-SHA'
# If works, add to cipher list # But consider security implications of legacy ciphers
# Test client's cipher capabilities # Use SSL Labs client test from failing client's machine ```
Step 6: Verify Cipher Suite Support
```bash # Test cipher negotiation after changes openssl s_client -connect example.com:443 -servername example.com
# Check negotiated cipher openssl s_client -connect example.com:443 2>&1 | grep "Cipher :"
# Test from failing client curl -vI https://example.com
# SSL Labs comprehensive cipher test # https://www.ssllabs.com/ssltest/analyze.html?d=example.com ```
Step 7: Debug Specific Cipher Issues
```bash # Test cipher string parsing openssl ciphers -v "$YOUR_CIPHER_STRING"
# If error, fix syntax: # - Colon separated # - No spaces # - Valid cipher names
# Common syntax errors: # ssl_ciphers "ECDHE RSA AES128 GCM SHA256" # Wrong - spaces # ssl_ciphers "ECDHE-RSA-AES128-GCM-SHA256" # Correct
# Check OpenSSL cipher names openssl ciphers -v 'ALL:COMPLEMENTOFALL' | head -20 ```
Step 8: Handle ECDSA vs RSA Certificate
```bash # If server has ECDSA certificate # Ensure ECDSA ciphers in cipher list ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305'
# If server has RSA certificate # Ensure RSA ciphers in cipher list ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305'
# Or support both types ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384' ```
Common Pitfalls
- Cipher string syntax errors (spaces instead of colons)
- Certificate type mismatch with cipher type
- Disabling all legacy ciphers without checking clients
- OpenSSL version too old for specified ciphers
- Cipher list too restrictive
- Not testing cipher string before deploying
Best Practices
- Use Mozilla's SSL configuration generator for cipher lists
- Test cipher configuration before production deployment
- Match cipher types to certificate key type
- Document minimum client cipher support requirements
- Audit client capabilities before tightening cipher list
- Use
ssl_prefer_server_ciphers onfor server cipher priority - Regularly review and update cipher configuration
Related Issues
- SSL Handshake Failed
- SSL Protocol Version Not Supported
- SSL Certificate Chain Incomplete
- TLS Key Share Missing