Fix TLS that will not handshake

We'll confirm the failure with openssl s_client, check TLS version and cipher support, then enable compatible settings or tell you when to escalate.

Category
Troubleshooting · Home maintenance
Time
15–30 min
Last reviewed
What you'll need
  • openssl (command-line)
  • Access to the server config (if you manage it)
  • The client or app that fails (to test and update)

Step-by-step diagnostic

Step 1 of 9
Show full guide

Confirm failure

Goal: Reproduce and capture the handshake error with openssl s_client.

  • Run openssl s_client -connect HOST:443 -servername HOST. Note the output.
  • A failure shows “handshake failure,” “no shared cipher,” “wrong version number,” or similar. A success shows “Verify return code: 0” and certificate details.
  • Good: You have the exact error. Proceed to Check version and cipher. Bad: “Connection refused”—check firewall, port, host. See fix-firewall-blocks-port.

Check version and cipher

Goal: Determine which TLS versions and ciphers the server supports.

  • Test TLS 1.2: openssl s_client -connect HOST:443 -servername HOST -tls1_2. If that works, the server supports TLS 1.2.
  • Test TLS 1.3: openssl s_client -connect HOST:443 -servername HOST -tls1_3.
  • Test a specific cipher: openssl s_client -connect HOST:443 -servername HOST -cipher "ECDHE-RSA-AES256-GCM-SHA384".
  • Good: You know which version and cipher work. Bad: All fail—check server config or escalate.

Fix server config

Goal: Enable TLS 1.2+ and compatible ciphers on the server.

  • Nginx: ssl_protocols TLSv1.2 TLSv1.3; and ssl_ciphers with a modern list (e.g. ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384).
  • Apache: SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1 and SSLCipherSuite.
  • Reload the server: systemctl reload nginx or systemctl reload apache2.
  • Good: openssl s_client -tls1_2 succeeds. Bad: Reload fails—check config syntax.

Update client

Goal: Update the client when it does not support TLS 1.2 or modern ciphers.

  • Update the OS, runtime (Java, Python, Node), or application to a version that supports TLS 1.2 and modern ciphers.
  • If you cannot update (legacy system), consider temporarily enabling older protocols on the server—weigh security vs compatibility.
  • Good: Updated client connects. Bad: Cannot update—escalate with evidence.

Rule out certificate

Goal: Separate certificate issues from version/cipher issues.

  • Run openssl s_client -connect HOST:443 -servername HOST 2>&1 | grep -i "verify\|certificate\|error". Verify errors indicate a cert problem.
  • Fix the cert first if needed. See fix-certificate-is-expired and fix-ssl-shows-error.
  • Good: No verify errors—focus on version/cipher. Bad: Verify error—fix cert first.

Escalate

Goal: Hand off when you cannot change server or client.

  • Capture the full openssl s_client output, client type and version, and server config (if available).
  • Contact the server admin or vendor with the exact handshake error and test results.

Verification

  • openssl s_client -connect HOST:443 -servername HOST completes without “handshake failure” or “no shared cipher.”
  • Output shows “Verify return code: 0 (ok)” and the certificate chain.
  • The failing client (browser, app) can connect to the site.

Escalation ladder

Work from the device outward. Stop when the problem is fixed.

  1. Confirm failure Run openssl s_client; capture exact error (handshake failure, no shared cipher, etc.).
  2. Version and cipher Test -tls1_2, -tls1_3, and specific ciphers to find what works.
  3. Rule out cert Check for verify errors; fix cert if needed before version/cipher.
  4. Fix server or client Enable TLS 1.2+ and ciphers on server, or update client.
  5. Escalate Capture openssl output, client type, server config; contact admin or vendor.

What to capture if you need help

Before calling support or posting for help, have these ready. It speeds everything up.

  • Full openssl s_client output (including error)
  • Result of -tls1_2 and -tls1_3 tests
  • Client type and version (browser, app, OS)
  • Server config (ssl_protocols, ssl_ciphers) if available
  • Whether a different client (e.g. browser) works

Does openssl s_client fail to connect?

Run openssl s_client -connect HOST:443 -servername HOST. Note the error.

Run openssl s_client -connect HOST:443 -servername HOST. Good: you see the error (handshake failure, no shared cipher, wrong version number). Bad: connection refused—check firewall, port, host. See fix-firewall-blocks-port.

You can change your answer later.

Does -tls1_2 work?

Test with openssl s_client -connect HOST:443 -servername HOST -tls1_2.

Run openssl s_client -connect HOST:443 -servername HOST -tls1_2. Works: server supports TLS 1.2; client may need update or different cipher. Fails: server may not have TLS 1.2 enabled—check server config.

You can change your answer later.

Is the failing client old or limited?

Legacy apps or old OS may not support TLS 1.2.

Check client: browser, app, OS version. Old client: update OS, runtime, or app. Modern client: check cipher—try specific cipher with -cipher. May be cert issue—run with -showcerts, check verify.

You can change your answer later.

Update client

Update the client, OS, or runtime (Java, Python, etc.) to support TLS 1.2 and modern ciphers. Retest. If you cannot update, consider enabling older protocols on server—weigh security risk.

Certificate or cipher issue?

Cert errors can cause handshake failure. Cipher mismatch causes "no shared cipher."

Check openssl output for verify errors. Verify error: fix cert—see fix-certificate-is-expired, fix-ssl-shows-error. No shared cipher: add compatible ciphers to server or use client that supports server ciphers.
Question

Cert or cipher?

Do you manage the server?

You need server access to enable TLS 1.2 and ciphers.

Yes: enable TLS 1.2+ and compatible ciphers in nginx/Apache. Reload. Retest with openssl s_client -tls1_2. No: escalate—contact server admin with openssl output.

You can change your answer later.

Enable TLS 1.2+ and ciphers

Set ssl_protocols TLSv1.2 TLSv1.3 (nginx) or equivalent. Set ssl_ciphers to a modern list. Reload. Run openssl s_client -tls1_2 again. Should succeed.

Escalate

Capture full openssl s_client output, client type and version, and (if available) server config. Contact server admin or vendor. They need the exact handshake error.

Connection or cert issue

If s_client succeeds, the issue may be client-specific or network.

If openssl s_client works, the server is OK. The failing client may have different TLS support or a network path issue. Test from another client. If connection refused, check firewall and port—see fix-firewall-blocks-port.

Reviewed by Blackbox Atlas

Frequently asked questions

Why does the TLS handshake fail?
Common causes are version mismatch (client supports only TLS 1.0, server requires 1.2+), no shared cipher (server and client have no cipher in common), or certificate issues. Use openssl s_client to see the exact error.
How do I test TLS with openssl?
Run openssl s_client -connect HOST:443 -servername HOST. A successful handshake shows "Verify return code: 0" and the certificate. A failure shows the error (e.g. "handshake failure," "no shared cipher"). Use -tls1_2 to force a specific version.
What does "no shared cipher" mean?
The server and client have no cipher suite in common. The server may be configured with only strong ciphers; the client may support only weak ones. Add compatible ciphers to the server config or update the client.

Rate this guide

Was this helpful?

Thanks for your feedback.

Continue to