Fehlermeldung
code: 'ERR_SSL_SSL/TLS_ALERT_HANDSHAKE_FAILURE'
Auch ausgegeben als
- ERR_SSL_SSL/TLS_ALERT_HANDSHAKE_FAILURE
Der Code spiegelt den Reason-String von OpenSSL wider: Node.js-Releases mit OpenSSL 3.0 oder 3.1 melden ERR_SSL_SSLV3_ALERT_HANDSHAKE_FAILURE (aus „sslv3 alert handshake failure“); aktuelle Releases mit OpenSSL 3.5 melden ERR_SSL_SSL/TLS_ALERT_HANDSHAKE_FAILURE. Bei https.request() erscheint derselbe Alert als „write EPROTO … SSL alert number 40“.
Node.js tls.connect / fetch — TLS alert 40 (handshake_failure) received from the server
Was der Fehler bedeutet
Der Server hat das ClientHello von Node.js mit dem TLS-Alert 40 (handshake_failure) beantwortet und die Verbindung geschlossen. Er hat keine akzeptable Kombination aus Cipher Suite, Schlüsselaustauschgruppe und Signaturalgorithmus gefunden, oder er verlangt ein Client-Zertifikat, das nicht gesendet wurde. Node.js leitet den Fehlercode aus dem Reason-Text von OpenSSL ab, deshalb enthält er „SSL/TLS“.
Warum der Fehler auftritt
Keine gemeinsame Cipher Suite
häufigAlte Server, die auf Suites mit RSA-Schlüsselaustausch, 3DES oder RC4 beschränkt sind, treffen auf eine Standard-Cipher-Liste von Node.js, die solche Suites nicht mehr enthält.
Der Server verlangt ein Client-Zertifikat (mTLS)
häufigZahlungs-, Banking- und B2B-APIs verlangen oft Mutual TLS; ohne cert und key im Agenten brechen Server mit TLS 1.2 mit handshake_failure ab.
SNI fehlt oder ist unbekannt
gelegentlichEine Verbindung zu einer IP-Adresse ohne servername oder zu einem Namen, den das CDN nicht bedient, bringt manche Frontends dazu, den Handshake abzulehnen.
So behebst du den Fehler
- 1.
Vergleichen, was beide Seiten unterstützen
Gib die Standard-Cipher-Liste von Node.js aus und ermittle die Suites des Servers; gibt es keine Überschneidung, muss der Server aktualisiert werden.
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.
Client-Zertifikat senden
Konfiguriere cert und key (oder pfx) in dem Agenten, der für den mTLS-Endpunkt verwendet wird.
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.
Eigener Server: aktuelle Suites anbieten
TLS 1.3 und dazu TLS 1.2 mit ECDHE und AES-GCM oder ChaCha20-Poly1305 funktioniert mit jedem gepflegten Node.js-Release.
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;
Verwandte Fehler
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)