TLS protocol/cipher mismatch — client and server can't agree
Older clients fail handshake with 'SSL: no protocols available'
Focused incident mode — strips away everything but this runbook.
Symptoms
- Older clients fail handshake with 'SSL: no protocols available'
- sslv3 alert: protocol version changes on both sides
- Handshake succeeds for modern browsers, fails for legacy clients
Balance: enabling TLS1.0 for one legacy client is a security regression — prefer updating the client or a dedicated TLS1.0 endpoint with mTLS + a WAF in front.
Evidence to grab
Collect these artifacts before you change anything — they prove (or rule out) each cause.
Server's supported versions/ciphers
nmap --script ssl-enum-ciphers -p 443 <HOST> 2>/dev/null || echo | openssl s_client -connect <HOST>:443 -tls1 2>&1 | head -5
Diagnostic flow
Run the steps in order, marking each claim confirmed or refuted. The evidence you gather feeds the ranked causes below.
Guided decision tree is ready.
Steps with commands, expected output, and pass/fail branches.
Ranked root causes
Evidence checklist
- New server config disables TLS <1.2 (e.g. nginx ssl_protocols TLSv1.2 TLSv1.3)
- Legacy client (old Java, embedded device, payment terminal) supports only TLS1.0
Confirm before fixing
echo | openssl s_client -connect <HOST>:443 -tls1 2>&1 | grep -i 'alert protocol version\|error'Reproduce the alert
Fix
kubectl -n <NS> set env deploy/<app> SSL_OP_FLAGS=NO_SSLv3,TLSv1.2,TLSv1.3 2>/dev/null || trueRe-enable the minimum version the client requires (weigh security)
Resolution runbook
Apply from top to bottom after the cause is confirmed. Review every command before running it — risk tags are shown on each.
echo | openssl s_client -connect <HOST>:443 -tls1 2>&1 | head -3Probe TLS1.0
echo | openssl s_client -connect <HOST>:443 -tls1_2 -cipher 'ECDHE-RSA-AES128-GCM-SHA256' 2>&1 | head -3Probe modern handshake for comparison
Prevention
- Run a cipher/version matrix test (nmap ssl-enum-ciphers or a CI crawler) against every client family.
- Deprecate legacy clients before rotating server crypto settings.
- Keep an allowlist of legacy ciphers only for the specific endpoint that needs them.
Related runbooks
Same stack, same failure family — worth a skim.
curl: (35) error:14094410:ssl routines:ssl3_read_bytes:sslv3 alert handshake failure
Clients get 'certificate has expired' or verification error
Commands marked READ CHANGE DESTRUCTIVE — never run DESTRUCTIVE commands against production data you cannot restore. Copy → verify → execute.