RFC 9000 QUIC: A UDP-Based Multiplexed and Secure Transport

image_print
Internet Engineering Task Force (IETF)                   J. Iyengar, Ed.
Request for Comments: 9000                                        Fastly
Category: Standards Track                                M. Thomson, Ed.
ISSN: 2070-1721                                                  Mozilla
                                                                May 2021

QUIC: A UDP-Based Multiplexed and Secure Transport

Мультиплексируемый защищённый транспорт QUIC на основе UDP

PDF

Аннотация

Этот документ описывает ядро транспортного протокола QUIC, обеспечивающего приложениям управляемые потоки данных для структурированных коммуникаций с малой задержкой при организации соединений и возможностью изменения пути через сеть. QUIC включает средства защиты, обеспечивающие конфиденциальность, целостность и доступность в разных условиях развёртывания. В сопроводительных документах описана интеграция с TLS для согласования ключей, обнаружения потерь и алгоритма контроля перегрузок.

Статус документа

Документ относится к категории Internet Standards Track.

Документ является результатом работы IETF1 и представляет согласованный взгляд сообщества IETF. Документ прошёл открытое обсуждение и был одобрен для публикации IESG2. Дополнительную информацию о стандартах Internet можно найти в разделе 2 в RFC 7841.

Информацию о текущем статусе документа, ошибках и способах обратной связи можно найти по ссылке https://www.rfc-editor.org/info/rfc9000.

Авторские права

Авторские права (Copyright (c) 2021) принадлежат IETF Trust и лицам, указанным в качестве авторов документа. Все права защищены.

Этот документ является субъектом прав и ограничений, перечисленных в BCP 78 и IETF Trust Legal Provisions и относящихся к документам IETF (http://trustee.ietf.org/license-info), на момент публикации данного документа. Прочтите упомянутые документы внимательно, поскольку в них описаны права и ограничения, относящиеся к данному документу. Фрагменты программного кода, включённые в этот документ, распространяются в соответствии с упрощённой лицензией BSD, как указано в параграфе 4.e документа Trust Legal Provisions, без каких-либо гарантий (как указано в Simplified BSD License).

Оглавление

Исключено в варианте HTML.

1. Обзор

QUIC представляет собой защищённый транспортный протокол общего назначения. Этот документ определяет протокол QUIC версии 1 с независимыми от версии свойствами QUIC, определёнными в [QUIC-INVARIANTS].

Протокол QUIC ориентирован на соединения и обеспечивает взаимодействие между клиентом и сервером с учётом состояния.

Согласование (handshake) QUIC объединяет в себе выбор криптографических и транспортных параметров. QUIC включает в себя согласование TLS [TLS13], хотя для защиты пакетов применяется специальное кадрирование. Интеграция TLS и QUIC более подробно описана в [QUIC-TLS]. Согласование структурировано для максимального быстрого начала обмена данными приложения и позволяет клиенту начать передачу данных незамедлительно (0-RTT), для чего нужна та или иная предшествующая связь или настройка конфигурации.

Конечные точки QUIC взаимодействуют путём обмена пакетами QUIC, большинство которых содержат кадры, переносящие между конечными точками данные управления и приложений. QUIC проверяет подлинность каждого пакета и шифрует пакеты, насколько это практично. Пакеты QUIC передаются в дейтаграммах UDP [UDP] для упрощения развёртывания в существующих системах и сетях.

Протоколы приложение обмениваются информацией через соединение QUIC в форме потока, представляющего собой упорядоченную последовательность байтов. Возможно создание двух типов потоков – двухсторонних, где данные могут передавать обе конечных точки и односторонних, где данные может передавать лишь одна конечная точка. Для управления созданием потоков и объёмом передаваемых данных служит схема на основе кредита.

QUIC обеспечивает обратную связь для реализации гарантированной доставки и контроля перегрузок. Алгоритм обнаружения потери данных и восстановления описан в разделе 6 [QUIC-RECOVERY]. Для предотвращения перегрузок в сети QUIC использует специальный механизм, описанный в разделе 7 [QUIC-RECOVERY].

Соединения QUIC не привязаны строго к одному пути через сеть и для их перемещения в сети применяются специальные идентификаторы. В данной версии QUIC соединения могут переноситься лишь клиентами. Протокол позволяет сохранять соединения при изменении топологии сети или отображения адреса, например, при смене привязки NAT.

Для организованного соединения имеется множество вариантов завершения (разрыва). Приложения могут использовать аккуратное завершение (graceful shutdown), конечные точки могут согласовать время ожидания (тайм-аут), ошибки могут приводить к немедленному разрыву соединения, а механизм без учёта состояния обеспечивает завершение соединения после потери одной из конечных точек.

1.1. Структура документа

Этот документ описывает ядро протокола QUIC и состоит из нескольких частей, перечисленных ниже.

  • Потоки, являющиеся базовой абстракцией QUIC;

    • базовые концепции, связанные с потоками (раздел 2);

    • эталонная модель состояний потоков (раздел 3);

    • управление потоком данных (раздел 4).

  • Соединения, обеспечивающие контекст взаимодействия конечных точек QUIC;

    • базовые концепции, связанные с соединениями (раздел 5);

    • согласование версий (раздел 6);

    • процесс организации соединения (раздел 7);

    • проверка действительности адреса и ослабление DoS3-атак (раздел 8);

    • перенос конечными точками соединения на другой путь (раздел 9);

    • варианты прерывания соединений (раздел 10);

    • рекомендации по обработке ошибок в потоках и соединениях (раздел 11).

  • Пакеты и кадры, являющиеся базовыми блоками коммуникаций QUIC:

    • концепции, связанные с пакетами и кадрами (раздел 12);

    • модели передачи, повтора и подтверждения данных (раздел 13);

    • правила управления размером дейтаграмм для передачи пакетов QUIC (раздел 14).

  • Кодирование элементов протокола QUIC:

    • версии (раздел 15);

    • целые числа (раздел 16);

    • заголовки пакетов (раздел 17);

    • транспортные параметры (раздел 18);

    • кадры (раздел 19);

    • ошибки (раздел 20).

В сопровождающих документах описано детектирование потерь и контроль перегрузок в QUIC [QUIC-RECOVERY], а также использование TLS и других криптографических механизмов [QUIC-TLS].

Этот документ определяет протокол QUIC версии 1, соответствующий инвариантам, заданным в [QUIC-INVARIANTS].

Для указания QUIC версии 1 следует ссылаться на этот документ, для указания независимого от версии ограниченного набора свойств QUIC – [QUIC-INVARIANTS].

1.2. Термины и определения

Ключевые слова необходимо (MUST), недопустимо (MUST NOT), требуется (REQUIRED), нужно (SHALL), не следует (SHALL NOT), следует (SHOULD), не нужно (SHOULD NOT), рекомендуется (RECOMMENDED), не рекомендуется (NOT RECOMMENDED), возможно (MAY), необязательно (OPTIONAL) в данном документе интерпретируются в соответствии с BCP 14 [RFC2119] [RFC8174] тогда и только тогда, когда они выделены шрифтом, как показано здесь.

Ниже приведены определения используемых в документе терминов.

QUIC

Транспортный протокол, описанный в этом документе. QUIC — это имя, а не сокращение.

Endpoint – конечная точка

Сущность, которая может участвовать в соединении QUIC путём генерации, получения и обработки пакетов QUIC. В протоколе QUIC имеется лишь два типа конечных точек – клиенты и серверы.

Client – клиент

Конечная точка, инициирующая соединение QUIC.

Server – сервер

Конечная точка, воспринимающая соединение QUIC.

QUIC packet – пакет QUIC

Пригодный для обработки законченный блок QUIC, который может быть инкапсулирован в дейтаграмму UDP. Одна дейтаграмма UDP может содержать один или несколько пакетов QUIC.

Ack-eliciting packet – пакет с запросом подтверждения

Пакет QUIC, содержащий кадры, отличные от ACK, PADDING, CONNECTION_CLOSE. Такой пакет заставляет получателя передать подтверждение (см. параграф 13.2.1. Передача кадров ACK).

Frame – кадр

Блок структурированной информации протокола. Имеется множество типов кадров, каждый из которых содержит свою информацию. Кадры содержатся в пакетах QUIC.

Address – адрес

При использовании без уточнения — кортеж из номера версии IP, адреса IP и номера порта UDP, представляющих один конец пути через сеть.

Connection ID – идентификатор соединения

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

Stream – поток

Односторонний или двухсторонний канал (передачи) упорядоченных байтов в соединении QUIC. Соединение QUIC может поддерживать множество потоков одновременно.

Application – приложение

Сущность, использующая протокол QUIC для передачи и приёма данных.

В документе применяются термины «пакеты QUIC», «дейтаграммы UDP» и «пакеты IP» для обозначения блоков данных соответствующего протокола. Таким образом, один или несколько пакетов QUIC может быть инкапсулировано в дейтаграмму UDP, которая инкапсулирована в пакет IP.

1.3. Соглашения о нотации

Для представления пакетов и кадров в этом документе применяется свой формат, предназначенный для обобщения, а не для определения элементов протокола. Семантика и детали структур указываются в виде текста. Составные поля указываются именем, а затем следует список полей в фигурных скобках через запятые. Отдельные поля включают сведения о размере, а также указания о фиксированном значении, необязательности или повторах. Для полей применяются указанные ниже обозначения (размеры задаются в битах).

x (A)

Поле x размером A битов.

x (i)

Поле x содержит целое число с представлением размера, описанным в разделе 16.

x (A..B)

Указывает, что x может иметь любой размер от A до B, если A не указано, поле может иметь размер 0, отсутствие B говорит, что размер поля не ограничен. Значения в этом формате всегда завершаются на границе байта.

x (L) = C

Указывает, что x имеет фиксированное значение C, размером L в одной из приведённых выше форм.

x (L) = C..D

Указывает, что x имеет значение из диапазона от C до D, включительно, и имеет размер L, как указано выше.

[x (L)]

Указывает необязательность x размера L.

x (L) …

Указывает повторение x (возможно пустой набор), где каждый экземпляр имеет размер L.

В документе применяется сетевой порядок байтов (big endian), поля указываются со старшего бита в каждом байте.

Отдельные поля составного поля указываются с именем составного поля. На рисунке 1 представлен пример.

   Example Structure {
     One-bit Field (1),
     7-bit Field with Fixed Value (7) = 61,
     Field with Variable-Length Integer (i),
     Arbitrary-Length Field (..),
     Variable-Length Field (8..24),
     Field With Minimum Length (16..),
     Field With Maximum Length (..128),
     [Optional Field (64)],
     Repeated Field (8) ...,
   }

Рисунок 1. Пример формата.


При упоминании однобитового поля его позицию можно уточнить используя байт, содержащий поле с установленным значением. Например, значение 0x80 может служить ссылкой на старший бит байта, как One-bit Field на рисунке 1.

2. Потоки

Потоки в QUIC предоставляют приложению облегчённой абстракции упорядоченного потока байтов. Потоки могут быть односторонними и двухсторонними.

Потоки могут создаваться передачей данных. Другие процессы, связанные с управлениям потоками, завершение, отмена, управление потоком данных – организованы так, чтобы вносить минимальные издержки. Например, один кадр STREAM (параграф 19.8. Кадр STREAM) может создать поток, передать в нем данные и закрыть поток. Потоки могут также быть долгоживущими и сохраняться в течение всего срока работы соединения.

Потоки может создавать любая конечная точка и можно чередовать данные разных потоков, а также отменять потоки. QUIC не включает средств упорядочения байтов между разными потоками.

QUIC позволяет одновременную работу произвольного числа потоков и передачу в потоке произвольного объёма данных с учётом ограничений самого потока и управления потоком данных (см. раздел 4. Управление потоком).

2.1. Типы и идентификаторы потоков

Потоки могут быть односторонними и двухсторонними. В одностороннем потоке данные передаются от инициатора его партнёру, в двухстороннем – в обоих направлениях.

Потоки в соединении указываются идентификаторами (stream ID) в форме 62-битовых целочисленных значений от 0 до 262-1, которые однозначно указывают поток внутри соединения. Идентификаторы потоков представляются целыми числами переменного размера (см. раздел 16). Конечной точке QUIC недопустимо повторно применять идентификатор потока в том же соединении.

Младший бит идентификатора (0x01) указывает инициатора потока. Для потоков, созданных клиентом, этот бит сброшен (0), а для инициированных сервером потоков установлен (1). Таким образом, инициированные клиентом потоки имеют чётные идентификаторы, инициированные сервером – нечётные. Второй (с конца) бит идентификатора (0x02) указывает двухсторонний (0) или односторонний (1) поток. Эти два младших бита идентификатора указывают один из 4 типов потоков, показанных в таблице 1.

Таблица 1. Типы идентификаторов потока.

Биты

Тип потока

0x00

Двухсторонний по инициативе клиента

0x01

Двухсторонний по инициативе сервера

0x02

Односторонний по инициативе клиента

0x03

Односторонний по инициативе сервера

Пространство номеров потоков каждого типа начинается с минимального значения (от 0x00 до 0x03) и последующие потоки каждого типа создаются с увеличивающимся численным значением идентификатора. Создание потока с пропуском в пространстве идентификаторов ведёт к созданию потоков со всеми пропущенными номерами.

2.2. Передача и приём данных

Кадры STREAM (параграф 19.8) инкапсулируют данные, переданные приложением. Конечная точка использует поля Stream ID и Offset в кадрах STREAM для упорядочения данных. Конечные точки должны быть способны доставлять приложению поток данных в форме упорядоченного потока байтов. Доставка упорядоченного потока байтов требует от конечной точки буферизации полученных с нарушением порядка данных вплоть до объявленного предела управления потоком данных. QUIC не задаёт конкретных требований для доставки потоков данных с нарушением порядка. Однако реализация может предлагать возможность доставки данных принимающему приложению с нарушением порядка.

Конечная точка может получать данные для потока с одним смещением несколько раз и данные, которые уже были получены, отбрасываются. Данные с одним смещением недопустимо менять, если они передаются более одного раза. Конечная точка может рассматривать получение разных данных с одним смещением в потоке как ошибку соединения типа PROTOCOL_VIOLATION.

Поток является абстракцией упорядоченного потока байтов без представления протоколу QUIC его структуры. При передаче, повторе в случае потери пакета и доставке данных приложению не предполагается сохранение границ кадров STREAM.

Конечное точке недопустимо передавать данные в поток без гарантии выполнения установленных партнёром ограничений управления потоком данных (см. раздел 4. Управление потоком).

2.3. Приоритизация потока

Мультиплексирование потоков может существенно влиять на производительность приложения, если выделяемые потокам ресурсы корректно приоритизированы. QUIC не задаёт механизма обмена данными приоритизации, опираясь на информацию о приоритетах, полученную от приложения.

Реализации QUIC следует обеспечивать приложениям способ указания относительного приоритета потоков. Сведения о приоритете от приложения используются при распределении ресурсов, выделяемых потокам.

2.4. Операции над потоками

Этот документ не определяет API для протокола QUIC, а задаёт набор функций для потоков, на которые может полагаться прикладной протокол. Протокол приложения может полагать, что реализация QUIC обеспечивает интерфейс, описанный в этом параграфе. Реализации, созданные для применения с конкретным прикладным протоколом, могут предоставлять лишь используемые этим протоколом операции.

На передающей стороне потока прикладной протокол может:

  • записывать данные, понимая, когда протокол управления потоком данных (параграф 4.1) успешно зарезервирован для отправки записанных данных;

  • завершать поток (аккуратно), в результате чего в кадре STREAM (параграф 19.8) устанавливается бит FIN;

  • сбрасывать поток (аварийно), в результате чего появляется кадр RESET_STREAM (параграф 19.4), если поток ещё не находится в завершающем состоянии.

На приёмной стороне потока прикладной протокол может:

  • читать данные;

  • прерывать чтение из потока и запрашивать закрытие, возможно с появлением кадра STOP_SENDING (параграф 19.5).

Прикладной протокол может также запросить информирование об изменении статуса потоков, включая открытие или сброс потока партнёром, когда тот прекращает считывание потока, нет доступных данных или управление потоком данных не позволяет запись в поток.

3. Состояния потока

В этом разделе потоки описываются с точки зрения передающей и приёмной стороны. Описаны два конечных автомата, один для потоков передающей конечной точки (параграф 3.1), другой – для приёмной (параграф 3.2).

Односторонние потоки используют один из этих автоматов в зависимости от типа потока и роли конечной точки. В двухсторонних потоках на каждой стороне применяются оба конечных автомата. Использование этих конечных автоматов в значительной степени одинаково для односторонних и двухсторонних потоков. Условия создания потока чуть сложнее для двухстороннего потока, поскольку создание потока приёмной или передающей стороной ведёт к созданию встречного потока.

В этом разделе конечные автоматы представлены в основном для информации. Документ использует состояния потоков для описания правил отправки разных типов кадров и реакции на получение разных типов кадров. Хотя эти автоматы предназначены для использования реализациями QUIC, описание не предназначено для задания ограничений. Реализация может определить свой конечный автомат, обеспечивающий поведение, соответствующее этому документу.

Примечание. В некоторых случаях одно событие или действие может вызывать переход через несколько состояний. Например, отправка STREAM с установленным флагом FIN может вызывать две смены состояния передающего потока – из Ready в Send и из Send в Data Sent.

3.1. Состояния передающего потока

На рисунке 2 показаны состояния передающей стороны потока. Передающая сторона потока, который инициирует конечная точка (типы 0 и 2 для клиентов, 1 и 3 для серверов), создаётся приложением. Состояние Ready представляет вновь созданный поток, способный воспринимать данные от приложения. В этом состоянии данные потока могут буферизоваться для подготовки к их передаче.

    o
    | Создание потока (передающего)
    | Партнер создаёт двухсторонний поток
    v
+-------+
| Ready | Отправка RESET_STREAM
|       |-----------------------.
+-------+                       |
    |                           |
    | Отправка STREAM /         |
    |      STREAM_DATA_BLOCKED  |
    v                           |
+-------+                       |
| Send  | Отправка RESET_STREAM |
|       |---------------------->|
+-------+                       |
    |                           |
    | Отправка STREAM + FIN     |
    v                           v
+-------+                   +-------+
| Data  |Отпр. RESET_STREAM | Reset |
| Sent  |------------------>| Sent  |
+-------+                   +-------+
    |                           |
    | Получены все ACK          | Получение ACK
    v                           v
+-------+                   +-------+
| Data  |                   | Reset |
| Recvd |                   | Recvd |
+-------+                   +-------+

Рисунок 2. Состояния передающих частей потока.


Отправка первого кадра STREAM или STREAM_DATA_BLOCKED вызывает переход передающей стороны в состояние Send. Реализация может отложить выделение идентификатора потоку до отправки первого кадра STREAM и перехода в это состояние, что может позволить лучше приоритизировать потоки.

Передающая часть двухстороннего потока, инициированного партнёром (тип 0 для сервера, 1 для клиента), запускается в состоянии Ready при создании приёмной части.

В состоянии Send конечная точка передаёт (при необходимости повторно) данные потока в кадрах STREAM, соблюдая ограничения управления потоком данных, установленные партнёром, и продолжает воспринимать и обрабатывать кадры MAX_STREAM_DATA. Конечная точка в состоянии Send генерирует кадры STREAM_DATA_BLOCKED, если отправка для неё заблокирована ограничениями управления потоком данных (параграф 4.1).

После того, как приложение указало, что все данные потока отправлены, и передало кадр STREAM с флагом FIN, передающая сторона переходит в состояние Data Sent. Из этого состояния конечная точка лишь повторяет передачу данных потока при необходимости. В этом состоянии конечной точке не нужно проверять ограничения контроля потока данных или передавать кадры STREAM_DATA_BLOCKED. Пока партнёр не получит данные с конечным смещением для потока, могут приходить кадры MAX_STREAM_DATA, которые конечная точка в этом состоянии может игнорировать.

После подтверждения всех данных потока передающая сторона переходит в завершающее состояние Data Recvd.

Из состояний Ready, Send, Data Sent приложение может сигнализировать о своём желании прервать передачу данных потока. Кроме того, конечная точка может получить от партнёра кадр STOP_SENDING. В любом из этих случаев конечная точка передаёт кадр RESET_STREAM, переводящий поток в состояние Reset Sent.

Конечная точка может передать RESET_STREAM в качестве первого кадра, где упоминается поток. Это ведёт к созданию передающей стороной потока и его незамедлительный переход в состояние Reset Sent.

После подтверждения пакета, содержащего RESET_STREAM, передающая сторона переходит в завершающее состояние Reset Recvd.

3.2. Состояния принимающего потока

На рисунке 3 показаны состояния принимающей стороны потока. Эти состояния отражают лишь некоторые из состояний потока передающей стороны у партнёра. Приёмная сторона не отслеживает состояний передающей, которые невозможно наблюдать, например Ready, а отслеживает доставку данных приложению и некоторые из этих состояний отправителю не видны.

    o
    | Получено STREAM / STREAM_DATA_BLOCKED / RESET_STREAM
    | Создание двухстороннего потока (передача)
    | Получено MAX_STREAM_DATA / STOP_SENDING (двухстороннее)
    | Создание потока с большим номером
    v
+-------+
| Recv  | Получено RESET_STREAM
|       |-----------------------.
+-------+                       |
    |                           |
    | Получено STREAM + FIN     |
    v                           |
+-------+                       |
| Size  | Получено RESET_STREAM |
| Known |---------------------->|
+-------+                       |
    |                           |
    | Получены все данные       |
    v                           v
+-------+Получ. RESET_STREAM+-------+
| Data  |--- (необязат) --->| Reset |
| Recvd |Получены все данные| Recvd |
+-------+<-- (необязат) ----+-------+
    |                           |
    | Прилож. считало все данные| Приложение сбросило чтение
    v                           v
+-------+                   +-------+
| Data  |                   | Reset |
| Read  |                   | Read  |
+-------+                   +-------+

Рисунок 3. Состояния принимающих частей потока.


Принимающая сторона потока, инициированного партнёром (типы 1 и 3 для клиента, 0 и 2 для сервера) создаётся при получении для потока первого кадра STREAM, STREAM_DATA_BLOCKED или RESET_STREAM. Для двухсторонних потоков, инициированных партнёром, получение кадра MAX_STREAM_DATA или STOP_SENDING для передающей стороны также создаёт приёмную часть. Исходным состоянием для приемной стороны потока является Recv. Для двухстороннего потока принимающая часть переходит в состояние Recv, когда инициированная конечной точкой передающая часть (тип 0 для клиента, 1 для сервера) переходит в состояние Ready.

Конечная точка создаёт двухсторонний поток при получении от партнёра кадра MAX_STREAM_DATA или STOP_SENDING. Приём кадра MAX_STREAM_DATA для несозданного потока показывает, что удалённый партнёр создал поток и предоставил кредит контроля потока данных. Получение кадра STOP_SENDING для несозданного потока говорит о нежелании удалённого партнёра продолжать приём данных в этом потоке. Любой из этих кадров может приходить до приёма STREAM или STREAM_DATA_BLOCKED, если пакеты теряются или нарушается порядок.

До создания потока должны быть созданы все потоки того же типа с меньшими идентификаторами. Это обеспечивает согласованность порядка потоков на обеих сторонах.

В состоянии Recv конечная точка принимает кадры STREAM и STREAM_DATA_BLOCKED. Входящие данные буферизуются и могут быть собраны в корректном порядке для доставки приложению. По мере чтения данных приложением и освобождения буферного пространства конечная точка передаёт кадры MAX_STREAM_DATA, позволяющие партнёру продолжить передачу данных.

При получении кадра STREAM с флагом FIN становится известным окончательный размер потока (параграф 4.5) и принимающая часть потока переходит в состояние Size Known. В этос состоянии уже не нужно передавать кадры MAX_STREAM_DATA и принимаются лишь повторы данных потока.

После получения всех данных потока приёмная сторона переходит в состояние Data Recvd. Это может быть результатом получения того же кадра STREAM, который вызвал переход в статус Size Known. После приёма всех данных кадры STREAM и STREAM_DATA_BLOCKED для потока могут отбрасываться.

Состояние Data Recvd сохраняется, пока данные потока не будут доставлены приложению, после чего поток переходит в состояние Data Read, которое является завершающим.

Получение кадра RESET_STREAM в состоянии Recv или Size Known переводит поток в статус Reset Recvd, что может приводить к прерыванию доставки данных из потока приложению. При получении RESET_STREAM все данные потока могут быть уже приняты (состояние Data Recvd). Возможно также прибытие остающихся данных потока после получения кадра RESET_STREAM (состояние Reset Recvd). Реализация может обрабатывать это по своему усмотрению.

Отправки RESET_STREAM означает, что конечная точка не может гарантировать доставку данных потока, однако не требуется отказа от доставки данных потока при получении RESET_STREAM. Реализация может прервать доставку данных потока, отбрасывая не прочитанные данные и сигнализируя о получении RESET_STREAM. Сигнал RESET_STREAM может быть подавлен или задержан, если данные потока полностью получены и буферизованы для считывания приложением. При подавлении RESET_STREAM приёмная сторона остаётся в состоянии Data Recvd.

После получения приложением сигнала о сбросе потока приёмная сторона переходит в состояние Reset Read, которое является завершающим.

3.3. Разрешённые типы кадров

Отправитель потока передаёт лишь три типа кадров, влияющих на состояние потока у отправителя или получателя: STREAM (параграф 19.8), STREAM_DATA_BLOCKED (параграф 19.13), RESET_STREAM (параграф 19.4).

Отправителю недопустимо передавать такие кадры из завершающего состояния (Data Recvd или Reset Recvd), а также недопустимо передавать кадры STREAM или STREAM_DATA_BLOCKED для потока в состоянии Reset Sent или завершающем состоянии, т. е. после отправки кадра RESET_STREAM. Получатель может принять любой из этих трёх кадров в любом состоянии, поскольку пакеты с ними могут быть задержаны.

Получатель потока передаёт кадры MAX_STREAM_DATA (параграф 19.10) и STOP_SENDING (параграф 19.5). Кадры MAX_STREAM_DATA получатель передаёт лишь в состоянии Recv. Получатель может передать кадр STOP_SENDING из любого состояния, в котором он не получил кадр RESET_STREAM (т. е. состояния, отличные от Reset Recvd и Reset Read). Однако нет большого смысла передавать STOP_SENDING из состояния Data Recvd. Поскольку все данные потока уже получены. Отправитель может получить любой из этих кадров в любом состоянии в результате задержки пакетов.

3.4. Состояния двухстороннего потока

Двухсторонний поток состоит из передающей и принимающей части. Реализация может представлять состояния двухстороннего потока как композицию состояний передающего и принимающего потока. Простейшая модель представляет поток как «открытый», когда любая из сторон находится в незавершающем состоянии, а «закрытым» считается поток, обе стороны которого находятся в завершающем состоянии.

В таблице 2 представлено более сложное сопоставление состояний двухстороннего потока, которые примерно соответствуют состояниям потока в HTTP/2 [HTTP2]. Это показывает, что несколько состояний передающей или приёмной стороны потока отображаются на одно композитное состояние. Отметим, что это лишь один из вариантов такого сопоставления и для него требуется подтверждение доставки до перехода в состояние closed или half-closed.

Таблица 2. Возможное отображение состояний потока на HTTP/2.

Передающая сторона

Приёмная сторона

Композитное состояние

No Stream / Ready

No Stream / Recv4

idle

Ready / Send / Data Sent

Recv / Size Known

open

Ready / Send / Data Sent

Data Recvd / Data Read

half-closed (удалённое)

Ready / Send / Data Sent

Reset Recvd / Reset Read

half-closed (удалённое)

Data Recvd

Recv / Size Known

half-closed (локальное)

Reset Sent / Reset Recvd

Recv / Size Known

half-closed (локальное)

Reset Sent / Reset Recvd

Data Recvd / Data Read

closed

Reset Sent / Reset Recvd

Reset Recvd / Reset Read

closed

Data Recvd

Data Recvd / Data Read

closed

Data Recvd

Reset Recvd / Reset Read

closed

3.5. Запрошенная смена состояния

Если приложение больше не заинтересовано в данных из потока, оно может прервать поток и указать код ошибки.

Если приложение находится в состоянии Recv или Size Known, транспорту следует указать это отправкой кадра STOP_SENDING для запроса закрытия потока в обратном направлении. Обычно этого указывает, что принимающее приложение больше не читает полученные в потоке данные, но не гарантирует игнорирование входящих данных.

Кадры STREAM, полученные после отправки STOP_SENDING, по-прежнему учитываются для соединения и управления потоком данных, хотя они могут быть отброшены при получении.

Кадр STOP_SENDING запрашивает у приёмной конечной точки отправку кадра RESET_STREAM. Получившая STOP_SENDING конечная точка должна передать кадр RESET_STREAM, если поток находится в состоянии Ready или Send. Если поток находится в состоянии Data Sent, конечная точка может отложить передачу кадра RESET_STREAM до подтверждения пакетов с оставшимися данными или признания их потерянными. Если оставшиеся данные сочтены потерянными, конечной точке следует передать кадр RESET_STREAM вместо отправки данных.

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

STOP_SENDING следует передавать лишь для потока, который не был сброшен партнёром и наиболее полезен этот кадр в состоянии Recv или Size Known.

Предполагается, что конечная точка передаст другой кадр STOP_SENDING при потере пакета с предыдущим STOP_SENDING. Однако после приёма для потока всех данных или получения кадра (т. е. для потока с состоянием, отличным от Recv и Size Known) отправка STOP_SENDING не требуется.

Конечная точка, желающая разорвать оба направления двухстороннего потока, может прервать одно направление отправкой кадра RESET_STREAM и ускорить завершение другого направления передачей STOP_SENDING.

4. Управление потоком

Получателям нужно ограничивать объем данных, которые они должны буферизовать для предотвращения перегрузки со стороны быстрого отправителя или потребления излишней памяти в результате действий злоумышленника. Чтобы получатель мог ограничить для соединения расход памяти, в потоках применяется управление потоком данных на уровне отдельного потока и соединения в целом. Получатель QUIC контролирует максимальный объем данных, которые может передать отправитель в потоке или всех потоках соединения, как указано в параграфах 4.1 и4.2.

Для ограничения числа одновременных потоков конечная точка QUIC может задать максимальное число потоков, которые может инициировать партнёр, как описано в параграфе 4.6.

Для данных, передаваемых в кадрах CRYPTO, не применяется такое же управление потоком данных, как для данных потока. QUIC полагается на реализацию криптографического протокола для предотвращения избыточной буферизации данных (см. [QUIC-TLS]). Для предотвращения избыточной буферизации на разных уровнях реализациям QUIC следует поддерживать интерфейс с реализацией криптографического протокола для обмена данными о буферизации.

4.1. Управление потоком данных

QUIC реализует схему управления потоками данных на основе ограничений, где получатель анонсирует предельное число байтов, которые он готов принять в данном потоке или соединении в целом. Это обеспечивает два уровня управления потоками данных в QUIC.

  • Управление на уровне потока препятствует занятие одним потоком всего приёмного буфера соединения путём ограничения объёма данных в каждом потоке.

  • Управление на уровне соединения не позволяет отправителю выйти за пределы буферной ёмкости получателя путём ограничения числа байтов, которые могут быть переданы в кадрах STREAM всех потоков.

Отправителям недопустимо передавать данные сверх заданного предела.

Получатель устанавливает начальные пределы для всех потоков через транспортные параметры в процессе согласования (параграф 7.4). Далее получатель передаёт отправителю кадры MAX_STREAM_DATA (параграф 19.10) или MAX_DATA (параграф 19.9) для анонсирования более высоких ограничений. Получатель может указать более высокий предел для потока, передавая кадр MAX_STREAM_DATA с соответствующим идентификатором потока. Кадр MAX_STREAM_DATA указывает максимальное абсолютное смещение в потоке. Получатель может определить смещение для контроля потока данных на основе текущего смещения воспринятых в потоке данных.

Получатель может установить более высокий предел для соединения, передав кадр MAX_DATA с максимальной суммой абсолютных смещений байтов во всех потоках. Получатель поддерживает совокупную сумму байтов, принятых во всех потоках, которая кружит для контроля ограничений, анонсированных для соединения или потоков. Получатель может определить максимальное значение предела данных на основе суммы данных, воспринятых всеми потоками.

После анонсирования получателем предельного значения для соединения или потока указание меньшего предела не является ошибкой, но не будет оказывать влияния.

Получатель должен закрыть соединение с ошибкой FLOW_CONTROL_ERROR, если отправитель нарушает заданные для соединения или потока ограничения (см. раздел 11. Обработка ошибок).

Отправитель должен игнорировать кадры MAX_STREAM_DATA или MAX_DATA, которые не увеличивают пределы ограничения потока данных.

Если отправитель передал заданный ограничением объем данных, он не сможет больше отправлять данные и считается заблокированным. Отправителю следует передать кадр STREAM_DATA_BLOCKED или DATA_BLOCKED для указания получателю, что имеются дополнительные данные для передачи, но отправитель заблокирован контролем потока данных. Если отправитель заблокирован на время, превышающее тайм-аут бездействия (параграф 10.1), получатель может закрыть соединение даже при наличии у отправителя дополнительных данных для передачи. Чтобы предотвратить закрытие соединения, отправителю, для которого задано управление потоком данных, следует периодически отправлять кадры STREAM_DATA_BLOCKED или DATA_BLOCKED, если у него нет находящихся «в полете» пакетов с подтверждениями.

4.2. Расширение пределов управления потоком данных

Реализация решает, когда и какие кредиты на передачу следует анонсировать в кадрах MAX_STREAM_DATA и MAX_DATA, а здесь приведены некоторые соображения на этот счёт. Для предотвращения блокировки отправителя получатель может передать кадр MAX_STREAM_DATA или MAX_DATA неоднократно в течение интервала кругового обхода или передать кадр заранее с учётом возможной потери кадра и восстановления.

Кадры управления вносят вклад в издержки соединения, поэтому частая отправка MAX_STREAM_DATA и MAX_DATA с небольшими изменениями нежелательна. С другой стороны, если обновления передавать реже, требуется существенное повышение пределов для предотвращения блокировки отправителя, а это ведёт к большему расходу ресурсов у получателя. Нужен компромисс между выделением ресурсов и издержками.

Получатель может использовать механизм автоматической настройки для выбора частоты анонсов и размера добавочного кредита на основе оценки времени кругового обхода и скорости, с которой принимающее приложение потребляет данные, подобно обычным реализациям TCP. В качестве оптимизации конечная точка может передавать кадры, относящиеся к управлению потоком данных, только при отправке других кадров, что позволит избавиться от передачи лишних пакетов.

Блокированному отправителю не требуется передавать кадры STREAM_DATA_BLOCKED или DATA_BLOCKED. Поэтому получателю недопустимо ждать получения STREAM_DATA_BLOCKED или DATA_BLOCKED перед отправкой MAX_STREAM_DATA или MAX_DATA. Такое ожидание может приводить к блокировке отправителя для оставшейся части соединения. Даже при передаче отправителем таких кадров ожидание может привести к блокировке отправителя по меньшей мере на интервал кругового обхода.

При получении отправителем кредита после блокировки он сможет передать в ответ больший объем данных, что может привести к кратковременной перегрузке (см. параграф 7.7 в [QUIC-RECOVERY], где рассматриваются способы предотвращения такой перегрузки).

4.3. Производительность и управление потоком данных

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

Потери пакетов вызывают пропуски в приёмном буфере, препятствующие восприятию данных приложением и освобождению пространства в приёмном буфере.

Своевременная передача обновлений пределов управления потоком данных может повысить производительность. Отправка пакетов лишь для управления потоком данных может увеличить загрузку сети и негативно повлиять на производительность. Передача обновлений контроля потока данных вместе с другими кадрами, такими как ACK, снижает расходы на обновления.

4.4. Обработка отмены потока

Конечные точки должны согласовывать объем кредита управления потоком данных, потребляемого каждым потоком, чтобы учесть все байты для контроля потока данных на уровне соединения.

При получении кадра RESET_STREAM конечная точка прервёт состояние для соответствующего потока и будет игнорировать последующие данные в этом потоке. RESET_STREAM жёстко прерывает одно направление потока и в двухсторонних потоках не влияет на другое направление. Обе конечных точки должны поддерживать состояние контроля потока данных для непрерванного направления, пока это направление не перейдёт в завершающий статус.

4.5. Окончательный размер потока

Окончательный размер – это кредит управления потоком данных, потреблённый потоком. В предположении однократной передачи каждого байта этот размер совпадает с числом переданных байтов. В более общем смысле – это значение на 1 больше максимального смещения байта, переданного в поток, или 0, если данные в поток не передавались.

Отправитель всегда гарантированно передаёт окончательный размер потока получателю, независимо от способа завершения потока. Окончательный размер определяет сумма полей Offset и Length в кадре STREAM с флагом FIN, но эти поля могут быть неявными. Кроме того, это значение передаётся в поле Final Size кадра RESET_STREAM. Это гарантирует, что обе конечные точки согласны с размером кредита управления потоком данных, использованного отправителем в этом потоке.

Конечная точка узнает окончательный размер потока, когда принимающая часть потока переходит в состояние Size Known или Reset Recvd (раздел 3). Получатель должен использовать окончательный размер потока для учёта всех байтов, переданных в поток, на контроллере управления потоком данных для соединения в целом.

Конечной точке недопустимо передавать в поток данные сверх окончательного размера5.

После того, как окончательный размер стал известен, его уже нельзя изменить. При получении кадра RESET_STREAM или STREAM, указывающего изменение окончательного размера для потока конечной точке следует вернуть ошибку типа FINAL_SIZE_ERROR (см. 11. Обработка ошибок). Получателю следует трактовать приём данных сверх окончательного размера как ошибку FINAL_SIZE_ERROR даже в случае уже закрытого потока. Возврат этой ошибки не является обязательным, поскольку введение такого требования означало бы необходимость поддержки конечной точкой окончательного размера для закрытых соединений, что может вести к избыточному числу состояний.

4.6. Контроль одновременной работы

Конечная точка ограничивает суммарное число входящих потоков, которые партнёр может создать, разрешая создавать лишь потоки, чей идентификатор меньше max_streams * 4 + first_stream_id_of_type (см. таблицу 1). Начальные ограничения задаются в транспортных параметрах (параграф 18.2. Определения транспортных параметров), а последующие анонсируются в кадрах MAX_STREAMS (параграф 19.11. Кадр MAX_STREAMS). Для односторонних и двухсторонних потоков применяются разные ограничения.

Получение параметра max_streams или кадра MAX_STREAMS со значением больше 260 указывает идентификатор потока, который не может быть выражен целым число переменного размера (16. Представление целочисленных полей переменного размера). Соединение должно закрываться немедленно с ошибкой TRANSPORT_PARAMETER_ERROR в случае транспортного параметра и FRAME_ENCODING_ERROR для значения в кадре (10.2. Незамедлительное закрытие).

Конечным точкам недопустимо выходить за установленный партнёром предел. Получение кадра с идентификатором потока сверх заданного предела конечная точка должна считать ошибкой соединения STREAM_LIMIT_ERROR (11. Обработка ошибок).

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

Как и для управления потоком данных, этот документ оставляет за реализацией выбор времени и способа анонсирования ограничений партнёру с помощью MAX_STREAMS. Реализации могут повышать предел по мере закрытия потоков для сохранения числа доступных партнёру потоков более или менее постоянным.

Конечной точке, не способной создать новый поток по причине ограничения партнёра, следует передать кадр STREAMS_BLOCKED (параграф 19.14). такая сигнализация может быть полезна для отладки. Конечной точке недопустимо ждать получения этого сигнала перед анонсированием дополнительного кредита, поскольку такое ожидание означает блокирование партнёра по меньшей мере на период кругового обхода и может даже приводить к бессрочному блокирования, если партнёр не передаёт кадров STREAMS_BLOCKED.

5. Соединения

Соединение QUIC является общим состоянием клиента и сервера. Каждое соединение начинается с фазы согласования (handshake), когда две конечных точки организуют общий секрет, используя протокол криптографического согласования [QUIC-TLS], и согласуют протокол приложения. Согласование (раздел 7) подтверждает, что точки готовы взаимодействовать (параграф 8.1) и задали параметры соединения (параграф 7.4).

Использование прикладного протокола в фазе согласования несколько ограничено. 0-RTT позволяет клиенту передать данные приложения до получения отклика от сервера, однако при этом не обеспечивается защиты от атак с повторным использованием (replay), как указано в параграфе 9.2 [QUIC-TLS]. Сервер также может передать клиенту данные приложения до получения финальных сообщения криптографического согласования, которое позволяет ему подтвердить подлинность и живучесть клиента. Эти возможности позволяют прикладному протоколу предложить возможность согласовать некоторые криптографические гарантии для снижения задержки.

Использование идентификаторов соединений (параграф 5.1) позволяет менять путь соединения через сеть в случае прямого перемещения конечной точки или вызванных промежуточными устройствами изменений. В разделе 9 рассматривается смягчение проблем безопасности и приватности при перемещении соединений.

Для соединений, которые стали ненужными или нежелательными, имеется несколько способов разрыва, описанных в разделе 10.

5.1. Идентификаторы соединения

Каждое соединение обладает набором идентификаторов, которые могут указывать соединение. Идентификаторы выбираются конечными точками независимо.

Основным назначением идентификаторов соединений является предотвращение отправки пакетов соединения QUIC не той конечной точке в случае смены адресации протоколов нижележащих уровней (UDP, IP). Каждая конечная точка выбирает идентификаторы соединения в зависимости от реализации (и, возможно, развёртывания) и эти идентификаторы позволяют пакетам соединения попадать в конечную точку и распознаваться при получении. Множество идентификаторов соединения позволяют конечной точке передавать пакеты так, чтобы наблюдатель в пути не мог связать пакеты с конечной точкой без взаимодействия с нею (9.5. Влияние переноса соединения на приватность). В идентификаторы соединений недопустимо включать какие-либо сведения, которые позволят стороннему наблюдателю (не взаимодействующему с эмитентом идентификатора) сопоставить их с другими идентификаторами того же соединения. Например, недопустимо использовать один идентификатор несколько раз в данном соединении.

Пакеты с длинными заголовками включают поля Source Connection ID и Destination Connection ID, которые служат для установки идентификаторов в новых соединениях (7.2. Согласование идентификаторов соединений). В пакеты с коротким заголовком (параграф 17.3) включается лишь Destination Connection ID без явного указания размера (предполагается, что конечные точки знает его). Конечные точки с балансировщиками нагрузки, распределяющими пакеты по идентификаторам соединений, могут согласовать балансировку по фиксированному размеру идентификаторов или выбрать схему их кодирования. Фиксированная часть может представлять явный размер, что позволяет идентификатору иметь переменный размер с возможностью его использования для балансировки нагрузки.

Пакет согласования версии (Version Negotiation, параграф 17.2.1) возвращает идентификаторы соединений, выбранные клиентом, что обеспечивает корректную маршрутизацию в направлении клиента и указывает, что пакет является откликом на переданный клиентом пакет.

Можно использовать пустой (размер 0) идентификатор соединения, если тот не нужен для маршрутизации корректной конечной точке. Однако мультиплексирование соединений с одним локальным адресом IP и номером порта при пустом идентификаторе соединения столкнётся с отказом при переносе соединения, перестройке NAT или повторном использовании клиентского порта. Конечной точке недопустимо применять один адрес IP и порт для нескольких одновременных соединений с пустыми идентификаторами, пока нет уверенности в том, что идентификаторы не нужны.

При использовании конечной точкой пустого идентификатора соединения она должна гарантировать, что у партнёра имеется идентификатор соединения для выбора пакетов, передаваемых этой конечной точке. Эти идентификаторы передаются конечной точкой в кадрах NEW_CONNECTION_ID (параграф 19.15).

5.1.1. Выдача идентификаторов соединения

С каждым идентификатором соединения связан порядковый номер помогающий определить принадлежность кадров NEW_CONNECTION_ID или RETIRE_CONNECTION_ID к одному идентификатору. Начальный идентификатор соединения, выданный конечной точкой, передаётся в поле Source Connection ID пакета с длинным заголовком (параграф 17.2) в процессе согласования. Этот идентификатор имеет порядковый номер 0. Если передаётся параметр транспорта preferred_address порядковым номером представленного идентификатора соединения будет 1.

Дополнительные идентификаторы соединения передаются в кадрах NEW_CONNECTION_ID (параграф 19.15) и для каждого нового идентификатора порядковый номер должен увеличиваться на 1. Идентификатор соединения, который клиент выбрал для первого переданного им поля Destination Connection ID, и любой идентификатор соединения из пакета Retry не имеет порядкового номера.

Конечная точка, выдавшая идентификатор соединения, должна воспринимать пакеты с этим идентификатором в течение срока действия соединения или до аннулирования идентификатора кадром RETIRE_CONNECTION_ID (параграф 19.16). Выданные и не аннулированные идентификаторы соединения считаются активными и пригодны для использования в любых пакетах соединения в любой момент. Активным считается и идентификатор соединения выданный сервером в транспортном параметре preferred_address.

Конечной точке следует обеспечивать для партнёра достаточное число доступных и не использованных идентификаторов соединения. Конечные точки анонсируют число поддерживаемых активных идентификаторов соединения через транспортный параметр active_connection_id_limit. Конечной точке недопустимо передавать идентификаторы соединения сверх заданного партнёром предела. Конечная точка может передавать идентификаторы, которые временно выходят за установленный партнёром предел, если кадр NEW_CONNECTION_ID также требует изъятия излишка, путём включения достаточно большого значения в поле Retire Prior To. Кадр NEW_CONNECTION_ID может вызвать добавление конечной точкой активных идентификаторов соединения и исключение других на основе значения поля Retire Prior To. После обработки кадра NEW_CONNECTION_ID с добавлением и удалением активных идентификаторов конечная точка должна закрыть соединение с ошибкой CONNECTION_ID_LIMIT_ERROR, если число активных идентификаторов превышает значение транспортного параметра active_connection_id_limit.

Конечной точке следует предоставлять новый идентификатор соединения, когда партнёр отзывает идентификатор. Если конечная точка предоставляет меньше заданного партнёром числа (active_connection_id_limit) активных идентификаторов, она может добавить новый идентификатор при получении пакета с не использованным ранее идентификатором соединения. Конечная точка может ограничить общее число выдаваемых идентификаторов соединения для предотвращения риска выхода за пределы (см. 10.3.2. Расчёт маркера Stateless Reset). Конечная точка может также ограничивать выпуск идентификаторов соединения для снижения числа поддерживаемых состояний на уровне пути, таких как статус проверки пути, поскольку партнёр может взаимодействовать с ней по числу путей, соответствующему количеству выданных идентификаторов соединения.

Конечной точке, которая инициирует перенос соединения и требует непустых идентификаторов, следует гарантировать, что пул доступных партнёру идентификаторов позволяет тому использовать при переходе новый идентификатор, поскольку партнёр не сможет ответить в противном случае.

Конечная точка, выбравшая пустой идентификатор соединения в процессе согласования, не может выбрать новый идентификатор. Поле Destination Connection ID с размером 0 используется во всех пакетах для этой точки по любому пути через сеть.

5.1.2. Потребление и отзыв идентификаторов соединения

Конечная точка может сменить используемый для партнёра идентификатор соединения на доступный в любой момент работы соединения. Конечная точка потребляет идентификатор соединения в ответ на перемещение партнёра (см. 9.5. Влияние переноса соединения на приватность).

Конечная точка поддерживает набор полученных от партнёра идентификаторов соединения, любой из которых она может применять для отправки пакетов. Когда конечная точка желает исключить идентификатор соединения из использования, она передаёт партнёру кадр RETIRE_CONNECTION_ID. Отправка кадра RETIRE_CONNECTION_ID показывает, что идентификатор соединения не будет использоваться снова и запрашивает у партнёра его замену в кадре NEW_CONNECTION_ID.

Как отмечено в параграфе 9.5, конечная точка ограничивает использование идентификатора соединения пакетами, передаваемыми с одного локального адреса на один адрес получателя. Конечным точкам следует отзывать идентификаторы соединений, когда они перестают использовать локальный или удалённый адрес, для которого применялся идентификатор соединения.

В некоторый случаях конечное точке может потребоваться прекратить восприятие ранее выданных идентификаторов соединения. Она может заставить своего партнёра отозвать идентификатор соединения путём отправки тому кадра NEW_CONNECTION_ID с увеличенным значением поля Retire Prior To. Конечное точке следует продолжать восприятие ранее выданных идентификаторов соединения, пока они не отозваны партнёром. Если конечная точка больше не может обрабатывать выданные идентификаторы соединения, она может закрыть соединение.

При получении поля Retire Prior To партнёр должен прекратить использование соответствующих идентификаторов соединения и отозвать их в кадрах RETIRE_CONNECTION_ID до добавления новых идентификаторов в число активных идентификаторов соединения. Такой порядок позволяет конечной точке заменить все активные идентификаторы, не оставляя партнёра без доступных идентификаторов и не превышая установленного им предела (параметр транспорта active_connection_id_limit, см. 18.2. Определения транспортных параметров). Неспособность прекратить использование идентификаторов соединения по запросу может приводить к отказу соединения, поскольку выдавшая идентификаторы конечная точка может быть не способна продолжать использование идентификаторов с активным соединением.

Конечной точке следует ограничивать число локально отозванных идентификаторов соединения, для которых кадры RETIRE_CONNECTION_ID ещё не подтверждены. Конечное точке следует разрешать передачу и отслеживание числа кадров RETIRE_CONNECTION_ID, по меньшей мере вдвое превышающего значение транспортного параметра active_connection_id_limit. Конечной точке недопустимо забывать идентификатор соединения без его отзыва, хотя она может считать наличие требующих отзыва идентификаторов соединения сверх этого предела ошибкой соединения типа CONNECTION_ID_LIMIT_ERROR.

Конечной точке не следует обновлять поле Retire Prior To до приёма кадров RETIRE_CONNECTION_ID, отзывающих идентификаторы сообщений, указанных в предыдущем Retire Prior To.

5.2. Сопоставление пакетов с соединением

Входящие пакеты классифицируются при получении. Пакеты могут быть связаны с одним из имеющихся соединений или (для серверов) создавать новое соединение. Конечные точки пытаются связать пакет с имеющимся соединением. Если в пакете содержится непустое поле Destination Connection ID, соответствующее имеющемуся соединению, QUIC выполняет соответствующую обработку пакета. Как указано в параграфе 5.1, с соединением может быть связано множество идентификаторов. Если поле Destination Connection ID имеет нулевой размер и адресная информация в пакете соответствует адресной информации, используемой конечной точкой для идентификации соединения с пустым идентификатором, QUIC обрабатывает пакет как часть соединения. Конечная точка может использовать для идентификации лишь IP-адрес и порт получателя или адреса отправителя и получателя, хотя это делает соединения более слабыми, как отмечено в параграфе 5.1.

Конечная точка может передать Stateless Reset (параграф 10.3) для любого пакета, который она не может связать с имеющимся соединением. Это позволяет партнёру быстрее обнаруживать непригодность соединения.

Соответствующие имеющемуся соединению пакеты отбрасываются, если они не согласуются с состоянием соединения. Например, отбрасываются пакеты, указывающие иную версию протокола, или при неудачном снятии защиты после того, как ожидаемые ключи стали доступными.

Недействительные пакеты без строгой защиты целостности, такие как Initial, Retry, Version Negotiation, можно отбрасывать. Конечная точка должна генерировать ошибку соединения, если обработка содержимого таких пакетов была выполнена до обнаружения ошибки, или полностью отменить изменения, внесённые при такой обработке.

5.2.1. Обработка пакетов клиентом

Переданные клиентам действительные пакеты всегда включают поле Destination Connection ID, соответствующее выбранному клиентом значению. Клиенты, выбравшие получение пустого идентификатора соединения, могут применять для идентификации соединения локальный адрес и порт. Пакеты, не соответствующие имеющемуся соединению (Destination Connection ID или локальный адрес IP и порт при пустом идентификаторе), отбрасываются.

В результате потери или нарушения порядка пакетов клиент может получить пакеты, зашифрованные с ключом, которые ещё не рассчитан. Клиент может отбросить такие пакеты или буферизовать их в ожидании последующих пакетов, которые позволят рассчитать ключ.

При получении клиентом пакета, использующего отличную от исходно выбранной версию, он должен отбросить пакет.

5.2.2. Обработка пакетов сервером

Если сервер получает пакет, указывающий неподдерживаемую версию и размер пакета достаточно велик, чтобы инициировать новое соединение для любой поддерживаемой версии, ему следует передать пакет Version Negotiation, как указано в параграфе 6.1. Сервер может ограничить число пакетов, на которые он отвечает пакетом Version Negotiation. Серверы должны отбрасывать мелкие пакеты, указывающие неподдерживаемую версию.

Первые пакет для неподдерживаемой версии может использовать иную семантику и кодирование для зависимых от версии полей. В частности, разные версии могут применять свои ключи защиты пакетов. Не поддерживающий конкретную версию сервер вряд ли сможет расшифровать данные пакета или корректно интерпретировать результат. Серверам следует отвечать пакетом Version Negotiation при условии достаточно большого размера дейтаграммы.

Пакеты с поддерживаемой версией или без поля Version сопоставляются с соединением по идентификатору соединения или локальным адресом и портом (при пустом идентификаторе соединения). Эти пакеты обрабатываются с использованием выбранного соединения, в иных случаях сервер выполняет описанные ниже действия.

Для пакетов Initial, полностью соответствующих данной спецификации, сервер выполняет согласование (раздел 7) с фиксацией сервером выбранной клиентом версии.

Если сервер отвергает новое соединение, ему следует передать пакет Initial с кадром CONNECTION_CLOSE, содержащим код ошибки CONNECTION_REFUSED.

Пакеты 0-RTT сервер может буферизовать в ограниченном количестве в ожидании последующего получения пакета Initial. Клиенты не могут передавать пакеты Handshake до получения отклика от сервера, поэтому серверу следует игнорировать такие пакеты.

В остальных случаях сервер должен отбрасывать входящие пакеты.

5.2.3. Простые балансировщики нагрузки

Развёртывание сервера может использовать распределение нагрузки между несколькими серверами, используя лишь IP-адреса и порты отправителей и получателей. Смена в пакетах адреса или порта у клиента может приводить к пересылке пакета не тому серверу. В таких системах может применяться один из указанных ниже способов обеспечения непрерывности соединения при смене адреса клиента.

  • Сервер может применять отдельный (out-of-band) механизм для пересылки пакетов корректному серверу на основе идентификатора соединения.

  • Если серверы могут использовать выделенные адреса IP или порты, отличающиеся от тех, по которым исходно подключался клиент, они могут использовать транспортный параметр preferred_address для запроса у клиента переноса соединения на выделенный адрес.

Серверу, который не реализует решения по поддержке непрерывности соединения при смене адреса клиента, следует указывать, что перенос не поддерживается с помощью транспортного параметра disable_active_migration. Этот параметр не запрещает перемещение клиента после действий клиента в соответствии с параметром preferred_address.

Серверы, использующие эту простую форму распределения нагрузки, должны избегать предсказания сброса без учёта состояния (21.11. Предсказание Stateless Reset).

5.3. Операции на соединениях

Этот документ не задаёт API для QUIC, определяя лишь набор функций для соединений QUIC, которые прикладные протоколы могут использовать. Протоколы приложений могут считать, что реализация QUIC обеспечивает интерфейс, включающий описанные в этом параграфе операции. Реализация, рассчитанная на определённый прикладной протокол, может предоставлять лишь нужную данному протоколу часть описанных операций.

При реализации роли клиента протокол приложения может:

  • создавать соединения, начинающиеся с обмена, описанного в разделе 7;

  • включать Early Data при доступности данных;

  • получать информацию о восприятии или отклонении сервером Early Data.

При реализации роли сервера протокол приложения может:

  • прослушивать входящие соединения, готовясь к обмену, описанному в разделе 7;

  • при поддержке Early Data встраивать контролируемые приложением данные в «квитанцию» (ticket) возобновления TLS, передаваемую клиенту;

  • при поддержке Early Data извлекать контролируемые приложением данные из клиентских «квитанций» восстановления и воспринимать или отвергать Early Data на основе этих сведений.

В любой из роле протокол приложения может:

  • настраивать минимальные значения для исходного числа разрешённых потоков каждого типа, передаваемые в транспортных параметрах (параграф 7.4);

  • управлять выделением ресурсов для приёмных буферов путём установки ограничений контроля потока данных на уровне соединения и потоков;

  • определять успешное завершение согласования (handshake) или его продолжение;

  • предохранять соединение от закрытия «втихую» путём генерации кадров PING (параграф 19.2) или запроса у транспортного уровня передачи дополнительных кадров до тайм-аута бездействия (параграф 10.1);

  • незамедлительно закрывать соединение (параграф 10.2).

6. Согласование версии

Согласование версии позволяет серверу узнать, поддерживает ли он используемую клиентом версию. Отправитель передаёт пакет Version Negotiation в ответ на каждый пакет, который может инициировать новое соединение (см. 5.2. Сопоставление пакетов с соединением).

Размер первого пакета, переданного клиентом, определяет возможность отправки сервером пакета Version Negotiation. Клиентам, поддерживающим несколько версий QUIC, следует обеспечить для первой передаваемой дейтаграммы UDP размер, являющийся наибольшим из всех минимальных значений размера дейтаграммы в поддерживаемых клиентом версиях, используя при необходимости кадры PADDING (параграф 19.1). Это гарантирует ответ сервера при наличии поддерживаемой обеими сторонами версии. Сервер может не передавать пакет Version Negotiation, если полученная дейтаграмма меньше минимального размера, указанного в другой версии (см. 14. Размер дейтаграмм).

6.1. Передача пакетов согласования версии

Если для сервера не подходит выбранная клиентом версия, он отвечает пакетом Version Negotiation (параграф 17.2.1), включающий список поддерживаемых сервером версий. Конечной точке недопустимо передавать пакет Version Negotiation в ответ на получение пакета Version Negotiation.

Это позволяет серверу обрабатывать пакеты неподдерживаемых версий без сохранения состояния. Поскольку пакет Initial или переданный в ответ пакет Version Negotiation может потеряться, клиент будет передавать новые пакеты, пока не получит ответ или не откажется от попытки соединения.

Сервер может ограничить число передаваемых пакетов Version Negotiation. Например, сервер, способный распознавать пакеты как 0-RTT, может отказаться от передачи пакетов Version Negotiation в ответ на пакеты 0-RTT, ожидая получить пакет Initial.

6.2. Обработка пакетов согласования версии

Пакеты Version Negotiation предназначены для определения в будущем функциональности, которая позволит QUIC согласовывать версию протокола для соединения. Будущие спецификации Standards Track могут изменить поведение реализаций с поддержкой нескольких версий QUIC при получении пакетов Version Negotiation в ответ на попытку организации соединения с использованием данной версии.

Клиент, поддерживающий лишь данную версию QUIC, должен отказаться от текущей попытки соединения при получении сообщения Version Negotiation, за исключением двух указанных ниже случаев. Клиент должен отбрасывать любой пакет Version Negotiation, если он получил и успешно обработал другие пакеты, включая предшествующий пакет Version Negotiation. Клиент должен отбрасывать пакет Version Negotiation, указывающий выбранную клиентом версию QUIC.

Согласование версии оставлено для будущих спецификаций Standards Track. В частности, эти будущие документы обеспечат устойчивость к атакам на понижение версии (21.12. Понижение версии).

6.3. Использование зарезервированных версий

Чтобы клиент мог в будущем использовать новую версию, клиентам нужно корректно обрабатывать неподдерживаемые версии. Некоторые номера версий (0x?a?a?a?a, как указано в разделе 15) зарезервированы для включения в поля, содержащие номер версии.

Конечные точки могут добавлять резервные версии в любое поле, где неизвестная или неподдерживаемая версия игнорируется, для проверки корректности игнорирования значения партнёром. Например, конечная точка может включить резервную версию в пакет Version Negotiation (см. параграф 17.2.1). Конечные точки могут передавать пакеты с резервной версией для проверки корректности отбрасывания пакетов партнёром.

7. Согласование криптографии и транспорта

QUIC использует комбинированное согласование криптографии и транспорта для минимизации задержки при организации соединений. Для криптографического согласования QUIC использует кадр CRYPTO (параграф 19.6). Определённая этим документом версия QUIC указывается идентификатором 0x00000001 и использует TLS, как описано в [QUIC-TLS]. Иная версия QUIC может применять другой протокол криптографического согласования.

QUIC обеспечивает надёжную, упорядоченную доставку данных криптографического согласования с использованием защиты пакетов QUIC для максимально возможного шифрования протокола согласования. Криптографическое согласование должно обеспечивать указанные ниже свойства.

  • Обмен аутентифицированными ключами, в котором:

    • подлинность сервера проверяется всегда;

    • может проверяться подлинность клиента;

    • каждое соединение создаёт разные и не связанные между собой ключи;

    • ключевой материал пригоден для защиты пакетов 0-RTT и 1-RTT.

  • Аутентифицированный обмен значениями транспортных параметров обеих конечных точек и защита конфиденциальности для транспортных параметров сервера (параграф 7.4).

  • Аутентифицированное согласование прикладного протокола (TLS использует для этого ALPN6 [ALPN]).

Кадр CRYPTO можно передать в разных пространствах номеров пакетов (параграф 12.3). Смещения в кадрах CRYPTO, используемые для гарантии упорядоченной доставки данных криптографического согласования, начинаются с 0 в каждом пространстве номеров пакетов.

На рисунке 4 упрощенно показано согласование и обмен пакетами и кадрами в процессе согласования. По возможности разрешается обмен данными приложения в процессе согласования (помечено *). По завершении согласования конечные точки могут свободно обмениваться данными.

Клиент                                               Сервер

Initial (CRYPTO)
0-RTT (*)              ---------->
                                           Initial (CRYPTO)
                                         Handshake (CRYPTO)
                       <---------- 1-RTT (*) Handshake (CRYPTO) 1-RTT (*) ---------->
                       <----------   1-RTT (HANDSHAKE_DONE)

1-RTT                  <=========>                    1-RTT

Рисунок 4. Упрощенное согласование QUIC.


Конечные точки могут использовать переданные при согласовании пакеты для тестирования поддержки ECN7 (см. параграф 13.4). Конечная точка определяет поддержку ECN, контролируя наличие в кадрах ACK, подтверждающих первые пакеты, полей ECN Count, как указано в параграфе 13.4.2.

Конечные точки должны явно согласовывать прикладной протокол, что позволяет избежать ситуаций с разногласиями по поводу используемого протокола.

7.1. Примеры потока согласования

Детали интеграции TLS с QUIC представлены в [QUIC-TLS], но здесь даны некоторые рекомендации. Расширение обмена для проверки адреса клиента описано в параграфе 8.1.2.

По завершении обмена для проверки адреса используется криптографическое согласование для ключей. В криптографическом согласовании применяются пакеты Initial (параграф 17.2.2) и Handshake (параграф 17.2.4).

На рисунке 5 приведён обзор согласования 1-RTT. Каждая строка показывает пакет QUIC с указанным типом и номером. Затем следуют кадры, обычно содержащиеся в этих пакетах. Например, первый пакет имеет тип Initial, номер 0 и содержит кадр CRYPTO с ClientHello.

Можно объединить несколько пакетов QUIC (даже разных типов) в одной дейтаграмме UDP (см. параграф 12.2). В результате согласование может состоять всего из 4 дейтаграмм UDP (зависит от присущих протоколу ограничений, таких как контроль перегрузки и предотвращения усиления). Например, первая отправка сервера содержит пакеты Initial, Handshake и данные 0.5-RTT в пакетах 1-RTT.

Клиент                                                  Сервер

Initial[0]: CRYPTO[CH] ->

                                 Initial[0]: CRYPTO[SH] ACK[0]
                       Handshake[0]: CRYPTO[EE, CERT, CV, FIN]
                                 <- 1-RTT[0]: STREAM[1, "..."] Initial[1]: ACK[0] Handshake[0]: CRYPTO[FIN], ACK[0] 1-RTT[0]: STREAM[0, "..."], ACK[0] ->

                                          Handshake[1]: ACK[0]
         <- 1-RTT[1]: HANDSHAKE_DONE, STREAM[3, "..."], ACK[0]

Рисунок 5. Пример согласования 1-RTT.


На рисунке 6 приведён пример соединения с согласованием 0-RTT и одним пакетом данных 0-RTT. Как указано в параграфе 12.3, сервер подтверждает данные 0-RTT в пакетах 1-RTT, а клиент передаёт пакеты 1-RTT в том же пространстве номеров.

Клиент                                                  Сервер

Initial[0]: CRYPTO[CH]
0-RTT[0]: STREAM[0, "..."] ->

                                 Initial[0]: CRYPTO[SH] ACK[0]
                                  Handshake[0] CRYPTO[EE, FIN]
                          <- 1-RTT[0]: STREAM[1, "..."] ACK[0] Initial[1]: ACK[0] Handshake[0]: CRYPTO[FIN], ACK[0] 1-RTT[1]: STREAM[0, "..."] ACK[0] ->

                                          Handshake[1]: ACK[0]
         <- 1-RTT[1]: HANDSHAKE_DONE, STREAM[3, "..."], ACK[1]

Рисунок 6. Пример согласования 0-RTT.


7.2. Согласование идентификаторов соединений

Идентификатор соединения служит для обеспечения согласованной маршрутизации пакетов, как описано в параграфе 5.1. Длинный заголовок содержит два идентификатора соединений – Destination Connection ID выбирается получателем пакета и служит для обеспечения согласованной маршрутизации, Source Connection ID служит для установки Destination Connection ID, используемого партнёром.

В процессе согласования применяются пакеты с длинным заголовком (параграф 17.2) для организации идентификаторов соединений, используемых обеими конечными точками. Каждая конечная точка использует поле Source Connection ID для указания идентификатора соединения, указываемого в поле Destination Connection ID передаваемых ей пакетов. После обработки первого пакета Initial каждая конечная точка устанавливает поле Destination Connection ID в последующих пакетах в соответствии с полученным значением поля Source Connection ID.

Когда пакет Initial передаётся клиентом, не получавшим ранее от сервера пакета Initial или Retry, клиент указывает в поле Destination Connection ID непредсказуемое значение. Размер поля Destination Connection ID должен быть не менее 8 байтов. Пока не будет получен пакет от сервера, клиент должен использовать одно значение Destination Connection ID во всех пакетах соединения.

Поле Destination Connection ID из первого пакета от клиента служит для определения ключей защиты пакетов Initial. Эти ключи меняются после приёма пакета Retry (см. параграф 5.2 в [QUIC-TLS]).

Клиент указывает в поле Source Connection ID выбранное им значение и указывает его размер в поле Source Connection ID Length.

Пакеты 0-RTT в первой отправке используют те же значения Destination Connection ID и Source Connection ID, что и в первом пакете Initial от клиента.

При получении от сервера пакета Initial или Retry клиент использует представленное сервером поле Source Connection ID в качестве значения Destination Connection ID для последующих пакетов, включая любые пакеты 0-RTT. Это значит, что клиенту может потребоваться изменить идентификатор соединения в поле Destination Connection ID дважды в процессе организации соединения – одни раз в ответ на пакет Retry и другой в ответ на пакет Initial от сервера. После получения клиентом действительного пакета Initial от сервера он должен отбрасывать в этом соединении все последующие пакеты с другим Source Connection ID.

Клиент должен менять Destination Connection ID в передаваемых пакетах лишь в ответ на первый принятый пакет Initial или Retry. Сервер должен установить Destination Connection ID для отправляемых пакетов на основе первого полученного пакета Initial. Последующие изменения Destination Connection ID разрешены лишь на значения из кадров NEW_CONNECTION_ID. Если последующие пакеты Initial включают другое значение Source Connection ID, они должны отбрасываться. Это позволяет избежать непредсказуемых результатов при обработке нескольких пакетов Initial с разными Source Connection ID без сохранения состояния.

Поле Destination Connection ID, передаваемое конечной точкой, может меняться в течение срока действия соединения, особенно при переносе соединения (раздел 9 и параграф 5.1.1).

7.3. Аутентификация идентификаторов соединений

Выбор каждой конечной точкой идентификатора соединения в процессе согласования аутентифицируется путём включения всех значений в транспортные параметры (см. параграф 7.4). Это гарантирует для всех идентификаторов соединений, используемых при согласовании, проверку подлинности в процессе криптографического согласования.

Каждая конечная точка включает значение Source Connection ID из первого переданного пакета Initial в транспортный параметр initial_source_connection_id (см. параграф 18.2). Сервер включает поле Destination Connection ID из первого полученного от клиента пакета Initial в транспортный параметр original_destination_connection_id. Если сервер передаёт пакет Retry это относится к первому пакету Initial, полученному до отправки Retry. Если сервер передаёт пакет Retry, он также включает поле Source Connection ID из пакета Retry в транспортный параметр retry_source_connection_id.

Предоставленные партнёром значения этих транспортных параметров должны совпадать со значениями, используемыми конечной точкой в полях Destination Connection ID и Source Connection ID передаваемых (и принимаемых для сервера) пакетов Initial. Конечные точки должны проверить соответствие полученных транспортных параметров полученным идентификаторам соединений. Включение идентификаторов соединений в транспортные параметры и их проверка предотвращают влияние атакующего на выбор идентификатора соединения для успешного подключения путём вставки пакетов с выбранным атакующим идентификатором соединения в процессе согласования.

Конечная точка должна считать отсутствие транспортного параметра initial_source_connection_id или транспортного параметра original_destination_connection_id от сервера как ошибку соединения TRANSPORT_PARAMETER_ERROR.

Конечная точка должна считать ошибкой TRANSPORT_PARAMETER_ERROR или PROTOCOL_VIOLATION:

  • отсутствие транспортного параметра retry_source_connection_id от сервера после получения пакета Retry;

  • присутствие транспортного параметра retry_source_connection_id, когда пакет Retry не был получен;

  • несоответствие значений. полученных от партнёра в этих транспортных параметрах, и значений, переданных в полях Destination Connection ID или Source Connection ID пакетов Initial.

При выборе пустого идентификатора соединения соответствующие транспортные параметры имеют размер 0.

На рисунке 7 показаны идентификаторы соединения (DCID=Destination Connection ID, SCID=Source Connection ID), используемые для полного согласования (handshake). Указан обмен пакетами Initial, а также последующий обмен пакетами 1-RTT, включающий идентификаторы соединения, организованные при согласовании.

Клиент                                                  Сервер

Initial: DCID=S1, SCID=C1 ->
                                  <- Initial: DCID=C1, SCID=S3 ... 1-RTT: DCID=S3 ->
                                             <- 1-RTT: DCID=C1

Рисунок 7. Использование идентификаторов соединения при согласовании.


На рисунке 8 показано похожее согласование с включением пакета Retry.

Клиент                                                  Сервер

Initial: DCID=S1, SCID=C1 ->
                                    <- Retry: DCID=C1, SCID=S2 Initial: DCID=S2, SCID=C1 ->
                                  <- Initial: DCID=C1, SCID=S3 ... 1-RTT: DCID=S3 ->
                                             <- 1-RTT: DCID=C1

Рисунок 8. Использование идентификаторов соединения при согласовании с Retry.


В обоих случаях (рисунки 7 и 8) клиент устанавливает для транспортного параметра initial_source_connection_id значение C1. При согласовании без пакета Retry (рисунок 7) сервер устанавливает original_destination_connection_id = S1 (это значение выбрано клиентом) и initial_source_connection_id = S3 и не включает транспортный параметр retry_source_connection_id. В согласовании с Retry (рисунок 8) сервер устанавливает original_destination_connection_id = S1, retry_source_connection_id = S2 и initial_source_connection_id = S3.

7.4. Транспортные параметры

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

Транспортные параметры каждая конечная точка объявляет в одностороннем порядке и может выбрать значения независимо от значений своего партнёра. Представление транспортных параметров описано в разделе 18.

QUIC включает кодированные транспортные параметры в криптографическое согласование, по завершении которого становятся доступными транспортные параметры, заявленные партнёром. Каждая конечная точка проверяет действительность полученных от партнёра значений. Определения транспортных параметров даны в параграфе 18.2.

Получение транспортного параметра с недействительным значением конечная точка должна считать ошибкой соединения типа TRANSPORT_PARAMETER_ERROR. Конечным точкам недопустимо передавать параметр более одного раза в данном расширении транспортных параметров. Получение дубликата транспортного параметра конечной точке следует считать ошибкой соединения типа TRANSPORT_PARAMETER_ERROR.

Конечные точки применяют транспортные параметры для аутентификации идентификаторов соединения при согласовании (см. параграф 7.3).

ALPN [ALPN] позволяет клиентам предложить несколько прикладных протоколов на этапе организации соединения. Транспортные параметры, включённые клиентом в процессе согласования, применяются ко всем прикладным протоколам, предлагаемым клиентом. Прикладные протоколы могут рекомендовать значения для транспортных параметров, такие как начальные ограничения контроля потока данных. Однако прикладные протоколы, устанавливающие ограничения для транспортных параметров, могут не позволить клиенту предложить множество прикладных протоколов, если возникают конфликты.

7.4.1. Значения транспортных параметров для 0-RTT

Использование 0-RTT зависит как от клиента, так и от сервера, применяющих параметры, согласованные в предшествующем соединении. Для включения 0-RTT конечные точки сохраняют значения транспортных параметров сервера со всеми сеансовыми квитанциями, полученными в соединении. Конечные точки также сохраняют сведения, требуемые прикладному протоколу или криптографическому согласованию (см. параграф 4.6 в [QUIC-TLS]). Значения сохранённых транспортных параметров используются при попытке применить 0-RTT с сеансовыми квитанциями.

Сохранённые параметры транспорта применяются к новому соединению, пока не будет завершено согласование и клиент не начнёт передачу пакетов 1-RTT. По завершении согласования клиент применяет заданные в нем параметры транспорта. Запоминаются не все транспортные параметры, поскольку некоторые из них не применимы к будущим соединениям или не влияют на использование 0-RTT.

Определение нового транспортного параметра (параграф 7.4.2) должно указывать режим его сохранения для 0-RTT (обязательно, опционально, запрещено). Клиенту не нужно сохранять параметры, которые он не может обработать.

Клиенту недопустимо применять сохранённые значения параметров ack_delay_exponent, max_ack_delay, initial_source_connection_id, original_destination_connection_id, preferred_address, retry_source_connection_id, stateless_reset_token и он должен использовать новые значения, полученные от сервера при согласовании. Если сервер не представил эти параметры, используются принятые по умолчанию значения.

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

Если сервер воспринимает данные 0-RTT, ему недопустимо снижать значения пределов или менять другие значения, которые могут быть нарушены клиентом через его данные 0-RTT. В частности, воспринимающему данные 0-RTT серверу недопустимо устанавливать значения меньше сохранённых для параметров (параграф 18.2):

  • active_connection_id_limit;

  • initial_max_data;

  • initial_max_stream_data_bidi_local;

  • initial_max_stream_data_bidi_remote;

  • initial_max_stream_data_uni;

  • initial_max_streams_bidi;

  • initial_max_streams_uni.

Пропуск некоторых параметров транспорта или установка для них значения 0 может приводить к тому, что данные 0-RTT будут разрешены, но не пригодны для использования. Для подмножества применимых транспортных параметров, разрешающих передачу данных приложения, следует задавать отличные от 0 значения для 0-RTT. Это включает initial_max_data и (1) initial_max_streams_bidi и initial_max_stream_data_bidi_remote или (2) initial_max_streams_uni и initial_max_stream_data_uni.

Сервер может задать более высокие начальные ограничения для контроля потока данных, нежели сохранённые значения, которые клиент применяет при отправке 0-RTT. По завершении согласования клиент обновляет ограничения контроля потока данных на всех передающих потоках, используя новые значения initial_max_stream_data_bidi_remote и initial_max_stream_data_uni.

Сервер может сохранять и восстанавливать переданные ранее значения max_idle_timeout, max_udp_payload_size, disable_active_migration и отвергать 0-RTT при выборе меньших значений. Снижение значений этих параметров при одновременном восприятии данных 0-RTT может снижать производительность соединения. В частности, снижение max_udp_payload_size может вызывать отбрасывание пакетов, ведущее к снижению производительности по сравнению с отклонением данных 0-RTT.

Сервер должен отвергать данные 0-RTT, если восстановленные значения параметров транспорта не могут поддерживаться.

При отправке кадров в пакетах 0-RTT клиент должен применять лишь запомненные параметры транспорта и недопустимо использовать обновлённые значения, полученные от сервера в транспортных параметрах или кадрах из пакетов 1-RTT. Например, ограничения контроля потока данных из запомненных параметров транспорта применяются ко всем пакетам 0-RTT даже при увеличении значений параметров в согласовании или кадрах из пакетов 1-RTT. сервер может считать применения обновлённых параметров транспорта в 0-RTT ошибкой соединения типа PROTOCOL_VIOLATION.

7.4.2. Новые транспортные параметры

Для согласования нового поведения протокола могут применяться новые параметры транспорта. Конечная точка должна игнорировать неподдерживаемые транспортные параметры. Отсутствие параметра отключает необязательную функцию протокола, согласуемую этим параметром. Как указано в параграфе 18.1, некоторые идентификаторы зарезервированы для исполнения этого требования.

Клиент, не понимающий транспортный параметр, может отбросить его и попытаться примерить 0-RTT в последующих соединениях. Однако при добавлении на клиенте поддержки отброшенного транспортного параметра возникает риск того, что задаваемые параметром ограничения будут нарушены при попытке использовать 0-RTT. Новые параметры транспорта позволяют избежать таких проблем за счёт установки по умолчанию наиболее консервативного значения. Клиенты могут избежать проблемы запоминая все параметры, включая неподдерживаемые.

Новые параметры транспорта могут регистрироваться в соответствии с правилами параграфа 22.3.

7.5. Буферизация криптографических сообщений

Реализациям нужно поддерживать буфер данных CRYPTO, принятых с нарушением порядка. Поскольку для кадров CRYPTO нет управления потоком данных, конечная точка может вынудить партнёра буферизовать неограниченный объем данных.

Реализация должна обеспечивать буфер не менее 4096 байтов для полученных с нарушением порядка кадров CRYPTO. Конечные точки могут согласовать выделение больших буферов. Увеличение предела в процессе согласования позволяет обмениваться более длинными ключами и свидетельствами. В течение срока действия соединения конечная точка не обязана сохранять размер буфера.

Неспособность буферизовать кадры CRYPTO в процессе согласования может приводить к отказу соединения. Если буфер конечной точки заполняется в процессе согласования, его можно временно расширить для завершения согласования. Если конечная точка не расширяет буфер, она должна закрыть соединение с кодом ошибки CRYPTO_BUFFER_EXCEEDED.

Если по завершении согласования конечная точка не способна буферизовать все данные кадра CRYPTO, она может отбросить кадр CRYPTO и все будущие кадры CRYPTO или может закрыть соединение с кодом ошибки CRYPTO_BUFFER_EXCEEDED. Пакеты, содержащие отброшенные кадры CRYPTO, должны подтверждаться, поскольку они были получены и обработаны транспортом, несмотря на отбрасывание кадров CRYPTO.

8. Проверка адреса

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

Основной защитой от атак с усилением трафика является проверка способности партнёра принимать пакеты по заявленному им транспортному адресу. Поэтому после приёма пакета с непроверенного адреса конечная точка должна ограничить объем передаваемых по непроверенному адресу данных до троекратного размера полученных с этого адреса данных. Этот предел размера откликов называют «антиусилительным» (anti-amplification).

Проверка адреса выполняется при организации (параграф 8.1) и переносе (параграф 8.2) соединения.

8.1. Проверка адреса при организации соединения

При организации соединения неявно выполняется проверка адресов обеих конечных точек. В частности, получение пакета, защищённого ключами Handshake, подтверждает, что партнёр успешно обработал пакет Initial. После успешной обработки пакета Handshake от партнёра конечная точка может считать его адрес проверенным. Кроме того, конечная точка может считать адрес партнёра проверенным, если тот использует идентификатор соединения, выбранный конечной точкой и содержащий не менее 64 битов энтропии.

Значение поля Destination Connection ID в его первом пакете Initial позволяет клиенту проверить адрес сервера в процессе обработки пакета. Пакеты Initial от сервера защищены с использованием ключей, выведенных из этого значения (см. параграф 5.2 в [QUIC-TLS]). Кроме того, значение возвращается сервером в пакетах Version Negotiation (раздел 6) или включается в тег Integrity пакетов Retry (параграф 5.8 в [QUIC-TLS]).

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

Клиент должен обеспечить в дейтаграмме UDP с пакетом Initial не менее 1200 байтов данных UDP (payload), добавляя при необходимости кадры PADDING. Отправка клиентом дополненных дейтаграмм позволяет серверу передать больше данных до завершения проверки адреса.

Потеря пакета Initial или Handshake от сервера может вызвать блокировку, если клиент не передаст дополнительных пакетов Initial или Handshake. Блокировка может возникнуть при достижении на сервере порода «антиусиления» и получении клиентом подтверждения для всех отправленных данных. Если в таком случае у клиента нет причин продолжать отправку дополнительных пакетов, сервер не сможет передать больше данных, поскольку адрес клиента ещё не проверен. Для предотвращения блокировки клиент должен передать пакет по тайм-ауту PTO (Probe Timeout, параграф 6.2 в [QUIC-RECOVERY]). В частности, клиент должен передать пакет Initial в дейтаграмме UDP, содержащей не менее 1200 байтов, если у него нет ключей Handshake, или передать пакет Handshake.

Сервер может захотеть проверить адрес клиента до начала криптографического согласования. QUIC использует маркер в пакете Initial для проверки адреса до завершения согласования. Этот маркер доставляется клиенту при организации согласования с пакетом Retry (параграф 8.1.2) или в предыдущем соединении с использованием кадра NEW_TOKEN (параграф 8.1.3).

Помимо ограничений на отправку до проверки адреса серверы также ограничены в возможности управлять ограничениями, заданными контроллером перегрузки. Клиенты ограничены лишь контроллером перегрузки.

8.1.1. Создание маркера

Маркер в кадре NEW_TOKEN или пакете Retry должен создаваться так, чтобы сервер мог определить способ его предоставления клиенту. Маркер в обоих случаях передаётся в одном поле, но обработка на сервере различается.

8.1.2. Проверка адреса с помощью пакетов Retry

После приёма пакета Initial от клиента сервер запрашивает проверку адреса, передавая пакет Retry (параграф 17.2.5) с маркером. Маркер должен повторяться клиентом во всех пакетах Initial, передаваемых для соединения после приёма пакета Retry. По результату обработки пакета Initial с маркером из пакета Retry сервер не может передать другой пакет Retry, а может лишь отвергнуть соединение или продолжить обработку. Пока атакующий не способен создать действительный маркер для своего адреса (см. параграф 8.1.4), а клиент может вернуть маркер, это подтверждает серверу получение маркера клиентом.

Сервер может также использовать пакет Retry, чтобы отложить на время состояние и расходы на обработку организации соединения. Требование к серверу предоставить другой идентификатор соединения вместе с исходным параметром транспорта original_destination_connection_id transport, определенным в параграфе 18.2, заставляет сервер продемонстрировать, что он или взаимодействующий с ним объект получил от клиента исходный пакет Initial. Представление другого идентификатора соединения также даёт серверу некоторый контроль над маршрутизацией последующих пакетов, что можно использовать для отправки соединений другому экземпляру сервера.

При получении сервером от клиента корректного пакета Initial с недействительным маркером Retry, он знает, что клиент не воспримет другой маркер Retry. Сервер может отбросить такой пакет и разрешить клиенту тайм-аут для обнаружения отказа при согласовании, но это может внести для клиента существенную задержку. Вместо этого серверу следует незамедлительно закрыть соединение (параграф 10.2) с ошибкой INVALID_TOKEN. Сервер на этом этапе не установил состояния для соединения и не задал время закрытия. Поток с использованием пакета Retry показан на рисунке 9.

Клиент                                                  Сервер

Initial[0]: CRYPTO[CH] ->

                                                <- Retry+Token 
Initial+Token[1]: CRYPTO[CH] ->

                                 Initial[0]: CRYPTO[SH] ACK[1]
                       Handshake[0]: CRYPTO[EE, CERT, CV, FIN]
                                 <- 1-RTT[0]: STREAM[1, "..."]

Рисунок 9. Пример согласования с пакетом Retry.


8.1.3. Проверка адреса для будущих соединений

Сервер может предоставить клиенту маркер проверки адреса для использования в последующем соединении. Проверка адреса особо важна для 0-RTT, поскольку сервер может передавать клиенту значительный объем данных в ответ на данные 0-RTT. Сервер применяет кадр NEW_TOKEN (параграф 19.7) для предоставления клиенту маркера, служащего для проверки адреса в будущих соединениях. В таком соединении клиент включает маркер в передаваемые пакеты Initial, пока пакет Retry не заменит маркер новым. Клиенту недопустимо применять маркер из пакета Retry для будущих соединений. Серверы могут отбрасывать пакеты Initial, не включающие ожидаемый маркер.

В отличие от сразу применяемого маркера из пакета Retry, маркер в кадре NEW_TOKEN можно использовать в течение некоторого времени после его передачи. Поэтому маркеру следует иметь срок действия, который может быть явно указан временем окончания или временной меткой, служащей для динамического расчёта времени окончания срока действия. Сервер может сохранять время завершения срока действия или включать его в зашифрованный маркер. В маркер кадра NEW_TOKEN недопустимо включать сведения, которые позволят стороннему наблюдателю связать значение с соединением, где оно было передано. Например, нельзя включать идентификатор предыдущего соединения или адресные данные, если эти значения не зашифрованы. Сервер должен обеспечить для каждого нового кадра NEW_TOKEN уникальность среди всех клиентов, за исключением случаев передачи с целью восстановления при потере предшествующих кадров NEW_TOKEN. Информация, позволяющая серверу различать маркеры из Retry и NEW_TOKEN. может быть доступна не только серверу.

Вероятность совпадения номера клиентского порта для двух разных соединений мала, поэтому проверка порта вряд ли будет эффективна.

Маркер из кадра NEW_TOKEN применим к любому серверу, для которого соединение считается полномочным (например, для серверов, имена которых указаны в сертификате). При соединении с сервером, для которого у клиента имеется применимый и не использованный маркер, следует включать этот маркер в поле Token пакета Initial. Включение маркера может позволить серверу проверить адрес клиента без дополнительного кругового обхода. Клиенту недопустимо включать маркер, не применимый для сервера, с которым соединяется клиент, пока у него нет уверенности, что передавший маркер сервер и сервер, к которому клиент подключается, управляют маркерами совместно. Клиент может использовать маркер из любого прежнего соединения с сервером.

Маркер позволяет серверу сопоставить соединение, где маркер был выпущен, с соединением, где тот используется. Клиенты, желающие прервать своё отождествление на сервере, могут отбросить маркеры из кадров NEW_TOKEN. Для сравнения, маркер из пакета Retry должен применяться сразу же в соединении, где он получен, и не может использоваться в последующих попытках соединения.

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

При получении сервером пакета Initial с маркером проверки адреса он должен попытаться проверить маркер, если проверка адреса ещё не завершена. Если маркер недействителен, серверу следует действовать как при отсутствии для клиента проверенного адреса, включая возможную отправку пакета Retry. Маркеры из кадра NEW_TOKEN и пакета Retry серверы могут различать (параграф 8.1.1) и последние могут проверяться более строго. При успешной проверке серверу следует разрешать выполнение согласования.

Примечание. Основанием считать клиента неподтвержденным вместо отбрасывания его пакетов служит то, что клиент мог получить маркер в кадре NEW_TOKEN предыдущего соединения и при утрате сервером состояния он не может проверить маркер, что приведёт к отказу в соединении, если пакет будет отброшен.

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

Клиенты могут использовать полученные в соединении маркеры при другой попытке соединения с той же версией. При выборе маркера для применения клиент не обязан рассматривать другие свойства соединения, включая выбор возможных прикладных протоколов, сеансовые квитанции и пр.

8.1.4. Целостность маркера проверки адреса

Маркер проверки адреса должен быть трудно предсказуемым. Включения в маркер случайного значения, содержащего не менее 128 битов энтропии, будет достаточно, но это зависит от того, помнит ли сервер значения, переданные клиентам.

Схема с маркером позволяет серверу выгрузить (offload) состояние, связанное с проверкой клиента. Чтобы это работало, маркер должен учитываться системой защиты целостности от изменения или поддержки клиентами. Без защиты целостности вредоносные клиенты могут создать или угадать маркеры, которые будут восприняты сервером. Доступ к ключу защиты целостности маркеров нужен лишь серверу.

Не требуется использовать для маркеров чётко заданный формат, поскольку маркеры воспринимает создавший их сервер. В маркеры, передаваемые в пакетах Retry, следует включать сведения, которые позволят серверу проверить неизменность IP-адреса и порта в пакетах клиента. Маркеры в кадрах NEW_TOKEN должны включать сведения, позволяющие серверу убедиться, что IP-адрес клиента не изменился с момента выдачи маркера. Сервер может использовать маркеры из кадров NEW_TOKEN для решения вопроса об отправке пакета Retry даже при смене клиентом адреса. Если IP-адрес клиента поменялся, сервер должен соблюдать предел «антиусиления», как указано в разделе 8. Отметим, что в присутствии NAT этого может быть недостаточно для защиты других хостов за NAT от атак с усилением.

Атакующий может воспроизвести маркеры для использования сервера в качестве усилителя DDoS-атак. Для защиты от таких атак серверы должны гарантировать предотвращение или ограничение повторного использования маркеров. Серверам следует воспринимать маркеры из пакетов Retry лишь в течение короткого времени, поскольку клиенты возвращают их незамедлительно. Маркеры из кадров NEW_TOKEN (параграф 19.7) должны действовать дольше, но не следует воспринимать их несколько раз. Серверам рекомендуется разрешать лишь однократное применение маркера, если это возможно. Маркеры могут включать другие сведения, дополнительно ограничивающие применимость и возможность повторного использования.

8.2. Проверка пути

Проверка пути используется обоими партнёрами при переносе соединения (см. раздел 9) для проверки доступности после смены адреса. Партнёры проверяют доступность пути между конкретным локальным адресом и портом и заданным адресом партнёра и его портом. При проверке пути тестируется получение партнёром. отправленных ему пакетов. Проверка служит для обеспечения гарантии того, что пакет, полученный от сменившего адрес партнёра, не содержит подставной адрес.

Проверка пути не подтверждает возможность передачи партнёром. пакетов в обратном направлении. Подтверждения не могут служить проверкой обратного пути, поскольку они не содержат достаточной энтропии и могут быть подделаны. Конечные точки независимо проверяют доступность пути в каждом направлении и доступность обратного пути может быть указана лишь партнёром. Проверку пути может использовать любая конечная точка в любой момент. Например, конечная точка может проверить, что партнёр по-прежнему владеет адресом после периода бездействия.

Проверка пути не предназначена для работы через NAT. Хотя описанный здесь механизм может быть эффективным для создания привязок NAT, поддерживающих прохождение через NAT, предполагается, что одна конечная точка способна принимать пакеты без предварительной отправки пакета по этому пути. Для эффективной работы через NAT нужны дополнительные механизмы синхронизации, не представленные здесь.

Конечная точка может дополнять другими кадрами используемые для проверки пути кадры PATH_CHALLENGE и PATH_RESPONSE. В частности, конечная точка может включать кадры PADDING вместе с кадром PATH_CHALLENGE для PMTUD8 (см. параграф 14.2.1), а также отправлять свой кадр PATH_CHALLENGE при передаче PATH_RESPONSE.

Конечная точка использует новый идентификатор соединения для отправки пробных пакетов с нового локального адреса (см. параграф 9.5). Про зондировании нового пути конечная точка может гарантировать своему партнёру наличие неиспользованного идентификатора соединения для отправки откликов. Передача NEW_CONNECTION_ID и PATH_CHALLENGE в одном пакете (если позволяет параметр партнёра active_connection_id_limit) обеспечивает доступность неиспользованного идентификатора соединения для передачи отклика.

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

8.2.1. Инициирование проверки пути

Для начала проверки пути конечная точка передаёт кадр PATH_CHALLENGE с непредсказуемыми данными по проверяемому пути. Конечная точка может передать множество кадров PATH_CHALLENGE для защиты от потери пакетов, однако не следует передавать несколько кадров PATH_CHALLENGE в одном пакете. Конечной точке не следует проверять новый путь с пакетами, содержащими PATH_CHALLENGE, более часто, чем передаются пакеты Initial. Это гарантирует, что при переносе соединения нагрузка на новом пути не будет выше нагрузки при организации соединения. Конечная точка должна использовать непредсказуемые данные в каждом кадре PATH_CHALLENGE, чтобы связать отклик партнёра с соответствующим PATH_CHALLENGE.

Конечная точка должна обеспечивать дейтаграммам с кадром PATH_CHALLENGE размер не меньше минимально разрешённого максимума в 1200 байтов, если предел антиусиления не запрещает это. Отправка дейтаграмм UDP такого размера гарантирует, что путь от конечной точки до партнёра подходит для QUIC (см. раздел 14). Если конечная точка не может расширить дейтаграмму до 1200 байтов из-за ограничений антиусиления, значение MTU на пути не будет проверено. Чтобы гарантировать достаточный размер MTU на пути, конечная точка должна выполнить втору проверку пути, отправляя кадр PATH_CHALLENGE в дейтаграмме размером не менее 1200 байтов. Эта дополнительная проверка может быть выполнена после приёма кадра PATH_RESPONSE или получения по данному пути достаточного числа байтов, чтобы можно было передать большую дейтаграмму без ограничений антиусиления.

В отличие от других случаев расширения размера дейтаграмм, конечным точкам недопустимо отбрасывать дейтаграммы, представляющиеся слишком мелкими, если они содержат PATH_CHALLENGE или PATH_RESPONSE.

8.2.2. Отклики при проверке пути

При получении кадра PATH_CHALLENGE конечная точка должна ответить кадром PATH_CHALLENGE с копией данных из PATH_RESPONSE. Конечной точке недопустимо задерживать отправку кадров PATH_RESPONSE, если ей не препятствует механизм контроля перегрузок. Кадр PATH_RESPONSE должен передаваться в путь, по которому был получен кадр PATH_CHALLENGE. Это обеспечивает успешную проверку пути партнёром. лишь при работе пути в обоих направлениях. Инициатору проверки пути недопустимо применять это требование, поскольку это открывает возможность атак на перенос соединений (см. параграф 9.3.3).

Конечная точка должна увеличивать размер дейтаграмм с кадром PATH_RESPONSE по меньшей мере до наименьшего разрешённого максимума в 1200 байтов для подтверждения поддержки дейтаграмм такого размера в обоих направлениях. Однако конечной точке недопустимо расширять дейтаграммы с PATH_RESPONSE сверх предела антиусиления. Предполагается, что это может происходить лишь при получении PATH_CHALLENGE без расширения дейтаграммы.

Конечной точке недопустимо передавать более одного кадра PATH_RESPONSE в ответ на кадр PATH_CHALLENGE (см. параграф 13.3). Предполагается, что при необходимости партнёр передаст дополнительные кадры PATH_CHALLENGE, чтобы получить добавочные отклики PATH_RESPONSE.

8.2.3. Успешная проверка пути

Проверка пути успешна при получении PATH_RESPONSE с данными из соответствующего кадра PATH_CHALLENGE. Кадр PATH_RESPONSE, принятый по любому пути, подтверждает путь, по которому отправлен PATH_CHALLENGE.

Если конечная точка передаёт кадр PATH_CHALLENGE в дейтаграмме размером не более 1200 байтов и отклик на неё подтверждает адрес партнёра, путь считается проверенным, но без подтверждения MTU для него. В результате конечная точка может передать данные размером более троекратного размера принятых данных. Однако конечная точка должна инициировать другую проверку пути с расширенными дейтаграммами для проверки значения MTU.

Получение подтверждения для пакета с кадром PATH_CHALLENGE не обеспечивает проверки пути, поскольку подтверждение можно подделать.

8.2.4. Отказ при проверке пути

Проверка пути считается неудачной лишь в том случае, когда проверяющая путь конечная точка отказывается от дальнейших попыток проверить путь. Конечным точкам следует прекращать проверку пути по таймеру. При установке таймера реализации следует понимать, что новый путь может иметь больший период кругового обхода. Рекомендуется устанавливать значение в 3 раза больше текущего PTO или PTO для нового пути (с использованием kInitialRtt, как определено в [QUIC-RECOVERY]). Такой тайм-аут позволяет проверять путь в течение нескольких PTO, чтобы потеря одного кадра PATH_CHALLENGE или PATH_RESPONSE не приводила к отказу.

Отметим, что проверяющая система может получать по новому пути другие кадры, но для успешной проверки нужен кадр PATH_RESPONSE с соответствующими данными.

Когда конечная точка отказывается от проверки пути, она считает его непригодным для использования. Это не обязательно вызывает отказ в соединении и конечные точки могут продолжать передачу пакетов по другим путям. Если доступных путей нет, конечная точка может подождать появления нового пути или закрыть соединение. Конечная точка, не имеющая доступного пути к партнёру, может сообщить об этом, используя ошибку соединения NO_VIABLE_PATH и указав при этом, что это возможно лишь при наличии пути без поддержки требуемого MTU (параграф 14).

Проверка пути может быть прекращена по иным причинам, прежде всего, в результате перехода на новый путь в процессе выполняемой проверки пути.

9. Перенос соединения

Использование идентификаторов соединения обеспечивает устойчивость соединений к смене адресов конечных точек (IP-адрес и порт), например при переходе конечной точки в другую сеть. В этом разделе описан процесс перехода конечной точки на новый адрес. Работа QUIC основана на сохранении конечными точками стабильных адресов в процессе согласования (handshake). Конечной точке недопустимо инициировать перенос до завершения согласования, как указано в параграфе 4.1.2 [QUIC-TLS].

Если партнёр передал транспортный параметр disable_active_migration, конечной точке недопустимо передавать пакеты (включая пакеты зондирования, см. параграф 9.1) с другого локального адреса на использованный при согласовании адрес партнёра, коль скоро конечная точка не действует в соответствии с транспортным параметром preferred_address от партнёра. Если партнёр нарушает это требование, конечная точка должна отбрасывать входящие пакеты на этом пути без генерации Stateless Reset или выполнить проверку пути и позволить партнёру переместиться. Генерация Stateless Reset или закрытие соединения позволили бы третьей стороне вызвать закрытие соединения путём использования обманных адресов или иных манипуляций с наблюдаемым трафиком.

Не каждая смена адреса партнёром. связана с преднамеренным (активным) перемещением. Это может быть связано с перестройкой NAT – сменой адреса промежуточным устройством (обычно NAT), выделением нового выходного порта или даже адреса IP для потока. Конечная точка должна проверить путь (параграф 8.2) при обнаружении смены партнёром. адреса, если этот адрес не был проверен ранее.

Когда у конечной точки нет проверенного пути для отправки пакетов, она может сбросить соединение. Конечная точка, способная переносить соединение, может выждать появления доступного пути без сброса соединения.

Этот документ ограничивает перенос соединений сменой адреса клиента, а также случаем, описанным в параграфе 9.6. Предпочтительный адрес сервера. За инициирование переноса отвечают клиенты. Серверы не передают пакетов, не связанных с зондированием (см. параграф 9.1) по адресу клиента, пока они не получат с этого адреса пакетов, не являющихся зондами. Пакеты, полученные клиентом с неизвестного адреса сервера должны отбрасываться.

9.1. Зондирование нового пути

Конечная точка может проверить доступность партнёра с нового локального адреса, используя проверку пути (параграф 8.2) до переноса соединения на этот адрес. Отказ при проверке пути просто означает непригодность пути для этого соединения и не ведёт к разрыву соединения, если имеются другие пути.

Кадры PATH_CHALLENGE, PATH_RESPONSE, NEW_CONNECTION_ID и PADDING считаются «кадрами зондирования», а пакет, содержащий лишь такие кадры – «пакетом зондирования».

9.2. Инициирование переноса соединения

Конечная точка может перенести соединение на новый локальный адрес, передавая с этого адреса пакеты, не относящиеся к зондированию.

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

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

При переносе новый путь может не поддерживать текущую скорость передачи конечной точки, поэтому конечная точка сбрасывает свой контроллер перегрузок и оценку RTT, как описано в параграфе 9.4. На новом пути возможности ECN могут отличаться, поэтому конечная точка проверяет их, как описано в параграфе 13.4.

9.3. Реакция на перенос соединения

Получение с нового адреса партнёра не относящегося к зондированию пакета указывает переход партнёра на новый адрес. Если получатель разрешает переход, он должен передавать последующие пакеты по новому адресу, а также должен начать проверку пути (параграф 8.2), чтобы убедиться во владении партнёра адресом, если проверка ещё не проведена. Если у получателя нет неиспользуемого идентификатора соединения от партнёра, он не сможет ничего передать по новому пути (см. параграф 9.5).

Конечная точка меняет адрес, по которому она отправляет пакеты, лишь в ответ на пакет с большим номером, не относящийся к зондированию. Это предотвращает отправку конечной точкой пакетов по старому адресу партнёра в случае приёма разупорядоченных пакетов.

Конечная точка может передавать данные по непроверенному адресу партнёра, но она должна защищаться от атак , описанных в параграфах 9.3.1 и 9.3.2. Конечная точка может пропустить проверку адреса партнёра, если она видела этот адрес раньше. В частности, при возврате конечной точки на проверенный ранее путь после обнаружения того или иного ложного переноса пропуск проверки адреса и восстановление статуса обнаружения потерь могут снижать влияние атаки на производительность.

После смены адреса, по которому передаются не являющиеся зондами пакеты, конечная точка может отказаться от проверки пути для других адресов.

Получение пакета с новым адресом партнёра может быть результатом перестройки NAT на стороне партнёра.

После проверки нового адреса клиента серверу следует передать новые маркеры проверки адреса (параграф 8).

9.3.1. Подмена адреса партнёра.

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

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

Если конечная точка не проверяет адрес партнёра, как описано выше, ей не нужно ограничивать скорость отправки.

9.3.2. Подмена адреса на пути

Атакующий может вызвать ложный перенос соединения, копируя и пересылая пакеты с фиктивным адресом так, чтобы они приходили раньше исходных пакетов. Пакеты с фиктивными адресами будут казаться пакетами с нового адреса, а исходные пакеты – дубликатами (отбрасываются). После ложного переноса проверка адреса отправителя может привести к отказу, поскольку у объекта с подставным адресом нет криптографических ключей для чтения кадра PATH_CHALLENGE и отклика на него.

Для защиты соединения от таких ложных переносов конечная точка должна вернуться к использованию проверенного адреса партнёра. в случае отказа при проверке нового адреса. Кроме того, получение пакетов с большими номерами с легитимного адреса партнёра вызовет ещё один перенос соединения. В результате проверка адреса для ложного переноса будет отменена, ограничивая ложный перенос вставкой одного пакета.

Если у конечной точки нет статуса последнего проверенного адреса партнёра, она должна закрыть соединение без уведомления партнёра, просто сбросив его состояние. Это ведёт к обычной обработке пакетов в новом соединении. Например, конечная точка может передавать a Stateless Reset в ответ на последующие входящие пакеты.

9.3.3. Подмена адреса вне пути

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

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

Не связанные с зондированием пакеты, полученные по исходному пути с ростом порядковых номеров в принятых пакетах заставят конечную точку вернуться на этот путь. Выявление таких пакетов повышает вероятность обнаружения атаки и её неудачи. Поэтому смягчение таких атак зависит от инициирования обмена пакетами.

В ответ на очевидный перенос соединения конечные точки должны проверить ранее активный путь с помощью кадра PATH_CHALLENGE. Это включает отправку по данному пути новых пакетов. Если путь больше не действует, попытка проверки приведёт к тайм-ауту и отказу. Если же путь действует, но перестал быть желательным, проверка завершится успехом, но приведёт лишь к отправке пакетов зондирования.

Конечной точке, принявшей кадр PATH_CHALLENGE по активному пути, следует передать в ответ не являющийся зондом пакет. Последующий перенос пути запустит процесс снова.

Такая защита несовершенна, но не создаёт серьёзных проблем. Если путь через атакующего действительно быстрее исходного пути, атаку невозможно отличить от изменения маршрутизации, несмотря на попытки использовать исходный путь.

Конечная точка может использовать эвристические методы для более надёжного обнаружения этого типа атак. Например, смену привязки NAT невозможно проверить, если пакеты были недавно приняты по старому пути. Кроме того, смена привязки редко возникает на путях IPv6. Конечные точки могут также искать дубликаты пакетов. Изменение идентификатора соединения более чётко указывает преднамеренный перенос соединения, а не атаку.

9.4. Обнаружение потерь и контроль перегрузок

Пропускная способность нового пути может отличаться от прежней. Отправленные по прежнему пути пакеты недопустимо учитывать при контроле перегрузки или расчёте RTT для нового пути.

После подтверждения владения партнёром. новым адресом конечная точка должна немедленно сбросить контроллер перегрузки и оценку времени кругового обхода для нового пути (см. Приложения A.3 и B.3 в [QUIC-RECOVERY]), если единственным изменением не является номер порта партнёра. Поскольку смена лишь порта обычно является результатом перестройки NAT или действий промежуточного устройства, конечная точка может сохранить статус контроля перегрузки и оценку RTT для таких случаев. Если состояние контроля перегрузки старого пути применяется на новом пути с существенно иными характеристиками, отправитель может передать много данных, пока контроль перегрузок и оценка RTT будут скорректированы. Обычно разработчикам рекомендуется с осторожностью применять прежние значения для нового пути.

В процессе переноса соединения, когда конечная точка может отправлять данные и зонды по разным адресам или с разных адресов, у получателя может нарушаться порядок доставки пакетов из-за разного времени кругового обхода на путях. Получатель пакетов по нескольким путям будет по-прежнему отправлять кадры ACK, подтверждающие все принятые пакеты. Хотя в процессе переноса может использоваться несколько путей, может быть достаточно одного контекста контроля перегрузок и одного контекста восстановления при потерях, как указано в [QUIC-RECOVERY]. Например, конечная точка может задержать переключение на новый контекст контроля перегрузок, пока не убедиться в ненужности прежнего пути (как в случае, описанном в параграфе 9.3.3).

Отправитель может делать исключения для пакетов зондирования, чтобы обнаружение их потери было независимым и не вызывало чрезмерного снижения скорости контроллером перегрузки. Конечная точка может установить при отправке PATH_CHALLENGE отдельный таймер, который останавливается при получении соответствующего кадра PATH_RESPONSE. Если отсчёт таймера завершается до получения PATH_RESPONSE, конечная точка может передать новый кадр PATH_CHALLENGE и запустить таймер на большее время. Этот таймер следует устанавливать в соответствии с параграфом 6.2.1 в [QUIC-RECOVERY] и недопустимо делать более настойчивым.

9.5. Влияние переноса соединения на приватность

Использование стабильного идентификатора соединения на нескольких путях позволит пассивному наблюдателю сопоставить активность на этих путях. Перемещающаяся между путями конечная точка может не желать сопоставления своей активности сторонними объектами, поэтому следует использовать разные идентификаторы соединений при передаче с разных локальных адресов, как описано в параграфе 5.1. Для того, чтобы это было эффективным, конечным точкам нужно предотвратить возможность других связать идентификаторы между собой.

Конечные точки могут в любой момент сменить передаваемое значение Destination Connection ID на не применявшийся ранее на другом пути идентификатор.

Конечной точке недопустимо использовать один идентификатор соединения для отправки с нескольких локальных адресов, например при инициировании переноса соединения (параграф 9.2) или зондировании пути (параграф 9.1). Точно так же конечной точке недопустимо использовать один идентификатор соединения для отправки по нескольким адресам. В результате изменений, не контролируемых партнёром., конечная точка может получить пакеты с нового адреса отправителя, но с тем же Destination Connection ID и в этом случае она может продолжать использование идентификатора соединения с новым адресом, если отправка происходит с того же локального адреса.

Требования в части повторного использования идентификаторов соединения относятся лишь к отправке пакетов, поскольку возможны непреднамеренные изменения пути без смены идентификатора соединения. Например, после бездействия перестройка NAT может приводить к передаче пакетов по новому пути после восстановления передачи клиентом. Реакция конечной точки на такие пакеты описана в параграфе 9.3.

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

Конечной точке не следует инициировать переход для партнёра, запросившего пустой идентификатор соединения, поскольку трафик по новому пути тривиально сопоставляется с трафиком по прежнему пути. Способность сервера привязать пакеты с пустым идентификатором соединения к нужному соединению означает использование сервером других сведений для демультиплексирования пакетов. Например, сервер может предоставить каждому клиенту уникальный адрес, используя дополнительные службы HTTP [ALTSVC]. Сведения,, позволяющие корректно маршрутизировать пакеты по нескольким путям, позволяют также стороннему наблюдателю сопоставить активность на этих путях.

Клиент может снизить вероятность сопоставления путём смены идентификатора соединения, порта UDP у отправителя, адреса IP (см. [RFC8981]) при передача трафика после временного бездействия. Смена адреса, с которого передаются пакеты, может приводить к тому, что сервер сделает вывод о переносе соединения. Это ведёт к применению механизмов поддержки переноса соединения даже для клиентов, с которыми не связана перестройка NAT или фактический перенос. Смена адреса может заставить партнёра сбросить состояние контроля перегрузки (параграф 9.4), поэтому адреса следует менять нечасто.

Конечная точка, исчерпавшая запас идентификаторов соединений, не может проверить новые пути или инициировать перенос, а также ответить на зонды или попытку партнёра перенести соединение. Для обеспечения возможности переноса и предотвращения сопоставления переданных по разным путям пакетов конечным точкам следует предоставлять новые идентификаторы соединения до переноса партнёра (см. параграф 5.1.1). Если партнёр мог исчерпать доступные идентификаторы соединения, переносимой конечной точке следует включать кадр NEW_CONNECTION_ID во все пакеты, передаваемые по новому пути.

9.6. Предпочтительный адрес сервера

QUIC позволяет серверу воспринять соединение по одному адресу IP и попытаться перенести его после согласования на более предпочтительный адрес. Это особенно полезно в тех случаях, когда клиенты изначально подключаются к адресу, совместно используемому несколькими серверами, но предпочитают для обеспечения стабильности использовать свой индивидуальный адрес. В этом параграфе описан перенос соединения на предпочтительный адрес.

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

9.6.1. Передача предпочтительного адреса

Сервер передаёт предпочтительный адрес в параметре preferred_address во время согласования TLS. Сервер может сообщать предпочтительный адрес в каждом семействе (IPv4 и IPv6), позволяя клиенту выбрать наиболее подходящий.

По завершении согласования клиенту следует выбрать один или два представленных клиентом адреса для инициирования проверки пути (параграф 8.2). Клиент создаёт пакеты, используя не применявшиеся ранее идентификаторы соединения, взятые из транспортного параметра preferred_address или кадра NEW_CONNECTION_ID.

После успешной проверки пути клиенту следует передавать все будущие пакеты по новому адресу сервера, используя новый идентификатор соединения, и прекратить отправку по прежнему адресу сервера. Если проверка пути завершилась отказом, клиент должен продолжать отправку пакетов по прежнему IP-адресу сервера.

9.6.2. Переход на предпочтительный адрес

Переходящий на предпочтительный адрес клиент должен проверить выбранный адрес (см. параграф 21.5.3).

Сервер может получить пакет, направленный на предпочитаемый им адрес IP в любой момент после восприятия соединения. Если этот пакет содержит кадр PATH_CHALLENGE, сервер передаёт пакет с кадром PATH_RESPONSE, как указано в параграфе 8.2. Сервер должен передавать не относящиеся к зондированию пакеты со своего исходного адреса, пока он не получит от клиента не связанный с зондированием пакет на своём предпочтительном адресе и не проверит новый путь. Север должен проверять путь к клиенту со своего предпочтительного адреса. Это помогает защититься от ложных переносов, инспирированных злоумышленником. По завершении проверки пути сервером и получении не связанного с зондированием пакета с новым наибольшим номером на предпочтительном адресе сервер начинает отправку клиенту не связанных с зондированием пакетов исключительно с предпочтительного адреса IP. Серверу следует отбрасывать для этого соединения новые пакеты, направленные по прежнему адресу IP. Сервер может продолжать обработку задержанных пакетов, принятых на старом адресе IP.

Адрес, предложенный сервером в параметре preferred_address, действителен лишь для соединения, в котором он был представлен. Клиенту недопустимо применять этот адрес для других соединений, восстановленных из текущего.

9.6.3. Перенос клиента и переход на предпочтительный адрес сервера

Клиенту может потребоваться перенести соединение до перехода на предпочтительный адрес сервера. В таком случае клиенту следует одновременно выполнить проверку пути для исходного и предпочтительного адреса сервера со своего нового адреса. Если проверка пути к предпочтительному адресу сервера успешна, клиент должен отказаться от проверки исходного адреса сервера и использовать предпочтительный. Если же проверка пути к предпочтительному адресу завершилась отказом, а для исходного – успехом, клиент может перейти на свой новый адрес и продолжать отправку пакетов по исходному адресу сервера.

Если адрес отправителя в пакетах, принятых на предпочтительном адресе сервера, отличается от представленного клиентом при согласовании, сервер должен использовать защиту от возможных атак, как указано в параграфах 9.3.1 и 9.3.2. Кроме преднамеренного переноса клиента это может быть связано с использованием клиентской сетью доступа другой привязки NAT для предпочтительного адреса сервера.

Серверу следует начать проверку пути к новому адресу клиента при получении пакета зондирования с другого адреса (см. раздел 8).

Клиенту, переходящему на новый адрес, следует использовать предпочтительный адрес сервера из того же семейства.

Идентификатор соединения в транспортном параметре preferred_address не зависит от представленных адресов. Этот идентификатор служит для предоставления клиенту идентификаторов, используемых при переносе, но клиент может использовать идентификаторы на любом пути.

9.7. Использование метки потока IPv6 и перенос

Конечным точкам, передающим данные по протоколу IPv6, следует применять метки потоков IPv6 в соответствии с [RFC6437], если локальный API не запрещает их установку. Генерация меток потоков должна обеспечивать минимизацию возможности выделить ранее использованную метку потока, поскольку это позволит сопоставить активность на разных путях (см. параграф 9.5).

В [RFC6437] предлагается выделять метки потоков с использованием псевдослучайной функции. Включение поля Destination Connection ID в дополнение к адресам отправителя и получателя при генерации меток гарантирует синхронизацию изменений с изменениями других наблюдаемых идентификаторов. Криптографическая функция, комбинирующая эти входные данные с локальным секретом, является одним из вариантов реализации.

10. Завершение соединений

Организованное соединение QUIC может быть прервано одним из трёх способов:

  • тайм-аут бездействия (параграф 10.1);

  • незамедлительное закрытие(параграф 10.2);

  • сброс без учёта состояния (параграф 10.3).

Конечная точка может отбросить статус соединения, если у неё нет проверенного пути для передачи пакетов (параграф 8.2. Проверка пути).

10.1. Тайм-аут бездействия

Если конечная точка задала транспортный параметр max_idle_timeout (параграф 18.2), соединение просто закрывается с отбрасыванием состояния при бездействии в течение времени, превышающего значение max_idle_timeout, заданное обеими конечными точками. Значение max_idle_timeout анонсирует каждая конечная точка и действовать будет меньшее из заявленных значений или единственное, если одна из точек не указала параметр. Анонсируя max_idle_timeout, конечная точка принимает на себя обязательство незамедлительно инициировать закрытие соединения (параграф 10.2), если она завершает его раньше действующего тайм-аута.

Конечная точка перезапускает таймер бездействия при получении и успешной обработке пакета от партнёра, а также при отправке пакета запроса подтверждения, если такие пакеты не передавались с момента обработки полученного последним пакета. Перезапуск таймера при отправке пакета пакета обеспечивает сохранение соединения после его активизации.

Для предотвращения слишком короткого времени ожидания конечные точки должны устанавливать тайм-аут не менее 3 текущих значений тайм-аута зондирования (Probe Timeout или PTO). Это позволяет отправить несколько зондов (которые могут теряться) до истечения тайм-аута ожидания.

10.1.1. Проверка живучести

Конечная точка, передающая пакеты, незадолго до завершения тайм-аута бездействия рискует, что эти пакеты будут отброшены партнёром., поскольку время ожидания может завершиться до прибытия пакета.

Конечная точка может передать PING или иной кадр запроса подтверждения для проверки жизнеспособности соединения, если партнёр может вскоре достичь тайм-аута, такого как PTO (см. параграф 6.2 в [QUIC-RECOVERY]). Это особенно полезно, если нет возможности безопасно повторить отправку данных приложения. Отметим, что безопасность повтора передачи данных определяет приложение.

10.1.2. Отсрочка тайм-аута бездействия

Конечной точке может потребоваться отправить пакеты с запросом подтверждения, чтобы избежать тайм-аута бездействия, если ей нужны данные отклика, но нет возможности передать данные приложения.

Реализация QUIC может предоставлять приложениям возможность отложить тайм-аут бездействия. Это можно использовать в случаях, когда приложение не хочет потерять статус соединения, но не ожидает обмена данными в течение некоторого времени. Конечная точка может периодически передавать кадр PING (параграф 19.2), заставляющий партнёра сбрасывать таймер ожидания. Отправка пакета с кадром PING также перезапускает таймер ожидания для этой конечной точки, если это первый пакет с запросом подтверждения с момента приёма пакета. Отправка кадра PING заставляет партнёра ответить подтверждением и это также перезапускает таймер ожидания для конечной точки.

Прикладным протоколам, использующим QUIC, следует давать указания о возможности отсрочить тайм-аут. Отправка избыточных кадров PING может негативно влиять на производительность.

Тайм-аут возникает при отсутствии приёма или передачи пакетов в течение времени, больше заданного транспортным параметром max_idle_timeout (раздел 10). Однако состояния в промежуточных устройствах могут истекать раньше этого времени. Хотя REQ-5 в [RFC4787] рекомендует время ожидания 2 минуты, опыт показывает, что нужно отправлять пакеты каждые 30 секунд, чтобы большинство промежуточных устройств могло сохранить статус потоков UDP [GATEWAY].

10.2. Незамедлительное закрытие

Конечная точка передаёт кадр CONNECTION_CLOSE (параграф 19.19) для незамедлительного разрыва соединения. Этот кадр немедленно закрывает все потоки и открытые потоки можно считать закрываемыми неявно. После отправки кадра CONNECTION_CLOSE конечная точка незамедлительно переходит в состояние закрытия (параграф 10.2.1), а получившая такой кадр точка – в состояние сброса (draining, см. параграф 10.2.2).

Нарушения протокола ведут к незамедлительному закрытию.

Немедленное закрытие может использоваться после того, как протокол приложения организовал закрытие соединения. Это может быть после согласования прикладным протоколом аккуратного отключения (graceful shutdown). Прикладной протокол может организовать обмен сообщениями, которые нужны обеим конечным точкам для решения вопроса о закрытии соединения, после чего приложение запрашивает закрытие соединения QUIC. При закрытии соединения протоколом QUIC используется кадр CONNECTION_CLOSE с кодом ошибки для информирования партнёра.

Состояния закрытия и сброса соединения предназначены для аккуратного завершений соединений с отбрасыванием задержанных и разупорядоченных пакетов. Эти состояния следует сохранять в течение по меньшей мере 3 интервалов PTO, как указано в [QUIC-RECOVERY].

Удаление статуса соединения до выхода из состояния закрытия или сброса может приводить к генерации конечной точкой ненужного сообщения Stateless Reset при получении пакета с опозданием. Конечные точки, имеющие дополнительные средства предотвращения откликов на запоздалые пакеты, такие как закрытие сокета UDP, могут завершить эти состояния раньше для более быстрого освобождения ресурсов. Серверам, которые сохраняют открытый сокет для восприятия новых соединений, не следует раньше завершать состояние закрытия или сброса.

По завершении состояния закрытия или сброса конечной точке следует отбросить все состояния соединения и можно передавать Stateless Reset в ответ на запоздалые пакеты закрытого соединения.

10.2.1. Состояние Closing

Конечная точка переходит в состояние закрытия после инициирования немедленного закрытия. В этом состоянии конечная точка сохраняет лишь сведения, достаточные для генерации кадра CONNECTION_CLOSE и идентификации пакетов, относящихся к соединению. Конечная точка в таком состоянии передаёт пакет с кадром CONNECTION_CLOSE в ответ на любой входящий пакет, относящийся к соединению. Конечной точке следует ограничивать частоту генерации пакетов в состоянии закрытия. Например, можно ожидать получения прогрессивно увеличивающегося числа пакетов или просто увеличивать время отклика на принятые пакеты.

Выбранного конечной точкой идентификатора соединения и версии QUIC достаточно для идентификации пакетов закрываемого соединения. От остальных состояний конечная точка может отказаться и обработка полученных кадров от неё не требуется. Конечная точка может сохранять ключи защиты для входящих пакетов, чтобы прочесть и обработать кадр CONNECTION_CLOSE. Конечная точка может отбросить ключи защиты пакетов при переходе в состояние закрытия и передавать пакет с кадром CONNECTION_CLOSE в ответ на любую принятую дейтаграмму UDP. Однако, отбросив ключи защиты пакетов, конечная точка не сможет идентифицировать и отбросить недействительные пакеты. Для предотвращения атак с усилением такая конечная точка должна ограничивать общий размер передаваемых пакетов троекратным размером полученных пакетов, которые связаны с соединением. Для минимизации числа поддерживаемых состояний при закрытии соединения конечная точка может передавать один и тот же пакет в ответ на все принятые пакеты.

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

Находясь в состоянии закрытия, конечная точка может получать пакеты с новым адресом отправителя, возможно говорящие о переносе соединения (см. раздел 9). Она должна отбрасывать пакеты с непроверенных адресов или ограничивать общий размер передаваемых откликов троекратным размером принятого пакета.

В состоянии закрытия от конечной точки не ожидается обработка обновления ключей (раздел 6 в [QUIC-TLS]). Обновление ключа может помешать конечной точке перейти из состояния закрытия в состояние сброса, поскольку она не сможет обработать полученные позднее пакеты, но иного влияния это не оказывает.

10.2.2. Состояние Draining

Конечная точка переходит в состояние сброса при получении кадра CONNECTION_CLOSE, который указывает закрытие или сброс соединения партнёром. Хотя в остальном оно аналогично состоянию закрытия, конечной точке недопустимо передавать в состоянии сброса какие-либо пакеты. Сохранение ключей защиты пакетов не требуется.

Получив кадр CONNECTION_CLOSE, конечная точка может передать 1 пакет с кадром CONNECTION_CLOSE до перехода в состояние сброса, используя при необходимости код NO_ERROR. Последующая передача пакетов конечной точкой недопустима, поскольку может приводить к безостановочному обмену кадрами CONNECTION_CLOSE, пока одна из конечных точек не выйдет из состояния закрытия.

Конечная точка может перейти в состояние сброса из состояния закрытия при получении кадра CONNECTION_CLOSE, указывающего, что партнёр находится в состоянии закрытия или сброса. В этом случае состояние сброса заканчивается в тот момент, когда завершилось бы состояние закрытия. Иными словами, конечная точка в состоянии сброса использует то же время окончания, но не передаёт каких-либо пакетов.

10.2.3. Немедленное закрытие в процессе согласования

Целью отправки кадра CONNECTION_CLOSE является его обработка партнёром. В общем случае это означает передачу кадра в пакете с высшим уровнем защиты для предотвращения отбрасывания пакета. После того, как согласование подтверждено (см. параграф 4.1.2 в [QUIC-TLS]), конечная точка должна передавать любые кадры CONNECTION_CLOSE в пакетах 1-RTT. Однако до завершения согласования ключи расширенной защиты пакетов могут быть недоступны, поэтому другой кадр CONNECTION_CLOSE может быть передан в пакете с меньшей защитой.

  • Клиент всегда знает о наличии у сервера ключей Handshake (см. параграф 17.2.2.1), но сервер может не знать о наличии таких ключей у клиента. При таких обстоятельствах серверу следует передавать кадр CONNECTION_CLOSE в обоих пакетах Handshake и Initial, чтобы клиент мог обработать хотя бы один из них.

  • Клиент, передающий CONNECTION_CLOSE в пакете 0-RTT, не может быть уверен в восприятии сервером пакетов 0-RTT. Отправка CONNECTION_CLOSE в пакете Initial повышает вероятность получения сервером сигнала закрытия даже при отсутствии кода ошибки от приложения.

  • До подтверждения согласования партнёр может быть не способен обрабатывать пакеты 1-RTT, поэтому конечной точке следует передавать CONNECTION_CLOSE в обоих пакетах Handshake и 1-RTT. Серверу также следует передавать кадр CONNECTION_CLOSE в пакете Initial.

Отправка CONNECTION_CLOSE типа 0x1d в пакете Initial или Handshake может раскрывать или изменять состояние приложения. Кадры CONNECTION_CLOSE типа 0x1d должны заменяться кадрами CONNECTION_CLOSE типа 0x1c при их отправке в пакете Initial или Handshake для предотвращения раскрытия статуса приложения. Конечные точки должны очищать поле Reason Phrase, а также им следует использовать код APPLICATION_ERROR при преобразовании CONNECTION_CLOSE типа 0x1c.

Кадры CONNECTION_CLOSE в пакетах разных типов могут быть объединены в одну дейтаграмму UDP (см. параграф 12.2).

Конечная точка может передать кадр CONNECTION_CLOSE в пакете Initial как отклик на неаутентифицированные данные в пакете Initial или Handshake. Такое незамедлительное закрытие может приводить к отказу в обслуживании легитимных соединений. Протокол QUIC не включает мер защиты от атак в пути в процессе согласования (см. параграф 21.2), однако за счёт снижения числа отзывов об ошибках некоторые формы атак на службы можно осложнить, если конечные точки отбрасывают нелегитимные пакеты вместо прерывания соединения с помощью CONNECTION_CLOSE. По этой причине конечные точки могут отбрасывать пакеты без аутентификации при обнаружении в них ошибок.

Конечная точка, не установившая состояние (например, сервер, обнаруживший ошибку в пакете Initial), не может перейти в состояние закрытия. Конечная точка, не имеющая состояния для соединения, не может задать время для состояния закрытия или сброса при отправке кадра CONNECTION_CLOSE.

10.3. Сброс без учёта состояния

Сброс без учёта состояния предоставляется в качестве крайней меры для конечной точки, не имеющей доступа к состоянию соединения. Отказ или остановка работы могут приводить к продолжению отправки данных партнёром. конечной точке, не способной продолжать соединение. Конечная точка может передать Stateless Reset в ответ на получение пакета, который она не может связать с активным соединением. Сброс без учёта состояния не подходит для индикации ошибок в активных соединениях. Конечная точка, желающая сообщить о критической ошибке, должна использовать кадр CONNECTION_CLOSE. Если это возможно.

Для поддержки процесса конечная точка выпускает маркер сброса без учёта состояния, который является трудно предсказуемым 16-байтовым значением. Если партнёр после этого получает Stateless Reset в форме дейтаграммы UDP, заканчивающейся маркером сброса, он будет незамедлительно прерывать соединение. Маркер сброса связан с идентификатором соединения и конечная точка вводит маркер, включая значение в поле Stateless Reset Token кадра NEW_CONNECTION_ID. Серверы также вводят при согласовании параметр транспорта stateless_reset_token, который применяется к идентификатору соединения, выбранному сервером при согласовании. Эти обмены защищены шифрованием, поэтому значение известно лишь клиенту и серверу. Клиент не может использовать транспортный параметр stateless_reset_token, поскольку для его транспортных параметров не обеспечивается конфиденциальность. Маркер аннулируется при удалении связанного с ним идентификатора соединения кадром RETIRE_CONNECTION_ID (параграф 19.16).

Конечная точка, получившая пакет, который она не способна обработать, передаёт пакет с показанной ниже схемой (см. параграф 1.3).

   Stateless Reset {
     Fixed Bits (2) = 1,
     Unpredictable Bits (38..),
     Stateless Reset Token (128),
   }

Рисунок 10. Сброс без учета состояния.


Это гарантирует, что пакет с Stateless Reset (насколько это возможно) не отличается от обычного пакета с коротким заголовком. Stateless Reset использует всю дейтаграмму UDP, начиная с первых двух битов заголовка пакета. Остаток первого байта и произвольное число байтов после него содержат значение, которому следует быть неотличимым от случайного. Последние 16 байтов дейтаграммы содержат маркер сброса без учёта состояния. Для всех объектов, кроме предусмотренного получателя, Stateless Reset будет выглядеть обычным пакетом с коротким заголовком. Чтобы пакет с Stateless Reset выглядел обычным пакетом QUIC, в поле Unpredictable Bits нужно включать не менее 38 битов данных (5 байтов без двух битов). Получаемый при этом минимальный размер в 21 байт не гарантирует, что Stateless Reset будет трудно отличить от других пакетов, если получатель требует использовать идентификатор соединения. Чтобы сделать пакет неотличимым, конечной точке следует обеспечить для всех передаваемых пакетов размер по меньшей мере на 22 байта больше минимального размера идентификатора соединения, запрошенного у партнёра для включения в пакеты, путём добавления кадров PADDING. Конечной точке, передающей Stateless Reset в ответ на пакет размером не более 43 байтов следует передавать Stateless Reset на 1 байт короче пакета, который вызвал сброс. Эти значения предполагают, что размер маркер сброса совпадает с размером минимального расширения пакетов при защите AEAD. Дополнительные непредсказуемые байты нужны в тех случаях, когда конечная точка может иметь согласованную схему защиты с большим увеличением размера пакета.

Конечное точке недопустимо передавать Stateless Reset с размером в 3 и более раз превышающим размер вызвавшего сброс пакета для предотвращения возможности использования этого для усиления атак. Дополнительные ограничения размера Stateless Reset приведены в параграфе 10.3.3.

Конечные точки должны отбрасывать пакеты, которые слишком малы для QUIC. Например, с набором функций AEAD, определенным в [QUIC-TLS], пакеты с коротким заголовком, размер которых меньше 21 байта, недействительны.

Конечные точки должны передавать Stateless Reset как пакеты с коротким заголовком. Однако конечные точки должны принимать любой пакет с корректным маркером сброса в конце как Stateless Reset, поскольку другие версии QUIC могут разрешать использование длинного заголовка.

Конечная точка может передать Stateless Reset в ответ на пакет с длинным заголовком. Отправка Stateless Reset не работает, пока у партнёра нет маркера сброса без учёта состояния. В данной версии QUIC пакеты с длинным заголовком применяются лишь при организации соединения. Поскольку маркер сброса не доступен, пока организация соединения не завершена, игнорирование неизвестных пакетов с длинным заголовком может быть так же эффективно, как отправка Stateless Reset.

Конечная точка не может определить Source Connection ID из короткого заголовка, поэтому она не может указать Destination Connection ID в Stateless Reset. Следовательно, Destination Connection ID будет отличаться от значения в предшествующих пакетах. Случайное значение Destination Connection ID представляет идентификатор соединения как результат переноса на другой идентификатор, представленный в кадре NEW_CONNECTION_ID (см. параграф 19.15). Применение случайного идентификатора соединения создаёт две проблемы, указанных ниже.

  • Пакет может не попасть к партнёру. Если поле Destination Connection ID важно для маршрутизации к партнёру, пакет может быть отправлен не туда. Это также может вызвать в ответ другой пакет Stateless Reset (см. параграф 10.3.3). При некорректной маршрутизации Stateless Reset не будет эффективным механизмом обнаружения ошибок и восстановления. В этом случае конечным точкам нужны иные методы (такие как таймеры) для обнаружения отказов в соединениях.

  • Случайный идентификатор соединения может использоваться сторонними объектами как индикатор возможного Stateless Reset. Конечная точка, использующая другие идентификаторы соединения, может внести ту или иную неопределённость.

Такой сброс без учёта состояния принят в QUIC версии 1. Конечной точке, которая может поддерживать несколько версий QUIC, потребуется генерировать Stateless Reset, которые будут восприняты партнёрами, поддерживающими любую версию, которую может (или могла до потери состояния) использовать конечная точка. Разработчики новых версий QUIC должны понимать это и (1) сохранять данную схему или (2) использовать для передачи данных часть пакета, отличную от последних 16 байтов.

10.3.1. Обнаружение Stateless Reset

Конечная точка обнаруживает Stateless Reset по последним 16 байтам дейтаграммы UDP, помня все маркеры сброса, связанные с идентификаторами соединения и удалёнными адресами для недавно отправленных дейтаграмм. Это включает значения поля Stateless Reset Token из кадров NEW_CONNECTION_ID и транспортных параметров сервера, но без маркеров сброса, связанных с идентификаторами соединения, которые не использовались или отозваны. Конечная точка сравнивает последние 16 байтов принятых дейтаграмм со всеми маркерами сброса для удалённого адреса, с которого получена дейтаграмма. Сравнение может выполняться для каждой принятой дейтаграммы. Конечная точка может пропустить эту проверку, если какой-либо пакет из дейтаграммы успешно обработан. Однако сравнение должно выполняться, если первый пакет во входящей дейтаграмме не удаётся связать с соединением или расшифровать. Конечной точке недопустимо проверять маркеры сброса, связанные с не использованным или отозванным идентификатором соединения.

При сравнении дейтаграммы с маркером сброса конечная точка должна выполнять операцию без утечки значения маркера. Например, сравнение в постоянный момент защищает значение отдельного маркера сброса от утечки информации через побочные каналы синхронизации. Другим подходом может служить сохранение и сравнение преобразованных значений маркеров вместо необработанных, где преобразование определяется как криптографическая псевдослучайная функция с использованием секретного ключа (например, блочный шифр или HMAC9 [RFC2104]). От конечной точки не ожидается защиты сведений о расшифровке пакета или числе действительных маркеров сброса.

Если 16 последних байтов дейтаграммы совпадают с маркером сброса, конечная точка должна ввести период сброса и не передавать пакетов через это соединение.

10.3.2. Расчёт маркера Stateless Reset

Маркер сброса без учёта состояния должен быть трудно предсказуемым. Конечная точка может генерировать случайный секрет [RANDOM] для каждого организуемого соединения, который применяется при создании маркеров сброса. Однако здесь возникает проблема координации при наличии кластера с несколькими экземплярами или проблема хранилища для конечной точки, которая может потерять состояние. Сброс без учёта состояния предназначен именно для случаев потери состояния, поэтому такой подход не будет оптимальным.

Можно использовать один статический ключ для всех соединений с одной конечной точкой, генерируя свидетельство (proof) с использованием псевдослучайной функции, принимающей на входе статический ключ и идентификатор соединения, выбранный конечной точкой (см. параграф 5.1). Конечная точка может использовать HMAC [RFC2104] (например, HMAC(static_key, connection_id)) или функцию вывода ключей на основе HMAC (HKDF10) [RFC5869] (например, используя статический ключ в качестве входного ключевого материала и идентификатор соединения как затравку – salt). Результат функции отсекается до 16 байтов для создания ключа сброса в соединении. Конечная точка, потерявшая состояние, может применять тот же метод для создания маркера сброса, беря идентификатор соединения из принятого пакета.

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

Обнаружение маркера сброса позволяет любому объекту разорвать соединение, поэтому значение маркера может применяться лишь один раз. Этот метод выбора маркера сброса без учёта состояния означает, что комбинацию статического ключа и маркера соединения недопустимо применять в другом соединении. Если использовать один идентификатор экземплярами, применяющими общий статический ключ, или атакующий может направить пакет экземпляру без состояния, знающему статический ключ, возможна организация DoS-атаки (см. параграф 21.11). Идентификатор соединения, сбрасываемого путём обнаружения маркера сброса, недопустимо снова применять в соединениях узлов, знающих общий статический ключ.

Один маркер сброса недопустимо использовать с несколькими идентификаторами соединения. Конечные точки не обязаны сравнивать новое значение со всеми прежними, но дубликаты могут трактоваться как ошибка соединения типа PROTOCOL_VIOLATION.

Отметим, что для Stateless Reset не обеспечивается криптографическая защита.

10.3.3. Зацикливание

Схема Stateless Reset такова, что без знания маркера пакеты сброса неотличимы от обычных пакетов. Например, если сервер передаст Stateless Reset другому серверу, он может получить в ответ Stateless Reset, что может приводить к бесконечному обмену. Конечная точка должна гарантировать, что передаваемый ею пакет Stateless Reset меньше вызвавшего отправку пакета, если у неё нет состояния, предотвращающего зацикливание. Такой подход ведёт к тому, что при возникновении петли пакеты в конечном итоге станут слишком мелкими, чтобы вызвать ответ.

Конечная точка может запоминать число переданных Stateless Reset и прекращать генерацию по достижении заданного предела. Использование независимых ограничений для каждого удалённого адреса обеспечивает возможность использовать Stateless Reset для закрытия соединения, когда партнёр или соединение уже исчерпали свои попытки сброса.

Stateless Reset размером меньше 41 байта может быть идентифицирован сторонним наблюдателем как пакет сброса, в зависимости от размера партнерского идентификатора соединения. И наоборот, отказ от передачи Stateless Reset в ответ на мелкий пакет может приводить к тому, что Stateless Reset станет бесполезным для обнаружения оборванных соединений, где передаются лишь мелкие пакеты. Такие отказы можно обнаруживать лишь иными средствами, такими как таймеры.

11. Обработка ошибок

Обнаружившей ошибку конечной точке следует сообщить об этом партнёру. На соединение в целом могут влиять ошибки как транспортного, так и прикладного уровня (см. параграф 11.1). В одном потоке могут изолироваться лишь ошибки на уровне приложения (см. параграф 11.2).

В указывающий ошибку кадр следует включать наиболее подходящий код ошибки (раздел 20). Если эта спецификация указывает условия ошибки, задаётся и код, который следует передавать. Хотя это и задано в форме требования, разные стратегии реализации могут приводить к разным сообщениям об ошибке. В частности, конечная точка может использовать любой применимый код ошибки, когда она видит условия ошибки. Вместо конкретного кода всегда можно использовать базовый код ошибки, например, PROTOCOL_VIOLATION или INTERNAL_ERROR.

Сброс без учёта состояния (параграф 10.3) не подходит для ошибок, которые можно указать в кадре CONNECTION_CLOSE или RESET_STREAM. Сброс без учёта состояния недопустимо применять конечной точке, имеющей состояние, которое требует отправки кадра в соединение.

11.1. Ошибки соединения

Ошибки, делающие невозможным использование соединения (например, очевидное нарушение семантики протокола или повреждение состояния, влияющее на все соединение), должны указываться кадром CONNECTION_CLOSE (параграф 19.19).

Относящиеся к приложению ошибки протокола указываются в кадре CONNECTION_CLOSE типа 0x1d, ошибки связанные с транспортом, включая описанные в этом документе, – в кадре CONNECTION_CLOSE типа 0x1c.

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

Поскольку AEAD для пакетов Initial не обеспечивает строгой аутентификации, конечная точка может отбросить недействительный пакет Initial. Такое отбрасывание разрешено даже при иной трактовке спецификацией ошибок соединения. Конечная точка может отбросить пакет лишь в том случае, когда она не обрабатывает кадры из него или не отменяет результат обработки. Отбрасывание недействительных пакетов Initial может служить для снижения риска DoS-атак (см. параграф 21.2).

11.2. Ошибки потока

Если ошибка на уровне приложения затрагивает один поток, а состояние соединения может быть восстановлено, конечная точка может передать кадр RESET_STREAM (параграф 19.4) с подходящим кодом ошибки для сброса потока. Сброс потока без участия протокола приложения может приводить к невосстанавливаемому состоянию прикладного протокола. Отправка RESET_STREAM должна вызываться лишь протоколом приложения, использующего QUIC. Семантика кода ошибки приложения в RESET_STREAM определяется прикладным протоколом и только он может вызвать прерывание потока. Локальный экземпляр прикладного протокола применяет прямой вызов API, а удалённый использует кадр STOP_SENDING, который автоматически ведёт к отправке RESET_STREAM.

Прикладному протоколу следует задавать правила обработки потоков преждевременно прерываемых конечными точками.

12. Пакеты и кадры

Конечные точки QUIC обмениваются пакетами, для который обеспечивается защита целостности и конфиденциальности (см. параграф 12.1). Пакеты передаются в дейтаграммах UDP (см. параграф 12.2).

Эта версия QUIC использует в пакетах длинный заголовок в процессе организации соединения (см. параграф 17.2). К таким пакетам относятся Initial (параграф 17.2.2), 0-RTT (параграф 17.2.3), Handshake (параграф 17.2.4), Retry (параграф 17.2.5). Для согласования версии используются независимые от версии пакеты с длинным заголовком (см. параграф 17.2.1).

Для минимизации издержек используются пакеты с коротким заголовком, которые передаются после организации соединения, когда доступны ключи 1-RTT (см. параграф 17.3).

12.1. Защищённые пакеты

Уровень криптографической защиты пакетов QUIC зависит от типа пакета. Детали защиты пакетов описаны в [QUIC-TLS], а в этом параграфе представлен обзор предоставляемой защиты.

Для пакетов согласования версии криптографическая защита не применяется (см. [QUIC-INVARIANTS]), пакеты Retry используют функцию AEAD [AEAD] для защиты от случайного изменения. Для пакетов Initial применяется защита AEAD с ключами, выводимыми из значения, доступного в линии, поэтому защита этих пакетов не эффективна и фактически у них нет защиты конфиденциальности. Защита пакетов Initial служит для гарантии того, что отправитель пакета присутствует в сетевом пути. Любой объект, получивший пакет Initial от клиента, может восстановить ключи, которые позволят ему прочитать содержимое пакета и создать пакеты Initial, которые будут аутентифицированы другой конечной точкой. AEAD также защищает пакеты Initial от непреднамеренных изменений.

Все остальные пакеты защищаются с использованием ключей, выведенных из криптографического согласования, которое обеспечивает получение соответствующих ключей для пакетов Handshake, 0-RTT и 1-RTT лишь взаимодействующими конечными точками.

Поле Packet Number в некоторых типах пакетов обеспечивает дополнительную защиту конфиденциальности, применяемую как часть защиты заголовка (см. параграф 5.4 в [QUIC-TLS]). Номер увеличивается для каждого пакета, переданного в данном пространстве номеров (см. параграф 12.3).

12.2. Объединение пакетов

Пакеты Initial (параграф 17.2.2), 0-RTT (параграф 17.2.3), Handshake (параграф 17.2.4) содержат поле Length, указывающее конец пакета. Размер учитывает поля Packet Number и Payload, для которых используется защита конфиденциальности и начальный размер не известен. Размер поля Payload определяется после снятия защиты заголовка.

Используя поле Length, отправитель может объединить несколько пакетов QUIC в одну дейтаграмму UDP. Это позволяет снизить число дейтаграмм UDP, требуемых для криптографического согласования и начала передачи данных, а также может применяться для создания зондов PMTU11 (см. параграф 14.4.1). Получатели должны быть способны обрабатывать сборные пакеты.

Объединение пакетов в порядке роста уровня шифрования (Initial, 0-RTT, Handshake, 1-RTT, см. параграф 4.1.4 в [QUIC-TLS]) повышает вероятность обработки получателем всех пакетов за один проход. Пакет с коротким заголовком не включает поля размера, поэтому он может быть лишь последним в дейтаграмме UDP. Конечной точке следует включать несколько кадров в один пакет, если их нужно отправить с одним уровнем шифрования, вместо объединения нескольких пакетов с одним уровнем шифрования.

Получатели могут маршрутизировать информацию на основе первого пакета в дейтаграмме UDP. Отправителям недопустимо объединять пакеты QUIC с разными идентификаторами соединения в одну дейтаграмму UDP. Получателям следует игнорировать любые последующие пакеты с полем Destination Connection ID отличным от указанного в первом пакете дейтаграммы.

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

Пакеты Retry (параграф 17.2.5), Version Negotiation (параграф 17.2.1) и пакеты с коротким заголовком (параграф 17.3) не включают поля Length, поэтому в дейтаграмме UDP за ними не могут следовать другие пакеты. Отметим также, что пакеты Retry или Version Negotiation никогда не объединяются с другими пакетами.

12.3. Номера пакетов

Номер пакета является целым числом от 0 до 262-1. Номера используются при определении криптографических значений nonce для защиты пакетов. Каждая конечная точка поддерживает раздельную нумерацию для принимаемых и передаваемых пакетов. Диапазон номеров пакетов ограничен для того, чтобы их можно было представит целиком в поле Largest Acknowledged кадра ACK (параграф 19.3). Однако при указании в длинном или коротком заголовке номера пакетов занимают от 1 до 4 байтов (см. параграф 17.1).

Пакеты Version Negotiation (параграф 17.2.1) и Retry (параграф 17.2.5) не включают порядкового номера.

Номера пакетов берутся из трёх пространств QUIC:

Пространство Initial

Номера для всех пакетов Initial (параграф 17.2.2).

Пространство Handshake

Номера для всех пакетов Handshake (параграф 17.2.4).

Пространство данных приложения

Номера для всех пакетов 0-RTT (параграф 17.2.3) и 1-RTT (параграф 17.3.1).

Как указано в [QUIC-TLS], для каждого типа пакетов применяются свои ключи защиты. Концептуально пространство номеров пакетов является контекстом, где пакеты обрабатываются и подтверждаются. Пакеты Initial могут передаваться лишь с ключами защиты пакетов Initial и подтверждаются также в пакетах Initial. Аналогично пакеты Handshake передаются с уровнем шифрования Handshake и подтверждаются лишь в пакетах Handshake. Это обеспечивает криптографическое разделение между пакетами из разных пространств номеров. Номера пакетов в каждом пространстве начинаются с 0 и в каждом следующем пакете из того же пространства номер должен увеличиваться по меньшей мере на 1.

Данные 0-RTT и 1-RTT передаются в одном пространстве номеров для упрощения реализации механизмов восстановления при потере пакетов для этих двух типов.

Конечной точке QUIC недопустимо в одном соединении повторно использовать номера из того же пространства. Если номер передаваемого пакета достигает значения 262-1, отправитель должен закрыть соединение без отправки кадра CONNECTION_CLOSE и каких-либо дальнейших пакетов. Конечная точка может передать Stateless Reset (параграф 10.3) при получении дополнительных пакетов.

Получатель должен отбрасывать новый незащищённый пакет, если он не уверен, что не обработал другой пакет с тем же номером из этого же пространства. Подавление дубликатов должно выполняться после снятия защиты пакетов по причинам, указанным в параграфе 9.5 [QUIC-TLS].

Конечные точки, отслеживающие каждый отдельный пакет в поиске дубликатов, подвержены риску накопления избыточных состояний. Данные, требуемые для обнаружения дубликатов, можно ограничить, поддерживая минимальный номер для незамедлительного отбрасывания всех пакетов с меньшим номером. Минимум должен учитывать значительные вариации времени кругового обхода, которые включают возможность зондирования партнёром. путей через сеть с большими значениями времени кругового обхода (см. раздел 9).

Кодирование порядковых номеров отправителем и декодирование их получателем описаны в параграфе 17.1.

12.4. Кадры и их типы

   Packet Payload {
     Frame (8..) ...,
   }

Рисунок 11. Данные QUIC.


Данные (payload) в пакетах QUIC после снятия защиты состоят из последовательности полных кадров, как показано на рисунке 11. Пакеты Version Negotiation, Stateless Reset, Retry не содержат в себе кадров.

Данные пакетов, содержащих кадры, должны включать по меньшей мере 1 кадр и могут содержать несколько кадров разных типов. Конечная точка должна считать приём пакета без кадров ошибкой соединения PROTOCOL_VIOLATION. Кадр всегда помещается в один пакет QUIC и не может размещаться в нескольких пакетах. Каждый кадр начинается с поля Frame Type, указывающего тип кадра, за которым могут следовать другие поля, определяемые типом.

   Frame {
     Frame Type (i),
     Type-Dependent Fields (..),
   }

Рисунок 12. Базовая схема кадра.


В таблице 3 приведён список кадров, определённых в этой спецификации, и краткие сведения о них. Более подробные описания приведены ниже.

Таблица 3. Типы кадров.

Идентификатор типа

Имя типа

Определение

Пакеты

Spec

0x00

PADDING

Параграф 19.1

IH01

NP

0x01

PING

Параграф 19.2

IH01

0x02-0x03

ACK

Параграф 19.3

IH_1

NC

0x04

RESET_STREAM

Параграф 19.4

__01

0x05

STOP_SENDING

Параграф 19.5

__01

0x06

CRYPTO

Параграф 19.6

IH_1

0x07

NEW_TOKEN

Параграф 19.7

___1

0x08-0x0f

STREAM

Параграф 19.8

__01

FF

0x10

MAX_DATA

Параграф 19.9

__01

0x11

MAX_STREAM_DATA

Параграф 19.10

__01

0x12-0x13

MAX_STREAMS

Параграф 19.11

__01

0x14

DATA_BLOCKED

Параграф 19.12

__01

0x15

STREAM_DATA_BLOCKED

Параграф 19.13

__01

0x16-0x17

STREAMS_BLOCKED

Параграф 19.14

__01

0x18

NEW_CONNECTION_ID

Параграф 19.15

__01

PP

0x19

RETIRE_CONNECTION_ID

Параграф 19.16

__01

0x1a

PATH_CHALLENGE

Параграф 19.17

__01

P

0x1b

PATH_RESPONSE

Параграф 19.18

___1

P

0x1c-0x1d

CONNECTION_CLOSE

Параграф 19.19

ih01

NN

0x1e

HANDSHAKE_DONE

Параграф 19.20

___1

Формат и семантика кадров описаны в разделе 19, а в оставшейся части параграфа рассмотрены важные и базовые свойства кадров.

Поле Frame Type в кадрах ACK, STREAM, MAX_STREAMS, STREAMS_BLOCKED, CONNECTION_CLOSE служит для передачи зависимых от кадра флагов. Для других кадров поле Frame Type просто указывает тип.

Столбец «Пакеты» в таблице 3 указывает типы пакетов, в которых может появляться кадр каждого типа.

I

Initial (параграф 17.2.2).

H

Handshake (параграф 17.2.4).

0

0-RTT (параграф 17.2.3).

1

1-RTT (параграф 17.3.1).

ih

Только кадр CONNECTION_CLOSE типа 0x1c может присутствовать в пакетах Initial и Handshake.

Дополнительные сведения об этих ограничениях приведены в параграфе 12.5. Отметим, что в пакетах 1-RTT могут присутствовать все типы кадров. Конечная точка должна считать получение кадра в пакете, для которого кадр не разрешён, ошибкой соединения типа PROTOCOL_VIOLATION.

В столбце Spec таблицы 3 указаны специальные правила генерации и обработки кадра.

N

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

C

Пакеты, содержащие лишь кадры с этой маркировкой, не учитываются как находящиеся в пути байты для контроля перегрузок (см. [QUIC-RECOVERY]).

P

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

F

Содержимое кадров с этой маркировкой контролируется управлением потоком данных (см. раздел 4).

Столбцы «Пакеты» и Spec в таблице 3 не являются частью реестра IANA (см. параграф 22.4).

Конечная точка должна считать получение кадра неизвестного типа ошибкой соединения типа FRAME_ENCODING_ERROR.

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

Поле Frame Type использует кодирование целых чисел переменного размера (раздел 16) с одним исключением. Для обеспечения простой и эффективной реализации синтаксического анализа кадров тип кадра должен кодироваться максимально кратко. Для определённых в этом документе типов кадров это означает однобайтовое представление, хотя их можно представить 2-, 4- или 8-байтовыми целыми числами переменного размера. Например, хотя 0x4001 является легитимным 2-байтовым представлением целого числа переменного размера со значением 1, кадры PING всегда представляются одним байтом со значением 0x01. Это правило применяется ко всем имеющимся и будущим типам кадров QUIC. Конечная точка может считать получение кадра с более длинным кодированием типа, чем требуется, ошибкой соединения типа PROTOCOL_VIOLATION.

12.5. Кадры и пространства номеров

Некоторые кадры запрещены в отдельных пространствах номеров. Приведённые здесь правила обобщают правила TLS в том смысле, что кадры, связанные с организацией соединения, обычно могут появляться в пакетах любого пространства номеров, тогда как связанные с передачей данных кадры могут присутствовать лишь в пакетах пространства номеров приложения.

  • Кадры PADDING, PING, CRYPTO могут включаться в кадры любого пространства номеров.

  • Кадры CONNECTION_CLOSE, сообщающие об ошибках уровня QUIC (тип 0x1c) могут присутствовать в пакетах любого пространства номеров. Кадры CONNECTION_CLOSE, сообщающие об ошибках приложения (тип 0x1d) должны включаться лишь в пакеты прикладного пространства номеров.

  • Кадры ACK могут появляться в пакетах любого пространства номеров, но могут подтверждать лишь пакеты из того же пространства. Однако (см. ниже) в пакеты 0-RTT нельзя включать кадры ACK.

  • Все остальные типы кадров должны передаваться лишь в пакетах прикладного пространства номеров.

Отметим, что по ряду причин в пакетах 0-RTT невозможно передавать кадры ACK, CRYPTO, HANDSHAKE_DONE, NEW_TOKEN, PATH_RESPONSE, RETIRE_CONNECTION_ID. Сервер может считать получение таких кадров в пакете 0-RTT ошибкой соединения типа PROTOCOL_VIOLATION.

1Internet Engineering Task Force.

2Internet Engineering Steering Group.

3Denial-of-service – отказ в обслуживании.

4Соединение считается бездействующим (idle), если оно ещё не создано или принимающая сторона находится в состоянии Recv, но ещё не получила кадров.

5Здесь и далее слова «сверх окончательного размера» означают данные со смещением равным или превышающим этот размер. Прим. перев.

6Application-Layer Protocol Negotiation – согласование протокола прикладного уровня.

7Explicit Congestion Notification – явное уведомление о перегрузке.

8Path Maximum Transmission Unit Discovery – определение MTU для пути.

9Hashed Message Authentication Code – код аутентификации хэшированного сообщения.

10HMAC-based Key Derivation Function.

11Path Maximum Transmission Unit – максимальный размер передаваемого блока для пути.


Часть 2

Please follow and like us:
Запись опубликована в рубрике RFC. Добавьте в закладки постоянную ссылку.

Добавить комментарий