awesome-everything EN
↑ Обратно к восхождению

Сети и протоколы

Возобновление сессии и 0-RTT

Суть PSK-тикеты позволяют тёплым соединениям пропустить валидацию сертификата; ранние данные 0-RTT убирают RTT рукопожатия для запросов только для чтения — но атаки повтора ограничивают то, что может безопасно попасть в ранние данные.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на middle-высоте — в небе
◷ 12 min

Первое TLS-соединение с сервером стоит один полный RTT. Но когда вы перезагружаете ту же страницу пять минут спустя, браузер уже знает этот сервер. TLS 1.3 позволяет ему полностью пропустить валидацию сертификата — а в правильных условиях приложить первый запрос прямо к рукопожатию, не платя ни одного лишнего RTT.

NewSessionTicket и возобновление по PSK

После успешного рукопожатия сервер отправляет сообщение NewSessionTicket — зашифрованный блоб, содержащий предварительно согласованный ключ (PSK) и метаданные (возраст тикета, время жизни). Клиент кэширует его по имени хоста.

При следующем подключении к тому же серверу клиент включает расширение pre_shared_key в свой ClientHello вместе с тикетом. Сервер расшифровывает тикет, распознаёт PSK и полностью пропускает валидацию сертификата. Он выводит сессионные ключи из PSK вместо ECDHE.

Стоимость: по-прежнему один полный RTT (ClientHello всё равно должен дойти до сервера), но никаких дорогих операций PKI. Разбор сертификата и проверка цепочки исключаются.

Ранние данные 0-RTT

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

Сравнение RTT-стоимости
TLS 1.2 холодное
2 RTT
TLS 1.3 холодное
1 RTT
TLS 1.3 тёплое (возобновление PSK)
1 RTT (без сертификата)
TLS 1.3 0-RTT
0 RTT для запроса
При 100 мс RTT: выигрыш 0-RTT
100 мс против холодного TLS 1.3
Типичное время жизни тикета
до нескольких часов (зависит от реализации)

Проблема повтора

У 0-RTT есть фундаментальная уязвимость безопасности: он не защищён от атак повтора. Злоумышленник в сети может перехватить ClientHello с 0-RTT и переотправить его серверу. Сервер, увидев валидный PSK-тикет и валидные ранние данные, может обработать запрос снова.

  • Для GET /news: повтор безвреден — то же чтение, тот же результат.
  • Для POST /transfer: повтор катастрофичен — строка в базе данных создаётся дважды, деньги переводятся дважды.

Простейшее правило: 0-RTT безопасен только для идемпотентных запросов, где повтор не производит дополнительных побочных эффектов. GET, HEAD и OPTIONS обычно безопасны. POST, PUT, DELETE, изменяющие состояние, — небезопасны.

RFC 8470 и 425 Too Early

RFC 8470 определяет код HTTP-ответа 425 Too Early: сервер возвращает его, когда получает 0-RTT-запрос для маршрута, который небезопасно повторять. Клиент должен повторить попытку после завершения рукопожатия. Фреймворки (Spring, Express, Caddy) предоставляют промежуточное ПО, которое проверяет заголовок запроса Early-Data: 1 и возвращает 425 Too Early для любого обработчика, изменяющего состояние.

Проследи
1/4

POST /transfer приходит с TLS early_data и ticket_age = 5 секунд. Проследите путь принятия решений сервером.

1
Step 1 of 4
Шаг 1: Находится ли ticket_age внутри окна повтора (по умолчанию 10 с)?
2
Locked
Шаг 2: Встречался ли ранее этот nonce тикета (кэш одноразового использования)?
3
Locked
Шаг 3: Тикет свежий и не встречался. Какова третья проверка?
4
Locked
Шаг 4: GET /catalog/42 приходит в том же корректном 0-RTT-контексте. Что происходит?
Викторина

Почему злоумышленник может повторить 0-RTT ранние данные, но не обычные данные TLS 1.3?

Викторина

Возобновление PSK пропускает валидацию сертификата. Как клиент всё ещё знает, что разговаривает с нужным сервером?

Почему это работает

Обфускация NewSessionTicket. Каждый тикет включает ticket_age_add — случайное значение, которое клиент прибавляет к реальному возрасту тикета перед отправкой obfuscated_ticket_age. Это не позволяет наблюдателям на пути коррелировать тикеты между соединениями по видимому возрасту. Это также делает проверки окна повтора на основе времени более надёжными: сервер вычитает ticket_age_add, чтобы восстановить реальный возраст и сравнить его с ожидаемым RTT-окном.

Вспомните перед уходом
  1. 01
    Что сервер отправляет после рукопожатия, чтобы включить будущее возобновление?
  2. 02
    Почему 0-RTT ограничен идемпотентными HTTP-методами?
  3. 03
    Какой код статуса должен возвращать сервер для 0-RTT POST к мутирующей конечной точке, и что должен сделать клиент?
Итог

После рукопожатия TLS 1.3 сервер выдаёт NewSessionTicket с предварительно согласованным ключом. При следующем подключении клиент предъявляет этот тикет, чтобы сервер мог пропустить валидацию сертификата — по-прежнему один RTT, но дешевле. При наличии кэшированного PSK клиент может также зашифровать первый запрос прямо внутри ClientHello как ранние данные 0-RTT: сервер обрабатывает его до завершения рукопожатия, экономя полный RTT. Подвох — уязвимость к повтору: тот же ClientHello с 0-RTT может быть перехвачен и переотправлен злоумышленником. Безопасное использование ограничено идемпотентными запросами (GET, HEAD, OPTIONS), а серверы должны возвращать 425 Too Early для любой мутирующей конечной точки, получающей ранние данные.

Связанные уроки
встречается в152
Продолжить восхождение ↑Расписание ключей, SNI, ALPN и расширения
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.