Skip to content
← Все статьи

SSL Handshake Failed: причины ошибки и пошаговая диагностика

SSL Handshake Failed: причины ошибки и пошаговая диагностика

Ошибка «SSL handshake failed» — собирательное название для десятка разных проблем, возникающих во время установки TLS-соединения. Клиент и сервер не смогли договориться о параметрах: версии протокола, cipher suite, сертификате или SNI. В этой статье разберём все типичные причины, покажем команды для диагностики и дадим алгоритм, который за 15 минут приведёт к первопричине.

Что такое TLS handshake и где он может сломаться

TLS handshake — это многоступенчатый обмен сообщениями между клиентом и сервером перед началом шифрованной передачи данных. В TLS 1.2 он занимает 2 RTT, в TLS 1.3 — 1 RTT. На каждом шаге может произойти сбой:

  1. ClientHello: клиент присылает список поддерживаемых версий TLS, cipher suites и SNI.
  2. ServerHello: сервер выбирает версию и cipher, отправляет свой сертификат.
  3. Certificate verification: клиент проверяет цепочку сертификатов, срок действия, домен.
  4. Key exchange: стороны договариваются о сессионном ключе (ECDHE, RSA).
  5. Finished: обе стороны подтверждают согласованные параметры.

Ошибка handshake — это провал на одном из этих шагов. Чтобы найти, где именно, нужен подробный лог. Запустите:

openssl s_client -connect example.com:443 -servername example.com -tlsextdebug -status
# или в verbose-режиме
curl -vI https://example.com 2>&1 | grep -E "TLS|SSL|handshake"

Причина 1: несовместимые версии протокола

Самая частая причина — клиент поддерживает только TLS 1.0/1.1, а сервер давно отключил эти версии (и правильно сделал). Проверьте, какие версии принимает сервер:

for v in tls1 tls1_1 tls1_2 tls1_3; do
    echo -n "$v: "
    openssl s_client -connect example.com:443 -$v < /dev/null 2>&1 | grep "Cipher is"
done

Если клиент — старый Java (до 8u261), iOS < 11, Windows XP, Android < 4.4 — он не поддерживает TLS 1.2+. Решение: обновить клиент или (в крайнем случае) временно разрешить TLS 1.1 на сервере до миграции. Подробнее о миграции — в статье «TLS 1.3 vs TLS 1.2: миграция».

Причина 2: несовпадение SNI

SNI (Server Name Indication) — расширение TLS, позволяющее хостить несколько SSL/TLS проверку-сайтов на одном IP. Клиент должен в ClientHello указать, к какому хосту подключается. Если SNI не указан или указан неверный — сервер либо вернёт дефолтный сертификат, либо откажет в handshake:

# БЕЗ SNI — часто даёт handshake failure
openssl s_client -connect example.com:443

# С SNI — работает
openssl s_client -connect example.com:443 -servername example.com

Проблема встречается у старых curl, wget, скриптов на Python 2, IoT-устройств. Обновите клиент или явно передавайте SNI.

Причина 3: несовместимые cipher suites

Клиент и сервер должны иметь хотя бы один общий cipher suite. Если вы ужесточили конфигурацию nginx до AEAD-only, старые клиенты (например, с RSA-key-exchange) отвалятся. Проверьте, какие ciphers предлагает сервер:

nmap --script ssl-enum-ciphers -p 443 example.com

Безопасный и совместимый Mozilla Intermediate-профиль для nginx:

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;

Подробнее о выборе cipher suites — в статье «Слабые cipher suites».

Причина 4: проблема с сертификатом сервера

Handshake может упасть из-за проблем самого сертификата:

Полная диагностика цепочки:

openssl s_client -connect example.com:443 -servername example.com -showcerts < /dev/null \
    | openssl verify -CApath /etc/ssl/certs

Причина 5: mutual TLS (клиентский сертификат)

Если сервер настроен на mTLS, он требует от клиента собственный сертификат. Без него handshake падает с CertificateRequired. В nginx это выглядит так:

ssl_client_certificate /etc/nginx/ca.crt;
ssl_verify_client on;  # или optional

Клиент должен передать сертификат:

curl --cert client.crt --key client.key https://api.example.com

Причина 6: MITM-прокси, антивирусы, корпоративные файрволы

На клиенте может стоять прокси, который перехватывает TLS (Kaspersky, ESET, корпоративный Zscaler). Он подменяет сертификат своим, а клиент этого не ожидает. Симптомы: «self-signed certificate in chain» в curl, хотя сайт нормальный. Решение — добавить CA прокси в доверенные или отключить проверку только для тестов (никогда в проде).

Алгоритм диагностики за 15 минут

  1. Запустите SSL Checker enterno.io — получите общую оценку и список проблем.
  2. openssl s_client -connect host:443 -servername host — смотрите на первую ошибку.
  3. Проверьте версии протокола и cipher suites (см. выше).
  4. Проверьте срок действия и цепочку сертификата.
  5. Попробуйте с другого клиента / другой сети (исключить MITM-прокси).
  6. Сверьте конфиг nginx/Apache с Mozilla SSL Config Generator.

Часто задаваемые вопросы

Handshake работает с curl, но падает с браузером — почему?

Скорее всего проблема в OCSP stapling или в неподдерживаемом cipher. Браузер строже, чем curl. Запустите тест на SSL Labs — он симулирует handshake десятков разных клиентов.

Как включить подробный лог TLS-ошибок в nginx?

error_log /var/log/nginx/error.log debug; + ssl_debug on; в новых версиях. Смотрите на строки с «SSL_do_handshake() failed».

TLS 1.3 всегда совместим со старыми клиентами?

Нет. Многие клиенты до 2018 года TLS 1.3 не поддерживают. Рекомендуется одновременно держать TLS 1.2 и 1.3.

Ошибка «alert handshake failure» — что это?

Это generic-сообщение от OpenSSL. Нужен более детальный лог — либо со стороны сервера (nginx debug), либо openssl s_client -tlsextdebug -msg со стороны клиента.

Заключение

SSL handshake failed — это всегда конкретная причина: версия, cipher, сертификат, SNI или mTLS. Методичная проверка через openssl за 15 минут доводит до первопричины в 95% случаев. SSL Checker от enterno.io ускоряет первый шаг — запустите его перед ручной отладкой, чтобы сразу исключить очевидное. Постоянный мониторинг сайтов через Monitors предупредит об ухудшении конфигурации после деплоя.

TLS 1.3 — RFC 8446. SNI — RFC 6066. Генератор конфигов — Mozilla SSL Config Generator.

Проверьте ваш сайт прямо сейчас

Проверить →
Другие статьи: SSL
SSL
Слабые cipher suites: как найти и отключить небезопасные шифры TLS
15.04.2026 · 6 просм.
SSL
Просроченный SSL-сертификат: как исправить ошибку NET::ERR_CERT_DATE_INVALID
15.04.2026 · 7 просм.
SSL
Неполная цепочка SSL-сертификата: как найти и исправить incomplete chain
15.04.2026 · 7 просм.
SSL
TLS 1.3 vs TLS 1.2: что изменилось и как правильно мигрировать
15.04.2026 · 9 просм.