TLS handshake по шагам: что происходит за 100 миллисекунд до загрузки сайта

Полный разбор первого диалога браузера и сервера: версии, ключи, сертификаты, RTT

5 мая 2026 8 мин чтения TooTimes Team

Откройте F12 на любом современном сайте и посмотрите вкладку Network. Рядом с временем ответа почти каждого ресурса есть полоска SSL/TLS — те самые 30–150 миллисекунд, которые тратятся на TLS handshake. Это короткий, но очень насыщенный обмен сообщениями, без которого ни один HTTPS-запрос не уходит в сеть.

За это время браузер и сервер должны решить три задачи: договориться, на каком языке говорить (версия протокола, набор шифров, алгоритмы подписи), удостовериться, что собеседник действительно тот, за кого себя выдаёт (сертификат), и сгенерировать общий секрет, из которого выводятся ключи шифрования. Всё это нужно сделать так, чтобы пассивный наблюдатель не восстановил ключ, а активный посредник не смог незаметно подменить ответы.

Браузер                                Сервер
ClientHello                    ───────►
  versions, cipher_suites, key_share,
  SNI, ALPN, signature_algorithms
                               ◄───────  ServerHello (выбор)
                               ◄───────  EncryptedExtensions
                               ◄───────  Certificate (внутри TLS!)
                               ◄───────  CertificateVerify
                               ◄───────  Finished
Finished                       ───────►
GET /                          ───────►  (внутри защищённого канала)
                               ◄───────  200 OK + payload
Полный TLS 1.3 handshake занимает 1 RTT: уже после третьего сообщения по сети идут зашифрованные данные приложения.

Зачем вообще нужен handshake

HTTPS-соединение состоит из двух слоёв. Снаружи — TCP (или QUIC поверх UDP), который доставляет байты. Внутри — защищённый канал, в котором шифруются данные приложения. Чтобы построить этот канал, обеим сторонам нужно сделать четыре вещи одновременно и без права на ошибку: выбрать версию TLS из своих списков (1.2, 1.3, иногда экспериментальные); сошлись по cipher suite (например, TLS_AES_128_GCM_SHA256 для AES-NI или TLS_CHACHA20_POLY1305_SHA256 для мобильных без аппаратного ускорения); согласовать параметры подписи и группы для ECDHE; и наконец договориться о ключе.

Главная инженерная идея TLS 1.3 — ускорение. В TLS 1.2 handshake занимал 2 RTT поверх 1 RTT TCP. На дальних маршрутах (Москва ↔ Калифорния) это легко превращалось в 600–800 мс до первого байта. TLS 1.3 уменьшил handshake до одного RTT, выкинув устаревшие алгоритмы (RSA key exchange, RC4, MD5, SHA-1) и сделав структуру предсказуемой.

ClientHello: визитка клиента

Первое сообщение всегда отправляет клиент. Его содержимое можно мысленно разделить на пять блоков.

  • Список версий. В TLS 1.3 поле legacy_version по совместимости равно 0x0303 (вид TLS 1.2), а реальные версии передаются в расширении supported_versions.
  • Cipher suites. В TLS 1.3 их всего пять, в TLS 1.2 — десятки. Современные браузеры ставят первым TLS_AES_128_GCM_SHA256 на устройствах с AES-NI и TLS_CHACHA20_POLY1305_SHA256 там, где AES в железе нет.
  • Расширения. SNI с именем хоста, ALPN со списком прикладных протоколов (h2, http/1.1, h3), signature_algorithms, supported_groups (x25519, secp256r1) и главное — key_share с уже сгенерированной открытой частью ECDHE-ключа.
  • 32 байта случайности (client_random). Это число войдёт в формулу вывода ключей и помешает повторному воспроизведению одной и той же сессии.
  • PSK или session ID. Если соединение возобновляется, сюда кладётся идентификатор предыдущей сессии для быстрого старта.

Именно по этому первому сообщению чаще всего классифицируют клиента: порядок расширений, набор шифров и поддерживаемые группы образуют узнаваемый отпечаток JA3/JA4. Подробнее это разбирается в статье про сигнатуры и метаданные.

Ответ сервера и зашифрованные расширения

Сервер выбирает один cipher suite, одну группу для ECDHE и возвращает ServerHello с собственной случайностью и своим key_share. Уже после этого сообщения обе стороны умеют считать симметричные ключи: каждая перемножает свой приватный ECDHE-ключ с публичным от собеседника и получает один и тот же общий секрет.

Дальше начинается важное отличие от TLS 1.2: все следующие сообщения сервера шифруются handshake-ключом. Открытым текстом летят только ClientHello и ServerHello, дальше идут EncryptedExtensions с параметрами вроде ALPN-результата, потом сертификат сервера, CertificateVerify с подписью по транскрипту и наконец Finished — HMAC по всему handshake. В TLS 1.2 сертификат летел по сети открытым текстом, в 1.3 он закрыт криптографией. SNI же по-прежнему остаётся снаружи — пока не включён ECH, о котором отдельно рассказано в материале про SNI и ECH.

Как браузер проверяет сертификат

Сертификат сервера — это структура X.509, в которой указан домен, открытый ключ, срок действия и подпись вышестоящего удостоверяющего центра. Браузер выполняет несколько проверок последовательно, и любая из них может прервать соединение.

ПроверкаЧто именно смотрит браузер
Цепочка доверияОт листового сертификата до корневого CA, встроенного в ОС или браузер. Сломанная цепочка — UNKNOWN_ISSUER.
Срок действияСовременные сертификаты живут 90–398 дней. С 2026 года Apple и Google идут к 47 дням.
ИмяПоле SAN должно содержать запрошенный домен — точно или через wildcard *.example.com для одного уровня.
Статус отзываOCSP stapling: сервер сам прикладывает свежий ответ от CA. Без него браузер может сходить в OCSP сам или довериться короткому сроку.
ПрозрачностьSCT-метки от Certificate Transparency-логов. Без них Chrome ругается на любой публичный сайт.

Если хотя бы одна проверка не сходится, пользователь увидит экран с предупреждением. Это не формальность: без проверки сертификата шифрование защищало бы только от случайного слушателя, но не от активной подмены посередине.

Откуда берётся симметричный ключ и что такое forward secrecy

Полезные данные шифруются быстрыми симметричными алгоритмами вроде AES-GCM или ChaCha20-Poly1305. Но сам AES-ключ нельзя просто отправить по сети — кто угодно мог бы его перехватить. Поэтому используется ECDHE: эллиптический Диффи–Хеллман с эфемерными ключами.

  1. Стороны договариваются о группе (например, x25519) и каждая генерирует пару: приватный ключ остаётся у себя, публичный летит в key_share.
  2. Каждая сторона перемножает свой приватный с чужим публичным и получает общий секрет — но восстановить его, видя только публичные части, вычислительно невозможно.
  3. Из общего секрета через HKDF выводится дерево ключей: для handshake, для трафика клиент→сервер, для трафика сервер→клиент, для exporter'ов.

Главное свойство ECDHE — forward secrecy. Даже если завтра у сервера украдут приватный ключ сертификата, расшифровать ранее перехваченный трафик не получится: эфемерные ECDHE-ключи каждый раз новые и уже не существуют ни у одной стороны. Именно поэтому в TLS 1.3 RSA key exchange запрещён — он не давал forward secrecy.

1-RTT, 0-RTT и резюмирование сессий

В TLS 1.2 на согласование требовалось 2 RTT поверх трёх RTT TCP. TLS 1.3 спроектирован вокруг 1-RTT: клиент отправляет key_share сразу в первом сообщении, и после ответа сервера может тут же отдавать запрос приложения.

Для повторных подключений есть 0-RTT: клиент берёт PSK от прошлой сессии и сразу шифрует им так называемые early data — например, GET /. Это приятно для скорости, но опасно для повторного воспроизведения: один и тот же запрос может быть доставлен несколько раз, если сетевой посредник его сохранит и переиграет. Поэтому 0-RTT обычно разрешают только для идемпотентных запросов и не разрешают для платежей и POST-форм.

В QUIC и HTTP/3 эти концепции переехали внутрь транспорта, и эффект становится ещё заметнее. Подробнее транспорт разобран в статье про QUIC и TCP.

Типичные ошибки и что они значат на самом деле

СообщениеЧто произошло
ERR_SSL_VERSION_OR_CIPHER_MISMATCHУ клиента и сервера нет общей версии или шифра. Часто — устаревший сервер с TLS 1.0 или 1.1.
NET::ERR_CERT_AUTHORITY_INVALIDЦепочка не доходит до доверенного корня. Самоподписанный сертификат или забытый промежуточный CA.
NET::ERR_CERT_DATE_INVALIDСертификат просрочен или часы устройства уехали. Иногда лечится синхронизацией NTP.
NET::ERR_CERT_COMMON_NAME_INVALIDДомен не совпадает с SAN. Типично при доступе к сайту по IP или поддомену без wildcard.
handshake_failureСервер закрыл соединение посреди обмена. Часто — несовпадение sigalgs или некорректный SNI на multi-tenant хостинге.

Полезный приём при диагностике — запустить openssl s_client -connect host:443 -servername host -tls1_3 и посмотреть весь handshake глазами. Большинство «загадочных» проблем с HTTPS оказываются ровно в этих сообщениях.

Итого

TLS handshake — не магия и не «формальность перед загрузкой». За 1 RTT в нём решается всё, ради чего вообще существует HTTPS: договорённость о версии, выбор шифров, проверка личности сервера, согласование ключей с forward secrecy и защита транскрипта. Понимание этих шагов делает прозрачными десятки повседневных явлений: от ошибок браузера до поведения CDN, прокси и сетевого оборудования.

Нужен стабильный защищённый доступ к интернету?

TooTimes — зашифрованный туннель до серверов в 9 странах, без логов.

Посмотреть тарифы
✎ Панель блога