Zum Inhalt springen
ecdsa.com
curl (OpenSSL backend)curl

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

So behebst du den Fehler

  1. 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. 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. 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. 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

Gesamte Signaturfehler-Datenbank durchsuchen