Mensaje de error
code: 'ERR_SSL_SSL/TLS_ALERT_HANDSHAKE_FAILURE'
También se muestra como
- ERR_SSL_SSL/TLS_ALERT_HANDSHAKE_FAILURE
El código refleja la cadena del motivo de OpenSSL: las versiones de Node.js que incluyen OpenSSL 3.0 o 3.1 informan de ERR_SSL_SSLV3_ALERT_HANDSHAKE_FAILURE (a partir de «sslv3 alert handshake failure»); las versiones actuales, con OpenSSL 3.5, informan de ERR_SSL_SSL/TLS_ALERT_HANDSHAKE_FAILURE. Con https.request(), la misma alerta aparece como «write EPROTO … SSL alert number 40».
Node.js tls.connect / fetch — TLS alert 40 (handshake_failure) received from the server
Qué significa
El servidor respondió al ClientHello de Node.js con la alerta TLS 40 (handshake_failure) y cerró la conexión. No encontró ninguna combinación aceptable de conjunto de cifrado, grupo de intercambio de claves y algoritmo de firma, o exige un certificado de cliente que no se envió. Node.js deriva el código de error del texto del motivo de OpenSSL, y por eso contiene «SSL/TLS».
Por qué ocurre
Ningún conjunto de cifrado en común
frecuenteLos servidores antiguos limitados a conjuntos con intercambio de claves RSA, con 3DES o con RC4 se topan con una lista de cifrados predeterminada de Node.js que ya no los incluye.
El servidor exige un certificado de cliente (mTLS)
frecuenteLas API de pagos, de banca y B2B suelen exigir TLS mutuo; sin las opciones cert y key en el agente, los servidores TLS 1.2 abortan con handshake_failure.
SNI ausente o desconocido
ocasionalConectarse a una dirección IP sin servername, o a un nombre que la CDN no sirve, hace que algunos servidores frontales rechacen el handshake.
Cómo solucionarlo
- 1.
Comparar lo que admite cada lado
Imprime la lista de cifrados predeterminada de Node.js y enumera los conjuntos del servidor; si no coinciden en ninguno, hay que actualizar el servidor.
bash node -p "require('tls').getCiphers().length + ' suites; default list: ' + require('tls').DEFAULT_CIPHERS" nmap --script ssl-enum-ciphers -p 443 api.example.com # what the server accepts - 2.
Enviar el certificado de cliente
Configura cert y key (o pfx) en el agente que se usa para el endpoint mTLS.
js // Mutual TLS: present the client certificate the server requires import https from "node:https"; import fs from "node:fs"; const agent = new https.Agent({ cert: fs.readFileSync("client.pem"), key: fs.readFileSync("client.key") }); https.get("https://mtls.example.com/", { agent }, (res) => res.resume()); - 3.
Propietarios del servidor: ofrecer conjuntos actuales
TLS 1.3, más TLS 1.2 con ECDHE y AES-GCM o ChaCha20-Poly1305, funciona con todas las versiones de Node.js que siguen con mantenimiento.
text # Server side (nginx): TLS 1.3 + TLS 1.2 ECDHE with AEAD ciphers ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
Errores relacionados
curl: (35) TLS connect error: error:0A000410:SSL routines::ssl/tls alert handsh…curl (OpenSSL backend)SSL routines:ssl3_read_bytes:ssl/tls alert handshake failureOpenSSL (client side)[SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] ssl/tls alert handshake failurePython ssl module (OpenSSL)javax.net.ssl.SSLHandshakeException: (handshake_failure) Received fatal alert:…Java (JSSE)