The handshake_failure alert (TLS alert code 40) is sent when the TLS handshake cannot complete because the client and server are unable to negotiate an acceptable set of security parameters. This is one of the most generic TLS alerts and can be triggered by a wide range of issues: no common cipher suites, no common TLS protocol versions, client certificate requirements not met, or the server rejecting the handshake for internal reasons. Unlike more specific alerts (like protocol_version or insufficient_security), handshake_failure is a catch-all that requires deeper investigation to identify the root cause.
The client's ClientHello offered cipher suites that the server does not support, and vice versa. This often happens when one side is configured with a very restrictive cipher list. The server sends handshake_failure when it cannot find a cipher from the client's list that it is willing to use.
The server is configured for mutual TLS and sent a CertificateRequest during the handshake, but the client did not respond with a valid certificate. Some servers send handshake_failure instead of the more specific bad_certificate alert.
The server uses SNI to route connections to virtual hosts. If the hostname in the SNI extension does not match any configured virtual host, some servers send handshake_failure rather than completing the handshake with a default certificate.
A bug or misconfiguration in the server's TLS library (OpenSSL, BoringSSL, GnuTLS) can cause it to abort the handshake. This includes issues like unreadable certificate files, corrupted private keys, or DH parameter problems.
Use openssl s_client with verbose output to see exactly where the handshake fails. The error message after the connection attempt will indicate whether it is a cipher issue, protocol issue, or certificate issue.
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com -state -debug 2>&1 | head -50
Use nmap to list all cipher suites the server accepts. Compare this against what modern browsers support to identify mismatches.
nmap --script ssl-enum-ciphers -p 443 yourdomain.com
Ensure the domain resolves correctly to the server with the TLS configuration. DNS mispointing can connect you to a server without TLS or with different TLS settings.
Check PropagationConfirm the certificate and private key match and that the server can read them. A mismatch between certificate and key will cause the handshake to fail.
openssl x509 -noout -modulus -in cert.pem | openssl md5 && openssl rsa -noout -modulus -in key.pem | openssl md5
If the server requires client certificates, you need to provide one. Test with curl using your client certificate to verify.
curl -v --cert client.crt --key client.key https://yourdomain.com/
The browser could not establish a secure connection because the SSL/TLS protocol negotiation failed.
The browser and server could not agree on a supported SSL/TLS version or cipher suite.
The server rejected the cipher suites offered by the client because they do not meet minimum security requirements.
The TLS protocol version offered by the client is not supported by the server.