Message d’erreur
code: 'ERR_SSL_SSL/TLS_ALERT_HANDSHAKE_FAILURE'
Également affiché sous la forme
- ERR_SSL_SSL/TLS_ALERT_HANDSHAKE_FAILURE
Le code reprend la chaîne de raison d’OpenSSL : les versions de Node.js qui embarquent OpenSSL 3.0 ou 3.1 signalent ERR_SSL_SSLV3_ALERT_HANDSHAKE_FAILURE (issu de « sslv3 alert handshake failure ») ; les versions actuelles, avec OpenSSL 3.5, signalent ERR_SSL_SSL/TLS_ALERT_HANDSHAKE_FAILURE. Avec https.request(), la même alerte apparaît sous la forme « write EPROTO … SSL alert number 40 ».
Node.js tls.connect / fetch — TLS alert 40 (handshake_failure) received from the server
Ce que cela signifie
Le serveur a répondu au ClientHello de Node.js par l’alerte TLS 40 (handshake_failure) et a fermé la connexion. Il n’a trouvé aucune combinaison acceptable de suite de chiffrement, de groupe d’échange de clés et d’algorithme de signature, ou bien il exige un certificat client qui n’a pas été envoyé. Node.js dérive le code d’erreur du texte de la raison donné par OpenSSL, c’est pourquoi il contient « SSL/TLS ».
Pourquoi cela se produit
Aucune suite de chiffrement en commun
fréquenteLes anciens serveurs limités aux suites à échange de clés RSA, 3DES ou RC4 se heurtent à la liste de chiffrements par défaut de Node.js, qui ne les contient plus.
Le serveur exige un certificat client (mTLS)
fréquenteLes API de paiement, bancaires et B2B exigent souvent le TLS mutuel ; sans cert ni key dans l’agent, les serveurs TLS 1.2 abandonnent avec handshake_failure.
SNI absent ou inconnu
occasionnelleSe connecter à une adresse IP sans servername, ou à un nom que le CDN ne sert pas, amène certains serveurs frontaux à rejeter le handshake.
Comment corriger l’erreur
- 1.
Comparer ce que prennent en charge les deux parties
Affichez la liste de chiffrements par défaut de Node.js et énumérez les suites du serveur ; si elles n’ont rien en commun, le serveur doit être mis à jour.
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.
Envoyer le certificat client
Configurez cert et key (ou pfx) sur l’agent utilisé pour le point de terminaison 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.
Propriétaires de serveurs : proposer des suites actuelles
TLS 1.3 associé à TLS 1.2 avec ECDHE et AES-GCM ou ChaCha20-Poly1305 fonctionne avec toutes les versions maintenues de Node.js.
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;
Erreurs associées
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)