Зачем администратору лезть в ClientHello/ServerHello
Когда пользователи жалуются «сайт не открывается», а в мониторинге растёт доля ошибок handshake failure, часто проблема не в сертификате «вообще», а в том, как именно клиент и сервер договариваются о параметрах TLS. В TLS 1.3 значимая часть «торговли» происходит в первом сообщении клиента — ClientHello.
Для админа/DevOps это практичный уровень: по следам в ClientHello/ServerHello можно понять, почему один браузер работает по HTTP/2, а другой откатывается на HTTP/1.1, почему на одном домене отдаётся «не тот» сертификат, и почему часть клиентов проходит TLS 1.3, а часть падает.
Ниже — концентрат того, что реально помогает в диагностике: SNI и ALPN, базовые параметры TLS 1.3, типовые причины раннего отказа и быстрые проверки через openssl s_client. Для сложных случаев разберём, как подключать sslkeylogfile и расшифровывать трафик.
Карта рукопожатия TLS 1.3: что где происходит
Если сильно упростить, в TLS 1.3 важны такие этапы:
- ClientHello — клиент сообщает поддерживаемые версии TLS, наборы шифров, группы для (EC)DHE, а также отправляет расширения (включая SNI и ALPN).
- ServerHello — сервер выбирает конкретные параметры (версия/шифр/группа) и фиксирует их.
- EncryptedExtensions — сервер подтверждает часть расширений уже в зашифрованном виде (часто именно тут видно согласованный ALPN).
- Certificate и CertificateVerify — сервер отправляет цепочку и доказывает владение приватным ключом.
- Finished — завершение рукопожатия.
Практический вывод: SNI обычно виден в ClientHello (если не используется ECH), а ALPN клиент объявляет в ClientHello, но что выбрано сервером, чаще проявляется позже. Поэтому «почему не HTTP/2» иногда нельзя понять по одному только ServerHello: удобнее смотреть вывод клиента, который печатает согласованный ALPN, либо расшифровывать трафик.

ClientHello: что важно для веба (TLS 1.3 + HTTP/2)
В ClientHello полезно фокусироваться на полях/расширениях, которые влияют на совместимость, выбор сертификата и выбор протокола прикладного уровня.
SNI (Server Name Indication): как сервер понимает, какой сертификат отдать
SNI — расширение, в котором клиент сообщает имя хоста (например, example.com). Это критично, когда на одном IP живёт несколько сайтов. Без SNI сервер обычно отдаёт «сертификат по умолчанию», а клиент затем ругается на несоответствие имени.
Если в браузере «сертификат не на этот домен», а на сервере соединения есть, но попадают не в тот виртуальный хост, первым делом проверяйте SNI.
Почему SNI может «не сработать» на практике:
- клиент очень старый и не отправляет SNI;
- TLS терминируется на балансировщике/прокси не там, где вы ожидаете (или разными устройствами по разным путям);
- маршрутизация L4/L7 уводит часть трафика на другой фронтенд;
- ошибка конфигурации: дефолтный виртуальный хост перехватывает соединение.
Отдельно полезно помнить про HTTP-код 421 (Misdirected Request) в связке SNI/виртуальных хостов. Если видите странные 421 и ощущение «иногда работает, иногда нет», разберите кейсы по статье HTTP 421 (Misdirected Request) из-за SNI за прокси/CDN.
ALPN: как выбирается HTTP/2 (h2) или HTTP/1.1
ALPN (Application-Layer Protocol Negotiation) — расширение, где клиент перечисляет поддерживаемые протоколы верхнего уровня: обычно h2 и http/1.1. Сервер выбирает один из предложенных.
Для HTTP/2 ALPN практически обязателен. Если на фронтенде не настроен HTTP/2 или промежуточное устройство не «видит» ALPN, клиент почти всегда уйдёт на http/1.1, даже если TLS 1.3 успешно поднимается.
Типовые причины, почему HTTP/2 «пропадает»:
- на фронтенде не включён HTTP/2 (слушается только HTTP/1.1);
- между клиентом и сервером стоит TLS-терминатор, который не умеет ALPN или не прокидывает его в нужной точке;
- подключение идёт на другой порт/endpoint, где HTTP/2 не настроен;
- клиент не предлагает
h2(редко, но бывает у специфичных библиотек/SDK).
Если вам нужен быстрый и предсказуемый способ закрыть вопросы доверия и совместимости на фронтенде, проще всего держать актуальный сертификат с полной цепочкой и адекватными настройками TLS. Для продакшена это обычно означает нормальный выпуск и своевременное продление: SSL-сертификаты.
supported_versions, key_share, signature_algorithms: частые причины раннего отказа в TLS 1.3
Три группы параметров чаще всего дают «обрыв на старте»:
- Версии протокола — в TLS 1.3 клиент сообщает их через
supported_versions. Если на сервере жёстко отключены TLS 1.2/1.3 так, что пересечения нет, получитеhandshake failureили ошибку версии. - Группы/кривые и key share — клиент отправляет
key_share(например,X25519,secp256r1). Если сервер не принимает предложенные группы, возможны ошибки или дополнительный шаг (HelloRetryRequest), на котором часть «нестандартных» клиентов ломается. - Алгоритмы подписи — например, сертификат ECDSA, а клиент не поддерживает нужные варианты из
signature_algorithms(или наоборот сервер слишком «зажал» список).
ServerHello: что закрепляется выбором сервера
ServerHello — точка, после которой параметры рукопожатия уже фиксированы. В TLS 1.3 обычно интересуют:
- на какой версии реально договорились (TLS 1.3 или откат на TLS 1.2);
- какой cipher suite выбрали (в TLS 1.3 наборы проще, чем в TLS 1.2);
- какую группу выбрали для обмена ключами (кривая/группа key share).
Согласованный ALPN (h2 или http/1.1) чаще всплывает в EncryptedExtensions и обычно проще проверяется с клиентской стороны по итоговому выводу инструментов.
Быстрая диагностика через openssl s_client: что проверять и как читать вывод
openssl s_client удобен тем, что позволяет быстро «воспроизвести» ключевые условия: SNI, версия TLS, ALPN. Этого хватает, чтобы отсеять половину типовых проблем за несколько минут.
1) Проверяем SNI и сертификат, который реально отдаётся
Важно: без указания имени хоста вы можете случайно тестировать «дефолтный» сертификат на IP.
openssl s_client -connect example.com:443 -servername example.com -showcerts
Что смотреть в выводе:
- какой сертификат пришёл (Subject/SAN и цепочка);
- не подменился ли сертификат на другой домен;
- нет ли проблем с цепочкой (например, не отдали intermediate).
2) Проверяем, договоримся ли именно на TLS 1.3
openssl s_client -connect example.com:443 -servername example.com -tls1_3
Для сравнения полезно принудительно проверить TLS 1.2:
openssl s_client -connect example.com:443 -servername example.com -tls1_2
Если на TLS 1.2 всё стабильно, а на TLS 1.3 падение, дальше имеет смысл проверять посредников (корпоративные прокси, инспекцию TLS, старые балансировщики) и политику групп/подписей на сервере.
3) Проверяем ALPN: будет ли HTTP/2
Просим сервер выбрать протокол из списка. Для проверки «поднимется ли h2» достаточно предложить h2:
openssl s_client -connect example.com:443 -servername example.com -alpn h2
Для сценария ближе к браузеру — предложить оба варианта:
openssl s_client -connect example.com:443 -servername example.com -alpn h2,http/1.1
В выводе ищите строку ALPN protocol:. Если там пусто или выбран http/1.1, значит h2 не согласован (не включён на фронте или ломается по пути).
4) Если видите handshake failure: порядок действий
handshake failure — это класс ошибок, а не одна причина. Самый быстрый алгоритм, чтобы сузить круг:
- Проверить SNI: выполнить тест с
-servernameи без него, сравнить сертификат и поведение. - Зафиксировать версию TLS: сравнить результаты
-tls1_3и-tls1_2. - Проверить ALPN: убедиться, что
h2реально согласуется на нужном endpoint. - Собрать контекст: какой именно клиент падает (браузер/приложение/бот), ОС, сеть, есть ли корпоративный прокси/антивирус с инспекцией.
Расшифровка TLS-сессии с sslkeylogfile: когда s_client уже не хватает
Иногда рукопожатие формально проходит, но дальше начинаются «призрачные» симптомы: разное поведение у разных клиентов, сбои на уровне HTTP/2, неожиданные ответы приложения. В таких случаях полезно расшифровать трафик в анализаторе, но TLS 1.3 «в лоб» без ключей не читается.
sslkeylogfile решает это со стороны клиента: клиент пишет секреты сессии в файл, и анализатор может использовать их для расшифровки TLS-трафика.
Файл ключей — чувствительный артефакт. Используйте только точечно для диагностики, храните минимально возможное время и удаляйте после анализа.
Практический сценарий (в общих шагах)
- на клиенте включить запись ключей в файл (переменной окружения или настройкой приложения);
- параллельно снять трафик между клиентом и сервером (например, через tcpdump на клиенте/шлюзе);
- открыть дамп в анализаторе и указать путь к файлу ключей, чтобы увидеть расшифрованные запросы/ответы, включая HTTP/2.
Такой подход особенно полезен, когда проблема воспроизводится только у части пользователей и серверные логи не дают ответа «почему именно так».

Типовые сценарии: где чаще всего ломается SNI/ALPN/TLS 1.3
Сценарий A: приходит «чужой» сертификат или цепочка неполная
Чаще всего это SNI/виртуальные хосты или терминация TLS не в том месте. Проверьте:
- что клиент реально отправляет SNI (тест с
-servername); - что на нужной точке терминации назначен правильный сертификат на это имя;
- что балансировщик/прокси не подсовывает другой сертификат «по умолчанию»;
- что отдаются intermediate-сертификаты (полная цепочка), а не только leaf.
Если у вас много доменов и регулярно приходится разбирать «не тот сертификат», держите в закладках статью TLS и CA в инфраструктуре: где ломаются цепочки доверия (полезно для понимания, где именно хранится и как обновляется доверие/цепочки в разных компонентах).
Сценарий B: HTTP/2 «то есть, то нет»
Если ощущение «иногда h2, иногда нет», обычно это разные точки терминации TLS или разные upstream’ы:
- часть трафика идёт через один фронтенд (с
h2), часть — через другой (безh2); - часть клиентов попадает на другой порт/виртуальный хост;
- на пути есть устройство, которое не дружит с ALPN и «обнуляет» согласование;
- на одном из фронтендов включены отличающиеся политики TLS (например, на одном есть TLS 1.3, на другом нет).
Практика: запускайте проверки ALPN с нескольких сетей/узлов и сравнивайте вывод. Это быстро выявляет «плавающую» точку терминации.
Сценарий C: handshake failure только у части клиентов
Наиболее частые причины:
- слишком строгие настройки групп/подписей/версий на сервере;
- только ECDSA-сертификат без RSA-фолбэка, а часть клиентов не поддерживает нужные алгоритмы;
- старые TLS-библиотеки на устройствах (встроенные устройства, старые Android/прошивки);
- прокси/антивирус с инспекцией TLS, который ломается на TLS 1.3.
Здесь помогает «паспорт» клиента: точная версия ОС/браузера/библиотеки, плюс сравнение тестов openssl s_client с принудительным TLS 1.2 и TLS 1.3.
Чек-лист: что фиксировать, когда «TLS/HTTP2 не работает»
- Домен, IP, порт, точное время и сеть/провайдер, откуда тестировали.
- Вывод
openssl s_clientс-servernameи без него (важно сравнение). - Результаты
-tls1_3и-tls1_2. - Результат ALPN:
-alpn h2,http/1.1. - Если нужно углубление: дамп трафика плюс файл ключей
sslkeylogfileс клиента (строго ограниченно и временно).
Вывод
TLS 1.3 ускоряет рукопожатие, но для диагностики это означает простую вещь: больше внимания к тому, что клиент просит в ClientHello, и к тому, что сервер фиксирует (и подтверждает) в ответных сообщениях. Для HTTP/2 ключевым триггером становится ALPN, а для правильного сертификата на многодоменных фронтендах — SNI.
Начинайте с базовой тройки проверок: SNI (-servername), версия TLS (-tls1_3/-tls1_2) и ALPN (-alpn h2,http/1.1). Если симптомы сложнее и уходят в уровень приложений/HTTP/2, подключайте sslkeylogfile и расшифровку трафика — это часто самый короткий путь увидеть, где именно всё «ломается».


