Fehlermeldung
curl: (35) TLS connect error: error:0A000410:SSL routines::ssl/tls alert handshake failure
Auch ausgegeben als
- curl: (35) error:0A000410:SSL routines::sslv3 alert handshake failure
- curl: (35) error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure
Ab OpenSSL 3.3 lautet der Grund „ssl/tls alert handshake failure“; OpenSSL 3.1 und älter geben „sslv3 alert handshake failure“ aus (1.1.1 mit dem Code 14094410 und dem Funktionsnamen ssl3_read_bytes). Neuere curl-Releases stellen „TLS connect error: “ voran.
curl (OpenSSL backend) — CURLE_SSL_CONNECT_ERROR, TLS alert 40 (handshake_failure) received from the server
Was der Fehler bedeutet
Der Server hat den Handshake mit dem TLS-Alert 40 (handshake_failure) beendet: Er konnte sich mit dem, was curl angeboten hat, nicht auf Parameter einigen. Der Alert enthält keinen Grund, deshalb ist die tatsächliche Ursache nur in den Logs des Servers zu sehen; auf Client-Seite kannst du nur vergleichen, was beide Seiten unterstützen. Das Zertifikat wurde zu diesem Zeitpunkt noch nicht geprüft.
Warum der Fehler auftritt
Keine gemeinsame Cipher Suite
häufigVeraltete Server, die auf RSA-Schlüsselaustausch oder Suites mit CBC-SHA1, 3DES oder RC4 beschränkt sind, treffen auf Clients, die diese entfernt haben; gehärtete Server, die nur wenige Suites zulassen, treffen auf alte Clients, denen diese fehlen. In beiden Fällen findet der Server im ClientHello nichts Akzeptables.
Der Client hat den Servernamen (SNI) nicht gesendet
häufigCDNs und mandantenfähige Proxys (Cloudflare, AWS CloudFront, viele Kubernetes-Ingresses) lehnen Handshakes ohne SNI oder für Namen ab, die sie nicht bedienen. Eine Verbindung über die IP-Adresse oder mit Tools, die SNI weglassen, löst genau diesen Alert aus.
Der Server verlangt ein Client-Zertifikat
gelegentlichManche Server mit TLS 1.2, die für Mutual TLS konfiguriert sind, beantworten ein fehlendes oder nicht akzeptables Client-Zertifikat mit handshake_failure statt mit den spezifischeren Zertifikats-Alerts.
Keine gemeinsame Schlüsselaustauschgruppe oder kein gemeinsamer Signaturalgorithmus
gelegentlichEin Server, der nur eine hybride Post-Quanten-Gruppe, eine Brainpool-Kurve oder RSA-PSS-Signaturen zulässt, kann an Clients scheitern, die diese nicht anbieten; umgekehrt gilt dasselbe für sehr alte Clients.
So behebst du den Fehler
- 1.
Vergleichen, was beide Seiten anbieten
Ermittle die Suites und Protokollversionen des Servers und vergleiche sie mit der Cipher-Liste des Clients. Die ausführliche Ausgabe von curl zeigt, wie weit der Handshake gekommen ist und welche Version versucht wurde.
bash # What the server accepts (needs nmap) and what this client offers nmap --script ssl-enum-ciphers -p 443 api.example.com openssl ciphers -v 'DEFAULT' | head -20 # Full handshake trace from curl's side curl -sv https://api.example.com/ -o /dev/null 2>&1 | grep -E '^\* (TLS|SSL)' - 2.
Eigener Server: aktuelle Cipher-Konfiguration verwenden
Biete TLS 1.3 und TLS 1.2 mit ECDHE- und AEAD-Suites an (AES-GCM, ChaCha20-Poly1305). Jeder Client der letzten zehn Jahre unterstützt sie, und nichts Modernes braucht RSA-Schlüsselaustausch oder CBC.
text # nginx: TLS 1.2 with forward-secret AEAD suites + TLS 1.3 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:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305; ssl_prefer_server_ciphers off; - 3.
Richtigen Servernamen senden
Verwende den Hostnamen in der URL oder behalte den Namen bei und erzwinge die Adresse mit --resolve. Übergib bei openssl s_client die Option -servername, wenn du dich mit einer IP verbindest.
bash # Use the host name in the URL (SNI is sent automatically); for IP targets keep the name: curl --resolve api.example.com:443:203.0.113.10 https://api.example.com/ # openssl s_client sends SNI only with -servername (or a host name in -connect) openssl s_client -connect 203.0.113.10:443 -servername api.example.com </dev/null - 4.
Client-Zertifikat für Mutual TLS vorlegen
Ist der Endpunkt eine mTLS-API, konfiguriere Client-Zertifikat und Schlüssel; in den Logs des Servers taucht das Problem als fehlendes oder nicht prüfbares Peer-Zertifikat auf.
bash # Mutual TLS: present the client certificate and key the server expects curl --cert client.pem --key client.key https://mtls.example.com/
Verwandte Fehler
SSL routines:ssl3_read_bytes:ssl/tls alert handshake failureOpenSSL (client side)SSL routines:tls_post_process_client_hello:no shared cipherOpenSSL (server side: nginx, Apache, Postfix, openssl s_server)curl: (35) TLS connect error: error:0A00042E:SSL routines::tlsv1 alert protocol…curl (OpenSSL backend)[SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] ssl/tls alert handshake failurePython ssl module (OpenSSL)javax.net.ssl.SSLHandshakeException: (handshake_failure) Received fatal alert:…Java (JSSE)