Перейти к содержимому
ecdsa.com
rustls (via reqwest, ureq, tonic)Rust

Сообщение об ошибке

received fatal alert: HandshakeFailure

reqwest выводит эту ошибку в конце цепочки ошибок, ureq — как «io: received fatal alert: HandshakeFailure». При подключении к серверу, который поддерживает только TLS 1.0 (tls-v1-0.badssl.com), наш клиент на rustls получил это же оповещение. Другие оповещения выводятся под своими именами из rustls после «received fatal alert: ».

rustls (via reqwest, ureq, tonic) — rustls::Error::AlertReceived(HandshakeFailure)

Что это означает

Сервер ответил на ClientHello от rustls оповещением TLS 40 (handshake_failure). rustls намеренно реализует только современный TLS: TLS 1.2 и 1.3 с обменом ключами ECDHE и шифрами AEAD. Серверы, которым нужны обмен ключами RSA, наборы шифров с CBC, TLS 1.0/1.1 или клиентский сертификат, отклоняют подключение rustls именно так.

Почему это происходит

Как исправить

  1. 1.

    Проверьте, что предлагает сервер

    Если сервер не предлагает ни одного набора шифров ECDHE + AEAD, его нужно модернизировать.

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

    Крайняя мера для устаревшего сервера, который нельзя обновить: native-tls

    Отдельный клиент, собранный с feature native-tls в reqwest, использует платформенную библиотеку TLS (в Linux это OpenSSL, и для сборки нужны его заголовочные файлы для разработки), а эта библиотека может ещё разрешать старые наборы шифров, если это допускает системная политика. Используйте такой клиент только для устаревшего эндпоинта; слабая конфигурация сервера по-прежнему остаётся риском.

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

    Взаимная TLS-аутентификация: предъявите клиентский сертификат

    Вызовите reqwest::Identity::from_pem для PEM, в котором есть сертификат и закрытый ключ, и передайте полученный Identity в ClientBuilder.

    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()?;

Связанные ошибки

Открыть всю базу ошибок подписей