Fehlermeldung
received fatal alert: HandshakeFailure
reqwest gibt die Meldung am Ende seiner Fehlerkette aus, ureq als „io: received fatal alert: HandshakeFailure“. Gegen einen Server, der nur TLS 1.0 spricht (tls-v1-0.badssl.com), hat unser rustls-Client genau diesen Alert erhalten. Andere Alerts erscheinen mit ihren eigenen rustls-Namen nach „received fatal alert: “.
rustls (via reqwest, ureq, tonic) — rustls::Error::AlertReceived(HandshakeFailure)
Was der Fehler bedeutet
Der Server hat das ClientHello von rustls mit dem TLS-Alert 40 (handshake_failure) beantwortet. rustls implementiert bewusst nur modernes TLS: TLS 1.2 und 1.3 mit ECDHE-Schlüsselaustausch und AEAD-Verschlüsselungsverfahren. Server, die RSA-Schlüsselaustausch, CBC-Suites, TLS 1.0/1.1 oder ein Client-Zertifikat verlangen, weisen rustls auf diese Weise ab.
Warum der Fehler auftritt
Keine Cipher Suite, die rustls implementiert
häufigVeraltete Server, die auf Suites mit RSA-Schlüsselaustausch, CBC-SHA oder 3DES beschränkt sind, haben mit rustls nichts gemeinsam.
Der Server spricht nur TLS 1.0 oder 1.1
häufigrustls implementiert keine TLS-Versionen unter 1.2.
Der Server verlangt ein Client-Zertifikat
gelegentlichEndpunkte mit Mutual TLS beantworten unter TLS 1.2 einen Client ohne Zertifikat mit handshake_failure.
So behebst du den Fehler
- 1.
Prüfen, was der Server anbietet
Bietet der Server keine Suite mit ECDHE + AEAD an, muss er modernisiert werden.
bash # What does the server accept? rustls offers TLS 1.2/1.3 with ECDHE + AES-GCM or ChaCha20 only nmap --script ssl-enum-ciphers -p 443 legacy.example.com - 2.
Letzter Ausweg für einen nicht mehr wartbaren Altserver: native-tls
Ein eigener Client, gebaut mit dem Feature native-tls von reqwest, verwendet die TLS-Bibliothek der Plattform (unter Linux OpenSSL, dessen Entwicklungs-Header zum Bauen nötig sind), und diese Bibliothek erlaubt je nach Systemrichtlinie womöglich noch ältere Suites. Setze diesen Client nur für den alten Endpunkt ein; die schwache Konfiguration des Servers bleibt ein Risiko.
toml # A legacy server you cannot upgrade: build a separate client on the OS TLS library # (OpenSSL on Linux), which still implements older suites. Cargo.toml: reqwest = { version = "=0.13.5", default-features = false, features = ["native-tls", "blocking"] } - 3.
Mutual TLS: Client-Zertifikat vorlegen
reqwest::Identity::from_pem mit einem PEM, das Zertifikat und privaten Schlüssel enthält, am Builder gesetzt.
rust // Mutual TLS with rustls: present a client certificate (PEM with certificate + private key) let identity = reqwest::Identity::from_pem(&std::fs::read("client-cert-and-key.pem")?)?; let client = reqwest::Client::builder().identity(identity).build()?;