Сообщение об ошибке
SSL routines:ssl3_read_bytes:ssl/tls alert handshake failure
Также выводится как
- SSL routines:ssl3_read_bytes:sslv3 alert handshake failure
- SSL alert number 40
OpenSSL 3.3 и новее выводят «ssl/tls alert handshake failure», более ранние версии — «sslv3 alert handshake failure» (код тот же, 0A000410; в 1.1.1 был 14094410). В конце строки указаны место в исходном коде и «SSL alert number 40».
OpenSSL (client side) — TLS alert 40 (handshake_failure) received from the server
Что это означает
Сервер отправил оповещение TLS 40 (handshake_failure) и закрыл соединение. Это обобщённый отказ: сервер не нашёл в ClientHello приемлемого набора шифров, группы обмена ключами или алгоритма подписи, потребовал клиентский сертификат или отклонил запрошенное имя сервера. Узнать причину из оповещения клиент не может: она записана в журнале сервера.
Почему это происходит
Нет общего набора шифров
частоУстаревшие серверы, которые принимают только наборы шифров с обменом ключами RSA, с 3DES или с RC4; либо строгие серверы, которые разрешают лишь несколько наборов, и их нет у старого клиента.
Требуется клиентский сертификат (TLS 1.2)
частоВ TLS 1.2 многие серверы отвечают на отсутствующий или неприемлемый клиентский сертификат оповещением handshake_failure; серверы TLS 1.3 вместо него используют certificate_required (оповещение 116).
Нет SNI или имя в SNI неизвестно
иногдаopenssl s_client отправляет SNI, только если хост задан именем или указан параметр -servername; CDN и мультитенантные прокси прерывают рукопожатия, в которых нет известного им имени.
Нет общей группы или общего алгоритма подписи
редкоСерверы, которые допускают только одну группу (например, постквантовую гибридную) или только подписи RSA-PSS, могут не договориться с клиентами, которые не предлагают ни того ни другого.
Как исправить
- 1.
Посмотрите журнал сервера
Сервер записывает настоящую причину, например «no shared cipher» или «peer did not return a certificate».
bash # The server knows why; with openssl s_server or nginx the log says e.g. # ...:tls_post_process_client_hello:no shared cipher # ...:tls_process_client_certificate:peer did not return a certificate sudo tail -n 50 /var/log/nginx/error.log | grep -i ssl - 2.
Сузьте круг причин со стороны клиента
Меняйте SNI, версию протокола, список шифров и наличие клиентского сертификата: вариант, который сработает, покажет, чего не хватает.
bash h=api.example.com echo | openssl s_client -connect $h:443 -servername $h -brief # with SNI echo | openssl s_client -connect $h:443 -servername $h -tls1_2 -cipher 'ALL:@SECLEVEL=0' -brief echo | openssl s_client -connect $h:443 -servername $h -cert client.pem -key client.key -brief # mTLS - 3.
Владельцам серверов: предлагайте современные наборы шифров
Связка из TLS 1.3 и TLS 1.2 с наборами шифров на основе ECDHE и AEAD работает с любым клиентом, который ещё получает обновления.
text # nginx: modern suites for TLS 1.2 plus 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;
Связанные ошибки
SSL routines:tls_post_process_client_hello:no shared cipherOpenSSL (server side: nginx, Apache, Postfix, openssl s_server)SSL routines:tls_process_client_certificate:peer did not return a certificateOpenSSL (server side, mutual TLS)curl: (35) TLS connect error: error:0A000410:SSL routines::ssl/tls alert handsh…curl (OpenSSL backend)[SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] ssl/tls alert handshake failurePython ssl module (OpenSSL)