Спецификация языка P4_16, версия 1.2.2

Спецификация языка P416, версия 1.2.2

The P416 Language Specification version 1.2.2

The P4 Language Consortium

2021-05-17

PDF

Аннотация

P4 — язык программирования для уровня данных сетевых устройств. В этом документе приведено точное определение языка P416, который является результатом пересмотра в 2016 г. языка P4 (http://p4.org). Документ предназначен для разработчиков, создающих компиляторы, имитаторы, среды разработки (IDE) и отладчики для программ P4. Документ может также быть интересен программистам P4, желающим более глубоко понять синтаксис и семантику языка.

1. Сфера применения

Эта спецификация задаёт структуру и интерпретацию программ на языке P416. Определения включают синтаксис, семантику и требования к соответствию для реализаций.

Документ не задаёт:

  • механизмы компиляции, загрузки и исполнения программ P4 в системах обработки пакетов;

  • механизмы передачи данных из одной системы обработки пакетов в другую;

  • механизмы, с помощью которых уровень управления поддерживает таблицы «совпадение-действие» и другие зависящие от состояния объекты, определённые программами P4;

  • размер и сложность программ P4;

  • минимальные требования к системам обработки пакетов, соответствующим спецификации.

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

2. Термины, определения, символы

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

Architecture — архитектура

Набор программируемых на P4 компонентов и интерфейсов уровня данных между ними.

Control plane — уровень (плоскость) управления

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

Data plane — уровень (плоскость) данных

Класс алгоритмов, описывающих преобразования пакетов в системах пакетной обработки.

Metadata — метаданные

Промежуточные данные, создаваемые в процессе выполнения программы P4.

Packet — пакет

Форматированный блок данных, передаваемый в сети с коммутацией пакетов.

Packet header — заголовок пакета

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

Packet payload — данные пакета

Данные, следующие после заголовков пакета.

Packet-processing system — система обработки пакетов

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

Target — целевая платформа (цель)

Система обработки пакетов, способная выполнять программы P4.

Термины, определённые в этом документе, не следует трактовать как косвенно связанные с ними термины других документов. И наоборот, не определённые здесь термины следует интерпретировать в соответствии с общепризнанными источниками, такими как IETF RFC.

3. Обзор

P4 представляет собой язык, описывающий обработку пакетов в плоскости данных программируемого элемента пересылки, такого как программный или аппаратный коммутатор, сетевой адаптер, маршрутизатор или специализированная сетевая платформа. Имя P4 возникло из названия статьи, где язык был предложен — «Programming Protocol-independent Packet Processors»1. Хотя P4 изначально был предназначен для программируемых коммутаторов, область его применения расширилась и сейчас охватывает широкий спектр устройств. В оставшейся части документа такие устройствами будут называться целевыми платформами или целями (target).


Рисунок 1. Традиционные и программируемые коммутаторы.

Многие платформы реализуют плоскости данных и управления. Язык P4 предназначен лишь для задания функциональности в плоскости данных. Программы P4 также частично определяют интерфейс взаимодействия между плоскостями данных и управления, но P4 нельзя использовать для описания функциональности плоскости управления целевой платформой. В оставшейся части документа P4 рассматривается как язык программирования платформы в понимании «программирования плоскости данных».

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

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

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

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

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

  • Типы заголовков, описывающие формат (набор и размеры полей) каждого заголовка в пакете.

  • Синтаксические анализаторы (parser) описывают разрешённые последовательности заголовков в принимаемых пакетах, идентификацию таких последовательностей, а также заголовки и поля для извлечения из пакетов.

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

  • Действия — фрагменты кода, описывающие манипуляции с полями пакета и метаданными. Действия могут включать данные, представленные плоскостью управления в процессе работы.

  • Блоки «сопоставление-действие» (СД), выполняющие ряд операций:

    • создание ключей поиска из полей пакета или рассчитанных метаданных;

    • поиск в таблицах по созданным ключам и выбор выполняемых действий (включая связанные данные);

    • выполнение выбранного действия.

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

  • Внешние объектызависимые от архитектуры конструкции, которыми могут манипулировать программы P4 через чётко определённые API, но внутреннее поведение которых задано жёстко (например, блоки контрольных сумм) и не программируется в P4.

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

  • Внутренние метаданные, обеспечиваемые архитектурой, связанной с каждым пакетом (например, входной порт, принявший пакет).


Рисунок 2. Программирование с использованием P4.

На рисунке 2 показан типовой процесс программирования целевой платформы с использованием P4.

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

Компиляция набора программ P4 создаёт:

  • конфигурацию плоскости данных, реализующую логику пересылки, описанную в программе;

  • API для управления состояниями объектов уровня данных из плоскости управления.

P4 является предметно-ориентированным языком, предназначенным для реализации на разных платформах, включая программируемые интерфейсные платы, FPGA, программные коммутаторы и микросхемы ASIC. Поэтому язык ограничен конструкциями, которые могут быть эффективно реализованы на всех таких платформах.

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

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

3.1. Преимущества P4

По сравнению с современными системами обработки пакетов (например, на основе микрокода в специализированном оборудовании) P4 обеспечивает ряд существенных преимуществ.

  • Гибкость. P4 позволяет выразить множество правил пересылки пакетов в форме программ в отличие от традиционных коммутаторов с фиксированными машинами пересылки.

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

  • Отображение ресурсов и управлением ими. Программы P4 описывают ресурсы хранения (например, адрес отправителя IPv4) абстрактно, компиляторы отображают заданные пользователем поля на доступные аппаратные ресурсы и управляют на нижнем уровне такими задачами, как распределение и планирование.

  • Разработка программ. Программы P4 предоставляют важные преимущества, такие как проверка типов, сокрытие информации, многократное использование программного кода.

  • Библиотеки компонент. Поставляемые производителями библиотеки могут использоваться для включения аппаратно-зависимых функций в переносимые конструкции высокого уровня на языке P4.

  • Независимое развитие программ и оборудования. Производители платформ могут применять абстрактную архитектуру для дальнейшего отвязывания низкоуровневых деталей архитектуры от обработки на высоких уровнях.

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

3.2. Развитие P4 (сравнение с P4 v1.0/v1.1)

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


Рисунок 3. Развитие языка P4.

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

В версии 1.1 языка P4 добавлена конструкция extern, которую можно применять для описания библиотечных элементов. Многие конструкции в спецификации v1.1 были преобразованы в библиотечные элементы (включая исключённые из языка конструкции, такие как счётчики и измерители). Ожидается, что некоторые из этих внешних объектов будут стандартизованы и включены потом в новый документ, описывающий библиотечные элементы P4. В этом документе рассматривается несколько примеров внешних конструкций. P416 также вводит и меняет некоторые языковые конструкции v1.1 для описания программируемых частей архитектуры (parser, state, control, package).

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

4. Архитектурная модель

Архитектура P4 идентифицирует программные блоки P4 (например, анализаторы, блоки входного и выходного управления потоком, сборщики и т. п.) и их интерфейсы плоскости данных. Архитектуру P4 можно рассматривать как соглашение между программой и целевой платформой. Поэтому каждый производитель должен обеспечить компилятор P4, а также соответствующее определение архитектуры для своей платформы (предполагается что компиляторы P4 могут иметь общий блок предварительной компиляции — front-end для всех вариантов архитектуры). Определение архитектуры не обязательно должно раскрывать всю программируемую часть плоскости данных и производитель даже может предоставить для своего устройства несколько определений с разными возможностями (например, с поддержкой и без поддержки групповой адресации).

На рисунке 4 показаны интерфейсы плоскости данных между программными блоками P4. Показана платформа с двумя программируемыми блоками (#1 и #2), каждый из которых программируется своим фрагментом кода P4. Интерфейсы платформы с программой P4 организованы через набор регистров управления или сигналов. Входные элементы управления предоставляют информацию программам P4 (например, порт, принявший пакет), а выходные могут быть созданы программами P4 для влияния на поведение платформы (например, выбор выходного порта). Регистры управления (сигналы) представляются в P4 как внутренние метаданные. Программы P4 могут также сохранять данные для каждого пакета и манипулировать ими в качестве пользовательских метаданных.


Рисунок 4. Программные интерфейсы P4.

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

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


Рисунок 5. Программа P4, вызывающая службы объекта с фиксированными функциями.

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

4.1. Стандартные архитектуры

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

4.2. Интерфейсы уровня данных

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

control MatchActionPipe<H>(in bit<4> inputPort,
				inout H parsedHeaders,
				out bit<4> outputPort);

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

  • Первым параметром является 4-битовое значение inputPort. Направление in показывает, что это входной параметр, который не может быть изменён в блоке.

  • Вторым параметром является объект типа H с именем parsedHeaders, где H — переменная типа, представляющая заголовки, которые будут далее определены программистом P4. Направление inout показывает, что параметр является сразу входным и выходным.

  • Третьим параметром является 4-битовое значение outputPort. Направление out указывает выходной параметр, начальное значение которого не определено, но параметр можно изменять.

4.3. Внешние объекты и функции

Программы P4 могут взаимодействовать с объектами и функциями, обеспечиваемыми архитектурой. Эти объекты описываются с помощью конструкции extern, задающей интерфейсы, открываемые таким объектом уровню данных.

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

extern Checksum16 {
	Checksum16();		// конструктор
	void clear();		// подготовка к расчёту
	void update<T>(in T data); // добавление данных в контрольную сумму
	void remove<T>(in T data); // исключение данных из контрольной суммы
	bit<16> get(); 	// получение контрольной суммы для данных, добавленных после
			// предшествующего сброса (clear)
}

5. Пример очень простого коммутатора

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


Рисунок 6. Архитектура очень простого коммутатора.

Эта архитектура названа VSS2 и показана на рисунке 6. В VSS нет ничего особенного — это просто учебный пример, показывающий, как можно описать и запрограммировать коммутатор в P4. VSS имеет множество фиксированных функциональных блоков (голубые прямоугольники), поведение которых описано в параграфе 5.2. Описание архитектуры VSS. Отмеченные белым прямоугольники программируются с использованием P4.

VSS принимает пакеты через один из 8 входных портов Ethernet, канал рециркуляции или порт, подключенный напрямую к CPU. VSS имеет один синтаксический анализатор в единственном конвейере СД, связанном с единственным сборщиком (deparser). После выхода из сборщика пакет передаётся в один из 8 выходных портов Ethernet или в один из трёх специальных портов:

  • CPU для передачи плоскости управления;

  • Drop в случае отбрасывания пакета;

  • Recirculate для повторного прохождения через коммутатор.

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

5.1. Архитектура VSS

Приведённая ниже программа P4 объявляет VSS, как это мог сделать производитель. Задано несколько типов, констант и 3 программируемых блока, описанных типами и реализованных программой коммутатора.

// Файл "very_simple_switch_model.p4"
// Объявление в VSS основной библиотеки P4 требуется
// для определений packet_in и packet_out.
# include <core.p4>
/* Объявления констант и структур */
/* Порты представляются 4-битовыми значениями */
typedef bit<4> PortId;
/* Имеется лишь 8 реальных портов */
const PortId REAL_PORT_COUNT = 4w8;	// 4w8 - 8 в 4-битовом формате
/* Метаданные, сопровождающие входной пакет */
struct InControl {
	PortId inputPort;
}
/* Специальные значения для входных портов */
const PortId RECIRCULATE_IN_PORT = 0xD;
const PortId CPU_IN_PORT = 0xE;
/* Метаданные, которые должны создаваться для выходных пакетов */
struct OutControl {
	PortId outputPort;
}
/* Специальные значения для выходных портов */
const PortId DROP_PORT = 0xF;
const PortId CPU_OUT_PORT = 0xE;
const PortId RECIRCULATE_OUT_PORT = 0xD;
/* Прототипы программируемых блоков */
/**
* Программируемый анализатор.
* @param <H> - тип заголовка, задаваемый пользователем
* @param b - входной пакет
* @param parsedHeaders - заголовки, созданные анализатором
*/
parser Parser<H>(packet_in b, out H parsedHeaders);
/**
* Конвейер «сопоставление-действие»
* @param <H> - тип входных и выходных заголовков
* @param headers - заголовки, полученные от анализатора и отправляемые сборщику
* @param parseError - ошибки, которые могут возникать при анализе
* @param inCtrl - информация от архитектуры, сопровождающая входной пакет
* @param outCtrl - информация для архитектуры, сопровождающая выходной пакет
*/
control Pipe<H>(inout H headers,
			in error parseError,	// ошибка анализатора
			in InControl inCtrl,	// входной порт
			out OutControl outCtrl); 	// выходной порт
/**
* Сборщик VSS.
* @param <H> - тип заголовков, задаваемый пользователем
* @param b - выходной пакет
* @param outputHeaders - заголовки для выходного пакета
*/
control Deparser<H>(inout H outputHeaders, packet_out b);
/**
* Объявление пакета верхнего уровня. Должен создаваться пользователем.
* Аргументы задают блоки, которые должен создать пользователь.
* @param <H> - заданный пользователем тип обрабатываемых заголовков.
*/
package VSS<H>(Parser<H> p,
			Pipe<H> map,
			Deparser<H> d);
// Зависимые от архитектуры объекты, которые могут создаваться.
// Блок контрольных сумм.
extern Checksum16 {
	Checksum16();			// конструктор
	void clear();			// подготовка к расчёту
	void update<T>(in T data);	// добавление данных в контрольную сумму
	void remove<T>(in T data);	// исключение данных из контрольной суммы
	bit<16> get(); 		// контрольная сумма для данных после clear
}

Рассмотрим некоторые из элементов.

  • Файл core.p4 (Приложение D. Основная библиотека P4) определяет стандартные типы данных и коды ошибок.

  • Тип bit<4> указывает строку из 4 битов.

  • Синтаксис 4w0xF указывает значение 15, представленное 4 битами. Другим вариантом записи является 4w15. Во многих случаях указатель размера можно опустить, просто написав 15.

  • Тип error является встроенным типом P4 для кодов ошибок.

Далее приведено объявление синтаксического анализатора

parser Parser<H>(packet_in b, out H parsedHeaders);

Это объявление описывает интерфейс анализатора, но не содержит его реализации, которую предоставляет программист. Анализатор читает данные из packet_in (предопределённый внешний объект P4 для представления входящего пакета, объявленный в библиотеке core.p4). Анализатор записывает свой вывод (ключевое слово out) в аргумент parsedHeaders. Тип этого аргумента H ещё не известен и будет задан программистом.

Объявление

control Pipe<H>(inout H headers,
		in error parseError,
		in InControl inCtrl,
		out OutControl outCtrl);

описывает интерфейс конвейера СД (Match-Action) с именем Pipe. Конвейер принимает на входе заголовки headers, параметр для ошибок parseError и данные управления inCtrl. На рисунке 6 показаны источники этих данных. Конвейер записывает свой вывод в outCtrl и должен обновить заголовки, передаваемые сборщику.

Пакет верхнего уровня называется VSS и для программирования VSS пользователь должен создать экземпляр пакета этого типа (см. ниже). Объявление пакета верхнего уровня зависит от типа переменной H

package VSS<H>

Переменная типа указывает тип, который ещё не известен и должен быть предоставлен пользователем позже. В данном случае H является типом набора заголовков, который пользовательская программа будет обрабатывать. Анализатор будет выдавать разобранное представления этих заголовков, а конвейер СД будет обновлять входные заголовки, заменяя их выходными.

Объявление пакета VSS включает три составных параметра типов Parser, Pipe и Deparser, которые являются объявлениями, описанными здесь. Для программирования платформы нужно представить значения этих параметров.

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

5.2. Описание архитектуры VSS

Для полного понимания поведения VSS и создания осмысленных программ P4 для неё, а также реализации плоскости управления нужно полностью описать блоки с фиксированной функциональностью. Ниже рассматривается простой пример, иллюстрирующий все детали, которые нужно учитывать при описании архитектуры. Язык P4 не предназначен для описания всех функциональных блоков — он может лишь описать взаимодействие между программируемыми блоками и архитектурой. Для текущей программы этот интерфейс задаётся объявлениями блоков Parser, Pipe и Deparser. На практике предполагается полное описание архитектуры в виде исполняемой программы и/или схем и текста. В этом документе приводится неформальное текстовое описание.

5.2.1. Блок арбитража

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

  • Приём пакета от одного из физических портов Ethernet, плоскости управления или порта рециркуляции.

  • Для пакетов из портов Ethernet рассчитывается и проверяется контрольная сумма трейлера. При несовпадении пакет отбрасывается, при совпадении контрольная сумма удаляется из данных пакета (payload).

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

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

  • После получения пакета блок арбитража устанавливает значение inCtrl.inputPort, являющееся входным для конвейера СД, и указывает принявший порт пакет. Физические порты Ethernet имеют номера от 0 до 7, порт рециркуляции — 13, а порт CPU — 14.

5.2.2. Блок выполнения синтаксического анализа

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

5.2.3. Блок демультиплексора

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

  • Отправка пакета в порт drop вызывает исчезновение пакета.

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

  • Отправка пакета в выходной порт CPU ведёт к передаче пакета плоскости управления. Процессору передаётся исходный полученный пакет, а не результат работы сборщика (тот просто отбрасывается).

  • Отправка пакета в выходной порт рециркуляции передаёт его во входной порт рециркуляции. Это полезно для пакетов, обработку которых невозможно выполнить за один проход.

  • Если пакет имеет некорректное значение outputPort (например, 9), он отбрасывается.

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

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

5.2.4. Доступные внешние блоки

Архитектура VSS включает внешний блок инкрементного расчёта контрольных сумм Checksum16, имеющий конструктор и 4 метода:

  • clear() готовит блок к новому расчёту;

  • update<T>(in T data) добавляет данные в расчёт контрольной суммы (данные должны быть строкой битов, заголовком или структурой с такими значениями), указанные поля добавляются (конкатенация) в порядке их задания в объявлении типа;

  • get() возвращает 16-битовую контрольную сумму с дополнением до 1, при вызове этой функции блок контрольных сумм должен получать целое число байтов данных;

  • remove<T>(in T data) удаляет из расчёта данные, которые раньше учитывались в контрольной сумме.

5.3. Полная программа VSS

Здесь представлена полна реализация программы P4 для базовой пересылки пакетов IPv4 на платформе VSS. Программа не использует все возможности архитектуры (например, рециркуляцию), по применяет директивы препроцессора #include (6.2. Предварительная обработка).

Синтаксический анализатор пытается распознать заголовок Ethernet, за которым следует заголовок IPv4. Если любой из этих заголовков отсутствует, анализ завершается ошибкой. В остальных случаях информация из заголовков извлекается в структуру Parsed_packet. Конвейер СД, показанный на рисунке 7, включает 4 блока СД (ключевое слово P4 table).

  • При возникновении ошибки в анализаторе пакет отбрасывается (outputPort = DROP_PORT).

  • Первая таблица использует адрес получателя IPv4 для определения outputPort и адреса IPv4 следующего узла пересылки. Если поиск не дал результата, пакет отбрасывается. Таблица также декрементирует IPv4 ttl.

  • Вторая таблица проверяет значение ttl и при обнаружении 0 передаёт пакет плоскости управления через порт CPU.

  • Третья таблица использует адрес IPv4 следующего интервала (результат первой таблицы) для определения Ethernet-адреса следующего интервала.

  • Последняя таблица использует outputPort для определения Ethernet-адреса (MAC) отправителя в текущем коммутаторе, который помещается в выходной пакет.


Рисунок 7. Схема конвейера СД, выраженного программой P4 VSS.

Сборщик создаёт выходной пакет, собирая новые заголовки Ethernet и IPv4 по результатам работы конвейера.

// Включение основной библиотеки P4
# include <core.p4>
// Включение объявлений архитектуры VSS.
# include "very_simple_switch_model.p4"
// Эта программа обрабатывает пакеты с заголовками Ethernet и IPv4,
// пересылая их по IP-адресу получателя.
typedef bit<48>	EthernetAddress;
typedef bit<32>	IPv4Address;
// Стандартный заголовок Ethernet
header Ethernet_h {
	EthernetAddress dstAddr;
	EthernetAddress srcAddr;
	bit<16>	etherType;
}
// заголовок IPv4 (без опций)
header IPv4_h {
	bit<4>		version;
	bit<4>		ihl;
	bit<8>		diffserv;
	bit<16>	totalLen;
	bit<16>	identification;
	bit<3>		flags;
	bit<13>	fragOffset;
	bit<8>		ttl;
	bit<8>		protocol;
	bit<16>	hdrChecksum;
	IPv4Address	srcAddr;
	IPv4Address	dstAddr;
}
// Структура проанализированных заголовков
struct Parsed_packet {
	Ethernet_h 	ethernet;
	IPv4_h		ip;
}
// Раздел анализатора
// Заданные пользователем ошибки, которые могут возникать при анализе
error {
	IPv4OptionsNotSupported,
	IPv4IncorrectVersion,
	IPv4ChecksumError
}
parser TopParser(packet_in b, out Parsed_packet p) {
Checksum16() ck;	// Создание экземпляра блока контрольных сумм
	state start {
		b.extract(p.ethernet);
		transition select(p.ethernet.etherType) {
			0x0800: parse_ipv4;
			// Нет принятого по умолчанию правила — все прочие пакеты отвергаются
		}
	}
	state parse_ipv4 {
		b.extract(p.ip);
		verify(p.ip.version == 4w4, error.IPv4IncorrectVersion);
		verify(p.ip.ihl == 4w5, error.IPv4OptionsNotSupported);
		ck.clear();
		ck.update(p.ip);
		// Проверка нулевого значения контрольной суммы
		verify(ck.get() == 16w0, error.IPv4ChecksumError);
		transition accept;
	}
}
// Раздел конвейера СД
control TopPipe(inout Parsed_packet headers,
			in error parseError, // ошибка анализатора
			in InControl inCtrl, // входной порт
			out OutControl outCtrl) {
	IPv4Address nextHop;	// локальная переменная
	/**
	* Указывает отбрасывание пакета установкой выходного порта DROP_PORT
	*/
	action Drop_action() {
		outCtrl.outputPort = DROP_PORT;
	}
	/**
	* Установка следующего интервала и выходного порта.
	* Декрементирование поля IPv4 ttl.
	* @param ivp4_dest - адрес IPv4 следующего интервала
	* @param port - выходной порт
	*/
	action Set_nhop(IPv4Address ipv4_dest, PortId port) {
		nextHop = ipv4_dest;
		headers.ip.ttl = headers.ip.ttl - 1;
		outCtrl.outputPort = port;
	}
	/**
	* Расчёт адреса следующего интервала IPv4 и выходного порта
	* на основе адреса получателя IPv4 в текущем пакете.
	* Декрементирование поля IPv4 TTL.
	* @param nextHop - адрес IPv4 следующего интервала
	*/
	table ipv4_match {
		key = { headers.ip.dstAddr: lpm; }	// самый длинный совпадающий префикс
		actions = {
			Drop_action;
			Set_nhop;
		}
		size = 1024;
		default_action = Drop_action;
	}
	/**
	* Передача пакета в порт CPU
	*/
	action Send_to_cpu() {
		outCtrl.outputPort = CPU_OUT_PORT;
	}
	/**
	* Проверка TTL и отправка в CPU при значении 0
	*/
	table check_ttl {
		key = { headers.ip.ttl: exact; }
		actions = { Send_to_cpu; NoAction; }
		const default_action = NoAction; // определено в core.p4
	}
	/**
	* Установка MAC-адреса получателя пакета
	* @param dmac - MAC-адрес получателя.
	*/
	action Set_dmac(EthernetAddress dmac) {
		headers.ethernet.dstAddr = dmac;
	}
	/**
	* Установка адреса Ethernet получателя пакета
	* по IP-адресу следующего интервала.
	* @param nextHop - адрес IPv4 следующего интервала.
	*/
	table dmac {
		key = { nextHop: exact; }
		actions = {
			Drop_action;
			Set_dmac;
		}
		size = 1024;
		default_action = Drop_action;
	}
	/**
	* Установка MAC-адреса отправителя.
	* @param smac - MAC-адрес отправителя
	*/
	action Set_smac(EthernetAddress smac) {
		headers.ethernet.srcAddr = smac;
	}
	/**
	* Установка MAC-адреса отправителя по выходному порту.
	*/
	table smac {
		key = { outCtrl.outputPort: exact; }
		actions = {
			Drop_action;
			Set_smac;
		}
		size = 16;
		default_action = Drop_action;
	}
	apply {
		if (parseError != error.NoError) {
			Drop_action();	// вызов drop напрямую
			return;
		}
		ipv4_match.apply(); // Результатом совпадений будет переход к nextHop
		if (outCtrl.outputPort == DROP_PORT) return;
		check_ttl.apply();
		if (outCtrl.outputPort == CPU_OUT_PORT) return;
		dmac.apply();
		if (outCtrl.outputPort == DROP_PORT) return;
		smac.apply();
	}
}
// Раздел сборщика
control TopDeparser(inout Parsed_packet p, packet_out b) {
	Checksum16() ck;
	apply {
		b.emit(p.ethernet);
	if (p.ip.isValid()) {
		ck.clear();			// Подготовка блока контрольных сумм
		p.ip.hdrChecksum = 16w0; 	// Очистка контрольной суммы
		ck.update(p.ip);		// Расчёт новой контрольной суммы
		p.ip.hdrChecksum = ck.get();
	}
	b.emit(p.ip);
}
}
// Создание экземпляра пакета VSS.
VSS(TopParser(),
	TopPipe(),
	TopDeparser()) main;

6. Определение языка P4

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

  • Базовый язык, включающий типы, переменные, области действия, объявления, операторы, выражения и т. д.

  • Субязык для задания анализаторов на основе конечного автомата или машины состояний (12. Анализ пакета).

  • Субязык для выражения расчётов, используемых блоками СД, основанными на традиционной императивном потоке управления (13. Блоки управления).

  • Субязык описания архитектуры (16. Описание архитектуры).

6.1. Синтаксис и семантика

6.1.1. Грамматика

Полная грамматика P416 описана в Приложении H на основе языка описания грамматики Yacc/Bison, используемого и в данном тексте. В выдержках из грамматики принимается несколько стандартных допущений:

  • для обозначения терминальных символов применяются ЗАГЛАВНЫЕ буквы;

  • применяется нотация BNF, как показано ниже

p4program
	: /* пусто */
	| p4program declaration
	| p4program ';'
	;

Псевдокод, применяемый в основном для описания семантики конструкций P4, выводится фиксированным шрифтом

ParserModel.verify(bool condition, error err) {
	if (condition == false) {
		ParserModel.parserError = err;
		goto reject;
	}
}

6.1.2. Семантика и абстрактные машины P4

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

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

  • поведение операций ввода и вывода всех блоков P4;

  • состояния, поддерживаемые внешними (extern) блоками.

6.2. Предварительная обработка

Для сборки программ из нескольких исходных файлов P4 компиляторам следует поддерживать некоторые функции препроцессоров C:

  • #define для определения макросов (без аргументов);

  • #undef;

  • #if #else #endif #ifdef #ifndef #elif;

  • #include.

Препроцессору также следует удалять символы \ и перевода строки (ASCII 92, 10), используемые для разбиения строк с целью удобочитаемости.

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

# include <system_file>
# include "user_file"

Разница заключается в порядке поиска файлов препроцессором при неполном указании пути.

Компиляторам P4 следует корректно обрабатывать директивы #line, которые могут генерироваться в процессе предварительной обработки. Это позволяет собирать программы P4 из множества файлов:

  • базовая библиотека P4, определённая в этом документе;

  • архитектура, определяющая интерфейсы плоскости данных и блоки extern;

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

  • программы P4, задающие поведение каждого программируемого блока.

6.2.1. Основная библиотека P4

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

# include <core.p4>

6.3. Лексические конструкции

Все ключевые слова P4 содержат только символы ASCII, это же должно выполняться для всех идентификаторов P4. Компиляторам P4 следует корректно обрабатывать строки, содержащие 8-битовые символы в комментариях и строковых литералах. Язык P4 различает регистр символов. Пробельные символы, включая новую строку, считаются разделителями. Отступ от начала строки не регламентируется, однако P4 включает блочные конструкции в стиле C во всех примерах этого документа используются отступы в стиле C. Символы табуляции трактуются как пробелы.

Лексер распознает перечисленные ниже терминалы.

  • Идентификатор (IDENTIFIER) начинается с буквы или символа подчёркивания и может включать буквы, цифры и символы подчёркивания.

  • Идентификатор типа (TYPE_IDENTIFIER) указывает имя типа.

  • INTEGER означает целочисленные литералы.

  • DONTCARE — одиночный символ подчёркивания.

  • Ключевые слова (например, RETURN). По соглашению каждый терминал ключевого слова соответствует ключевому слову языка с таким же произношением, но в символах нижнего регистра. Например, терминал RETURN соответствует ключевому слову return.

6.3.1. Идентификаторы

Идентификаторы P4 могут включать лишь буквы, цифры и символы подчёркивания, а начинаться должны с буквы или подчёркивания. Специальный идентификатор _ зарезервирован для значения, которое «не имеет значения» (don’t care), а его тип может зависеть от контекста. Некоторые ключевые слова (например, apply) могут использоваться как идентификаторы, если контекст не позволяет путаницы.

nonTypeName
	: IDENTIFIER
	| APPLY
	| KEY
	| ACTIONS
	| STATE
	| ENTRIES
	| TYPE
	;

name
	:|;
	nonTypeName
	TYPE_IDENTIFIER

6.3.2. Комментарии

P4 поддерживает несколько типов комментариев:

  • однострочный комментарий от символов // до конца строки;

  • многострочный комментарий между символами /* и */, вложенные многострочные комментарии не поддерживаются;

  • комментарии в стиле Javadoc между символами /** и */.

Настоятельно не рекомендуется применять комментарии Javadoc в таблицах и действиях, используемых при создании интерфейса с плоскостью управления.

P4 считает комментарии разделителями и не допускает комментариев внутри маркера (token). Например, bi/**/t будет рассматриваться как два маркера bi и t, а не bit.

6.3.3. Литеральные константы

6.3.3.1. Логические литералы

Для логических (Boolean) значений поддерживаются константы true и false.

6.3.3.2. Целочисленные литералы

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

  • 0x или 0X — шестнадцатеричные значения;

  • 0o или 0O — восьмеричные значения;

  • 0d или 0D — десятичные значения;

  • 0b или 0B — двоичные значения.

Размер числового литерала в битах можно задать целым числом без знака с индикатором знака:

  • w — целое число без знака;

  • s — целое число со знаком.

Отметим, что 0 в начале сам по себе не указывает восьмеричную константу. Символ _ допускается в числовых литералах, но игнорируется при определении значения анализируемого числа. Это позволяет сделать длинные числовые константы более читаемыми. Этот символ не допускается в константах указания размера и не может быть первым символом числового литерала. Внутри литералов не допускаются комментарии и пробелы.

32w255			// 32-битовое число без знака со значением 255
32w0d255		// то же самое
32w0xFF		// то же самое
32s0xFF		// 32-битовое число со знаком и значением 255
8w0b10101010		// 8-битовое число без знака со значением 0xAA
8w0b_1010_1010	// то же самое
8w170			// то же самое
8s0b1010_1010		// 8-битовое число со знаком и значением -86
16w0377		// 16-битовое число без знака со значением 377 (не 255!)
16w0o377		// 16-битовое число без знака со значением 255 (основание 8)
6.3.3.3. Строковые литералы

Строковые литералы (строки констант) задаются в форме произвольных последовательностей 8-битовых символов, заключённых в двойные кавычки («, ASCII 34). Строка начинается с символа двойных кавычек и завершается на первом символе двойных кавычек, которому не предшествует нечётное число символов \ (ASCII 92). P4 не проверяет корректность строк (т. е., допустимость использованной кодировки UTF-8).

Поскольку в P4 не поддерживаются операции над строками, строковые литералы, включая завершающие кавычки, обычно пропускаются компилятором P4 без изменений другим сторонним инструментам или backend-компиляторам. Эти инструменты могут по-своему обрабатывать escape-последовательности (например, способ задания символов Unicode или обработку непечатаемых символов ASCII).

Ниже приведено 3 примера строковых литералов.

"simple string"
"string \" with \" embedded \" quotes"
"string with embedded
line terminator"

6.4. Соглашения об именовании

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

Ниже приведены принятые в документе соглашения об именовании.

  • Встроенные типы указываются символами нижнего регистра (например, int<20>).

  • Пользовательские типы включают заглавные буквы (например, IPv4Address).

  • Переменные типов всегда указываются заглавными буквами (например, parser P<H, IH>()).

  • В переменных заглавные буквы не используются (например, ipv4header).

  • Константы указываются заглавными буквами (например CPU_PORT).

  • Ошибки и перечисляемые указываются в стиле «верблюда» (camel-case), например PacketTooShort.

6.5. Программы P4

Программа P4 представляет собой список объявлений

p4program
	: /* пусто */
	| p4program declaration
	| p4program ';'	/* пустое объявление */
	;
declaration
	: constantDeclaration
	| externDeclaration
	| actionDeclaration
	| parserDeclaration
	| typeDeclaration
	| controlDeclaration
	| instantiation
	| errorDeclaration
	| matchKindDeclaration
	| functionDeclaration
	;

Пустое объявление указывается символом ; (пустые объявления поддерживаются с учётом привычек программистов C/C++ и Java, хотя в некоторых конструкциях, например, struct, точка с запятой в конце не требуется).

6.5.1. Область действия

Некоторые конструкции P4 действуют как пространства имён, создающие локальную область действия имён, включая:

  • объявления производных типов (struct, header, header_union, enum) с локальной значимостью имён полей;

  • операторы блоков, создающие локальные, лексически замкнутые области действия;

  • блоки parser, table, action, control с локальной областью действия;

  • объявления с переменными типов, создающими для переменных новые области действия; например, в приведённом ниже объявлении extern область действия типа H завершается в конце определения

extern E<H>(/* параметры опущены */) {/* тело опущено */} // область действия H кончается тут.

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

6.5.2. Элементы с состоянием

Большинство конструкций P4 не имеет состояний — результат работы конструкции определяется исключительно входными данными. Имеется лишь две конструкции с состояниями, сохраняющими информацию от пакета к пакету:

  • таблицы для плоскости данных доступны лишь на чтение, но их записи может менять уровень управления;

  • внешние объекты могут иметь состояния, доступные для чтения и записи плоскостям управления и данных; все конструкции из P414, сохраняющие состояние (например, счётчики, измерители, регистры), представлены в P416 объектами extern.

В P4 все элементы с состояниями должны явно выделяться при компиляции путём создания «экземпляров». Кроме того, анализаторы, блоки управления и пакеты могут создавать экземпляры элементов с состояниями. Такие элементы также должны создаваться до использования, даже если они исходно не имеют состояний. Однако таблицы не создаются заранее, хотя у них и есть состояния, — создание экземпляра таблицы происходит при её объявлении. Это сделано для поддержки общего случая, поскольку большинство таблиц используется лишь однократно. Для более точного контроля за состоянием таблиц программистам следует объявлять их в элементах управления.

В примере параграфа 5.3. Полная программа VSS TopParser, TopPipe, TopDeparser, Checksum16 и Switch являются типами. Имеется два экземпляра Checksum16, по одному в TopParser и TopDeparser (обозначены ck). Экземпляры TopParser, TopDeparser, TopPipe и Switch создаются в конце программы в объявлении основного объекта, который является экземпляром типа Switch (пакет).

6.6. Выражения для левой части

Выражениями для левой части (l-value) считаются выражения слева от оператора присваивания или аргументы параметров функций out и inout. Эти значения являются ссылками на хранилище. Корректные варианты приведены ниже.

prefixedNonTypeName
	: nonTypeName
	| dotPrefix nonTypeName
	;
lvalue
	: prefixedNonTypeName
	| lvalue '.' member
	| lvalue '[' expression ']'
	| lvalue '[' expression ':' expression ']'
	;
  • Идентификаторы базовых и производных типов.

  • Операции доступа к элементам структур, заголовков и объединений заголовков (нотация с точками).

  • Ссылки на элементы стека заголовков (8.17. Операции над стеком заголовков) — индексация и ссылки на последний или следующий элемент.

  • Результат оператора «нарезки» битов [m:l].

Примером корректного выражения может служить headers.stack[4].field. Отметим, что вызовы методов и функций не могут возвращать l-value.

6.7. Соглашения о вызовах

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

  • используются именованные и типизованные параметры;

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

  • можно передавать аргументы путём привязки их к параметрам.

Вызовы осуществляются с использованием семантики copy-in/copy-out. Каждый параметр помечается направлением.

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

  • Параметры out за исключением нескольких указанных ниже случаев, инициализируются и трактуются как l-value (6.6. Выражения для левой части) в теле методов и функций. Аргументы, передаваемые как параметры out, должны быть l-value, после выполнения вызова значение параметра копируется в соответствующее место хранилища, выделенное для данного l-value.

  • Параметры inout являются входными и выходными сразу (in и out). Аргументы, передаваемые как параметры inout должны быть l-value.

  • Отсутствие направления указывает, что параметр соответствует какому-либо из приведённых условий:

    • значение известно в момент компиляции;

    • значение является параметром действия (action), который может быть установлен лишь плоскостью управления;

    • значение является параметром действия, который может быть напрямую установлен другим вызовом (в этом случае поведение аналогично параметрам in).

Параметры out всегда инициализируются в начале выполнения части программы, имеющей такие параметры (например, элемента управления, анализатора, действия, функции и т. п.). Для других направлений такой инициализации нет.

  • Если параметр out имеет тип header или header_union, он считается недействительным (invalid).

  • Если параметр out имеет тип стека заголовков, все элементы стека считаются недействительными (invalid), а в поле nextIndex устанавливается 0 (8.17. Операции над стеком заголовков).

  • Если параметр out имеет композитный тип (например, struct), отличающийся от перечисленных выше, правила применяются рекурсивно к элементам композитного типа.

  • Если параметр out имеет иной тип (например, bit<W>), реализация не обязана инициализировать его предсказуемым значением.

Например, если параметр out имеет тип s2_t и имя p

header h1_t {
	bit<8> f1;
	bit<8> f2;
}
struct s1_t {
	h1_t h1a;
	bit<3> a;
	bit<7> b;
}
struct s2_t {
	h1_t h1b;
	s1_t s1;
	bit<5> c;
}

тогда в начале выполнения части программы, имеющей выходной параметр p, он должен инициализироваться с объявлением p.h1b и p.s1.h1a недействительными. Остальные части p инициализировать не требуется. Аргументы оцениваются слева направо до вызова самой функции. Порядок оценки важен, когда представленное для аргумента выражение может давать побочные эффекты. Например,

extern void f(inout bit x, in bit y);
extern bit g(inout bit z);
bit a;
f(a, g(a));

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

  1. Аргументы оцениваются слева направо в соответствии с выражением при вызове функции.

  2. Если параметр имеет принятое по умолчанию значение и соответствующий аргумент не представлен, в качестве аргумента применяется подразумеваемое значение.

  3. Для каждого аргумента out и inout сохраняется соответствующее значение l-value (это не позволяет изменить его при оценке последующих аргументов). Это важно, если аргумент содержит операции индексирования в стек заголовков.

  4. Значения каждого аргумента сохраняется во временной области.

  5. Функция вызывается с аргументами из временной области. Эти аргументы никогда не являются псевдонимами друг друга, поэтому такой «сгенерированный» вызов функции можно реализовать с помощью ссылки (call-by-reference), если архитектура это позволяет.

  6. При возврате из функции временные значения, соответствующие аргументам out и inout копируются слева направо в l-value, сохранённые в п. 2.

В соответствии с этим алгоритмом приведённый выше вызов функции эквивалентен последовательности операторов

bit tmp1 = a;		// оценка a и сохранение результата
bit tmp2 = g(a);	// оценка g(a), сохранение результата, изменение a
f(tmp1, tmp2);		// оценка f, изменение tmp1
a = tmp1;		// копирование результата inout обратно в a

Для подчёркивания важности п. 2 приведённого выше алгоритма рассмотрим пример

header H { bit z; }
H[2] s;
f(s[a].z, g(a));

Оценка этого вызова эквивалента последовательности операторов

bit tmp1 = a;		// сохранение a
bit tmp2 = s[tmp1].z;	// оценка первого аргумента
bit tmp3 = g(a);	// оценка второго аргумента, изменение a
f(tmp2, tmp3);		// оценка f, изменение tmp2
s[tmp1].z = tmp2;	// копирование результата inout обратно, не в s[a].z

При использовании объектов extern в качестве аргументов их можно передавать лишь без направления (см., например, аргументы packet в примере VSS).

6.7.1. Обоснование

Основная причина использования семантики copy-in/copy-out (вместо традиционной call-by-reference) заключается в контроле побочных эффектов внешних функций и методов, которые являются основным механизмом взаимодействия программы P4 со своим окружением. Семантика copy-in/copy-out не даёт внешним функциям удерживать ссылки на объекты программы P4 и это позволяет компилятору ограничить побочные влияния внешних функций на программу P4 как в пространстве (влияние лишь на параметры out), так и во времени (влияние лишь при вызове функции).

В общем случае внешние функции могут делать все, что угодно — хранить информацию в глобальном хранилище, порождать отдельные потоки, «вступать в сговор» с другими для совместного использования информации, — но они не имеют доступа к переменным программы P4. Семантика copy-in/copy-out позволяет компилятору считать программу P4 вызывающей внешние функции.

Имеется ещё два преимущества использования семантики copy-in/copy-out:

  • возможность компилировать программы P4 для архитектуры, не поддерживающей ссылки (например, при размещении данных в именованных регистрах), которая может требовать индексов в стеки заголовков, появляющиеся в программе, чтобы получить значения во время компиляции;

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

parameterList
	: /* пусто */
	| nonEmptyParameterList
	;

nonEmptyParameterList
	: parameter
	| nonEmptyParameterList ',' parameter
	;

parameter
	: optAnnotations direction typeRef name
	| optAnnotations direction typeRef name '=' expression
	;

direction
	: IN
	| OUT
	| INOUT
	: /* пусто */
	;

Ниже кратко перечислены ограничения, связанные с направлением параметров.

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

  • Все параметры конструкторов оцениваются во время компиляции, поэтому они не могут иметь направления, это относится к объектам package, control, parser, extern. Значения таких параметров должны быть заданы в момент компиляции и обеспечивать возможность оценки при компиляции (14. Параметризация).

  • Для действий все параметры без направления должны быть в конце списка параметров. Для действий в таблице должны указываться лишь параметры с направлением (13.1. Действия).

  • Действия могут также вызываться явно с использованием синтаксиса функций из блока управления или другого действия. При этом значения всех параметров действия должны быть заданы явно, включая значения параметров без направления, которые в такой ситуации ведут себя как параметры in (13.1.1. Вызов действия).

  • Принятые по умолчанию значение разрешены лишь для параметров без направления и in, они должны преобразовываться в константы, доступные при компиляции.

6.7.2. Необязательные параметры

Параметр, аннотированный как @optional, является необязательным и пользователь может опустить его значение при вызове. Необязательные параметры могут присутствовать лишь в аргументах пакетов, внешних функций и методов, а также конструкторов объектов extern. Такие параметры не могут иметь принятых по умолчанию значений. Если конструкция, подобная процедуре, использует необязательные параметры и подразумеваемые значения, она может вызываться лишь с указанием именованных аргументов. Рекомендуется (но не требуется) размещать необязательные параметры в конце списка параметров.

Реализация объектов с необязательными параметрами не задана в P4, поэтому назначение и реализация таких объектов должны задаваться целевой архитектурой. Например, можно представить архитектуру двухэтапной коммутации с необязательным вторым этапом. Это можно объявить как пакет с необязательным параметром

package pipeline(/* параметры опущены */);
package switch(pipeline first, @optional pipeline second);

pipeline(/* аргументы опущены */) ingress;
switch(ingress) main;	// коммутатор с одноэтапным конвейером

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

extern void h(in bit<32> a, in bool b = true);	// принятое по умолчанию значение
// вызовы функций
h(10);		// то же, что и h(10, true);
h(a = 10);	// то же, что и h(10, true);
h(a = 10, b = true);
struct Empty {}
control nothing(inout Empty h, inout Empty m) {
	apply {}
}
parser parserProto<H, M>(packet_in p, out H h, inout M m);
control controlProto<H, M>(inout H h, inout M m);

package pack<HP, MP, HC, MC>(@optional parserProto<HP, MP> _parser, // необязательный параметр
			controlProto<HC, MC> _control = nothing()); // подразумеваемое значение

pack() main;	// Нет значения _parser, а _control является экземпляром nothing()

6.8. Распознавание имён

Объекты P4, создающие пространства имён, организованы в иерархию. Имеется также безымянное пространство верхнего уровня, содержащее все объявления верхнего уровня. Идентификаторы, начинающиеся с точки (.), всегда относятся к пространству имён верхнего уровня.

const bit<32> x = 2;
control c() {
	int<32> x = 0;
	apply {
		x = x + (int<32>).x;	// x - локальная переменная int<32>,
					// .x - переменная bit<32> верхнего уровня
	}
}

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

const bit<4> x = 1;
control p() {
	const bit<8> x = 8;	// объявление x затеняет глобальную переменную x
	const bit<4> y = .x;	// ссылка на x верхнего уровня
	const bit<8> z = x;	// ссылка на локальную (p) переменную x
	apply {}
}

6.9. Видимость

Идентификаторы, определённые на верхнем уровне, видны глобально. Объявления внутри анализатора или элемента управления являются приватными и не могут упоминаться за пределами этого объекта.

7. Типы данных P4

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

7.1. Базовые типы

Ниже перечислены встроенные базовые типы, поддерживаемые P4:

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

  • error служит для передачи сведений об ошибках независимым от платформы, управляемым компилятором способом;

  • string может применяться лишь для строковых констант во время компиляции;

  • match_kind служит для описания реализации поиска в таблицах;

  • bool представляет логические значения;

  • int служит для представления целых чисел произвольного размера;

  • bit<> — битовые строки фиксированного размера;

  • int<> — целые числа фиксированного размера, представленные дополнением до 2;

  • varbit<> — битовые строки с ограничением максимального размера.

baseType
	: BOOL
	| ERROR
	| BIT
	| INT
	| STRING
	| BIT '<' INTEGER '>'
	| INT '<' INTEGER '>'
	| VARBIT '<' INTEGER '>'
	| BIT '<' '(' expression ')' '>'
	| INT '<' '(' expression ')' '>'
	| VARBIT '<' '(' expression ')' '>'
	;

7.1.1. Тип void

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

7.1.2. Тип error

Тип error содержит значения (opaque), которые могут служить для сигнализации ошибок. Константы типа error определяются в форме

errorDeclaration
	: ERROR '{' identifierList '}'
	;

Константы error помещаются в пространство имён ошибок, независимо от места их определения. Тип error похож на тип enum в других языках. Программа может включать множество объявлений ошибок, которые компилятор собирает вместе. Объявление одной константы error несколько раз является ошибкой. Выражения типа error описаны в параграфе 8.2. Операции над типом error. Например, ниже приведено определение двух констант (из основной библиотеки P4).

error { ParseError, PacketTooShort }

Базовое представление ошибок зависит от платформы.

7.1.3. Тип match_kind

Тип match_kind очень похож на error и применяется для объявления набора имён, которые могут служить свойствами ключа таблицы (13.2.1. Свойства таблицы). Все идентификаторы помещаются в пространство имён верхнего уровня. Определение одного идентификатора match_kind несколько раз является ошибкой.

matchKindDeclaration
	: MATCH_KIND '{' identifierList '}'
	;

Основная библиотека P4 содержит приведённое ниже объявление match_kind.

match_kind {
	exact,
	ternary,
	lpm
}

Архитектура может не поддерживать дополнительные типы match_kind. Объявление новых match_kind может выполняться лишь в файлах определения моделей и программисты P4 не могут делать таких объявлений.

7.1.4. Логический тип

Логический тип bool имеет значения false и true, не относящиеся к integer или bit-string.

7.1.5. Строки

Для представления строк используется тип string. Операций с этим типом в языке не выполняется и невозможно объявить переменную типа string. Параметры этого типа не могут иметь направления (6.7. Соглашения о вызовах). P4 не поддерживает манипуляций со строками в плоскости данных и этот тип можно применять лишь для констант, известных в момент компиляции. Это может быть полезно, например, для платформ, поддерживающих внешнюю функцию для регистрации событий вида

extern void log(string message);

В программах P4 могут использоваться лишь строковые константы, описанные в параграфе 6.3.3.3. Строковые литералы. Например, приведённая ниже аннотация указывает, что заданное имя следует применять для таблицы при генерации API плоскости управления.

@name("acl") table t1 { /* тело опущено */ }

7.1.6. Целые числа

P4 поддерживает целые числа произвольного размера. Особенности типизации целых чисел приведены ниже.

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

  • P4 пытается преодолеть многие особенности поведения C, включающего размер целых чисел (int), в результате чего комбинации целочисленных типов не приводят к неопределённому поведению.

  • Правила типизации P4 выбраны так, чтобы поведение было похоже на традиционные программы C.

  • Вместо правил, ведущих к неожиданным результатам (например, сравнение в C чисел со знаком и без знака), здесь запрещены выражения с неоднозначным результатом. Например, P4 не разрешает двоичные операции, комбинирующие числа со знаком и без знака.

Приоритет арифметических операций идентичен принятому в C.

7.1.6.1. Переносимость

Ни одна платформа P4 не может поддерживать все возможные типы и операции. Например, тип bit<23132312> корректен в P4, но с большой вероятностью не будет поддерживаться на практике всеми платформами. Поэтому каждая платформа вносит ограничения в число поддерживаемых типов. Такие ограничения могут включать:

  • максимальный размер (ширина);

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

  • ограничения для некоторых операндов (например, на значения сомножителей или величины сдвига).

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

7.1.6.2. Целые числа без знака (bit-string)

Целые числа без знака (bit-string) могут иметь произвольный размер в битах. Строка битов размера W обозначается bit<W>. Значение W должно быть известно (вычисляемо) в момент компиляции (17.1. Известные при компиляции значения) и быть целым числом больше 0. Выражения для размера числа должны указываться в скобках.

const bit<32> x = 10;		// 32-битовая константа со значением 10.
const bit<(x + 2)> y = 15;	// 12-битовая константа со значением 15.
				// при указании размера нужно использовать скобки ()

Биты в bit-string нумеруются от 0 до W-1, бит 0 является младшим, W-1 — старшим. Например, тип bit<128> указывает битовые строки размером 128 битов с номерами битов от 0 до 127, где бит 127 является старшим. Тип bit является сокращением для bit<1>.

Архитектура P4 может вносить дополнительные ограничения для битовых типов, например, может ограничиваться максимальный размер или поддерживаться некоторые арифметические операции лишь для определённых размеров (скажем, 16, 32, 64 бита). Операции, доступные для целых чисел без знака описаны в параграфе 8.5. Операции над битовыми типами (целые числа без знака).

7.1.6.3. Целые числа со знаком

Целые числа со знаком представляются дополнением до 2. Целое число размером W битов объявляется в форме int<W>, где W должно быть выражением, которое в момент компиляции преобразуется в положительное целое число. Биты числа нумеруются от 0 до W-1, бит 0 является младшим, а бит W-1 содержит знак. Например, тип int<64> описывает целые числа, представляемые 64 битами с номерами от 0 до 63, где бит 63 (старший) задаёт знак.

Архитектура P4 может вносить дополнительные ограничения для чисел со знаком, например, может ограничиваться максимальный размер или поддерживаться некоторые арифметические операции лишь для определённых размеров (скажем, 16, 32, 64 бита). Операции над целыми числами со знаком описаны в параграфе 8.6. Операции над целыми числами фиксированного размера со знаком.

Целое число со знаком размера 1 int<1> может иметь два корректных значения — 0 и -1.

7.1.6.4. Динамические строки битов

В некоторых сетевых протоколах используются поля, размер которых становится известен лишь в процессе работы (например, опции IPv4). Для поддержки ограниченных манипуляций с такими полями в P4 применяется специальный тип битовых строк, размер которых задаётся в процессе работы — varbit. Тип varbit<W> указывает строку битов размером не более W, где W — положительное целое число, известное при компиляции. Например, тип varbit<120> означает строки битов размером от 0 до 120. Большинство операций, применимых к битовым строкам фиксированного размера (целые числа без знака), не может быть выполнено для динамических битовых строк.

Архитектура P4 может вносить дополнительные ограничения для типа varbit, например, может ограничиваться максимальный размер или вводится требование использовать при работе лишь значения varbit с целым числом байтов. Операции над varbit описаны в параграфе 8.8. Операции над битовыми строками переменного размера.

7.1.6.5. Целые числа “бесконечной точности”

Тип данных «бесконечной точности» описывает целые числа неограниченного размера — int. Этот тип зарезервирован для целочисленных литералов и выражений, включающих лишь литералы. Ни одно значение P4 не может иметь тип int в процессе работы — компилятор преобразует значения int в подходящие типы фиксированных размеров.

Операции над типом int описаны в параграфе 8.7. Операции над целыми числами произвольной точности. Приведённый ниже пример показывает определения трёх констант типа int.

const int a = 5;
const int b = 2 * a;
const int c = b - a + 3;
7.1.6.6. Целочисленные литералы

Типы целочисленных литералов (констант) включают:

  • простые целочисленные константы типа int;

  • положительные целые числа с префиксом размера N и символом w типа bit<N>.

  • целые числа с префиксом размера N и символом s типа int<N>.

В таблице показано несколько примеров целочисленных литералов с их типами. Дополнительные примеры даны в параграфе 6.3.3. Литеральные константы.

Литерал

Интерпретация

10

Тип int, значение 10

8w10

Тип bit<8>, значение 10

8s10

Тип int<8>, значение 10

2s3

Тип int<2>, значение -1 (последние 2 бита), предупреждение о переполнении

1w10

Тип bit<1>, значение 0 (последний бит), предупреждение о переполнении

1s1

Тип int<1>, значение -1, предупреждение о переполнении

7.2. Производные типы

P4 поддерживает множество конструкторов типов, которые можно применять для создания производных типов:

  • enum;

  • header;

  • стек заголовков;

  • struct;

  • header_union;

  • tuple;

  • специализация типа;

  • extern;

  • parser;

  • control;

  • package.

Типы header, header_union, enum, struct, extern, parser, control, package могут использоваться лишь в объявлениях типа, где они задают новое имя типа, которое впоследствии позволяет указывать этот тип.

Другие типы не могут быть объявлены, но синтезируются компилятором для представления типов некоторых языковых конструкций. Эти типы описаны в параграфе 7.2.8. Синтезируемые типы данных (set и function). Например, программист не может объявить переменную типа set, но можно задать выражение, которое будет преобразовываться в этот тип. Эти типы используются в процессе проверки типов.

typeDeclaration
	: derivedTypeDeclaration
	| typedefDeclaration
	| parserTypeDeclaration ';'
	| controlTypeDeclaration ';'
	| packageTypeDeclaration ';'
	;

derivedTypeDeclaration
	: headerTypeDeclaration
	| headerUnionDeclaration
	| structTypeDeclaration
	| enumDeclaration
	;

typeRef
	: baseType
	| typeName
	| specializedType
	| headerStackType
	| tupleType
	;

namedType
	: typeName
	| specializedType
	;

prefixedType
	: TYPE_IDENTIFIER
	| dotPrefix TYPE_IDENTIFIER
	;

typeName
	: prefixedType
	;

7.2.1. Перечисляемые типы

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

enumDeclaration
	: optAnnotations ENUM name '{' identifierList '}'
	| optAnnotations ENUM BIT '<' INTEGER '>' name '{' specifiedIdentifierList '}'
	;

identifierList
	: name
	| identifierList ',' name
	;

specifiedIdentifierList
	: specifiedIdentifier
	| specifiedIdentifierList ',' specifiedIdentifier
	;

specifiedIdentifier
	: name '=' initializer
	;

Например, объявление

enum Suits { Clubs, Diamonds, Hearths, Spades }

вводит новый перечисляемый тип, включающий 4 константы (например, Suits.Clubs). Объявление enum вводит новый идентификатор в текущей области действия для именования созданного типа. Базовое представление перечисляемого типа Suits не задано, поэтому его «размер» в битах не задаётся (зависит от платформы).

Можно также задать enum с базовым представлением. Иногда это называют сериализацией enum, поскольку в заголовки можно включать поля данного типа enum. Это требует от программиста предоставить целочисленный тип фиксированного размера без знака или со знаком и связанное с ним значение для каждого символьного имени в enum. Идентификатор typeRef (см. выше) должен указывать один из следующих типов:

  • целое число без знака, т. е. bit<W> с неким постоянным W;

  • целое число со знаком, т. е. int<W> с неким постоянным W;

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

Например, объявление

enum bit<16> EtherType {
	VLAN	= 0x8100,
	QINQ	= 0x9100,
	MPLS	= 0x8847,
	IPV4	= 0x0800,
	IPV6	= 0x86dd
}

вводит новый перечисляемый тип с 5 константами (например, EtherType.IPV4). Это объявление enum задаёт представления целым числом фиксированного размера без знака для каждого элемента enum и указывает базовый тип bit<16>. Этот тип объявления enum можно считать объявлением нового типа bit<16>, где переменные или поля этого типа выражаются 16-битовыми целыми числами без знака и отображения символьных имён на числа, заданные enum, по сути определяют константы. Таким способом enum с базовым типом можно представлять как тип, выведенный из базового, что позволяет использовать равенство, присвоение и приведение к базовому типу или из него.

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

enum bit<8> FailingExample {
	first	= 1,
	second	= 2,
	third	= 3,
	unrepresentable = 300
}

будет вызывать ошибку, поскольку значение 300, связанное с FailingExample.unrepresentable выходит за пределы bit<8>.

Выражение для инициализации (initializer) должно быть известно в момент компиляции. Аннотации, представляемые нетерминальными optAnnotations, описаны в разделе 18. Аннотации, операции со значениями enum — в параграфе 8.3. Операции над типом enum.

7.2.2. Типы заголовков

Для определения типа header применяется показанный ниже синтаксис.

headerTypeDeclaration
	: optAnnotations HEADER name '{' structFieldList '}'
	;

structFieldList
	: /* пусто */
	| structFieldList structField
	;

structField
	: optAnnotations typeRef name ';'
	;

где каждое в качестве typeRef можно применять строки битов (переменного или фиксированного размера), целые числами фиксированного размера со знаком, логический тип или struct (с полями типа struct) с произвольной вложенностью, если все типы «листьев» относятся к bit<W>, int<W>, сериализуемым enum или bool. При использовании bool внутри заголовка P4, все реализации кодируют bool однобитовым полем, где 1 представляет true, а 0 — false.

Объявление заголовка вводит новый идентификатор в текущей области действия, который можно указывать заданным идентификатором типа. Заголовок похож на структуру C, содержащую все указанные поля. Однако заголовок также включает скрытое логическое поле validity. Когда это поле установлено (true), заголовок считается действительным. При объявлении локальной переменной типа header для бита validity автоматически устанавливается значение false. Менять этот бит можно с использованием методов isValid(), setValid() и setInvalid(), как описано в параграфе 8.16. Операции над заголовками.

Отметим, что вложенные заголовки не поддерживаются. Одна из сложностей состоит в усложнении определения поведения произвольных последовательностей операций setValid, setInvalid и emit. Рассмотрим пример, где заголовок h1 содержит заголовок h2 и оба заголовка действительны (valid). Программа выполняет h2.setInvalid(), за которым следует packet.emit(h1). Следует ли emit выводить все поля h1, пропуская h2? Следует ли h1.setInvalid() объявлять недействительными все заголовки внутри h1 независимо от глубины вложенности?

Заголовок может быть пустым, как показано ниже.

header Empty_h { }

Отметим, что бит validity имеется и в пустом заголовке.

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

struct ipv6_addr {
	bit<32> Addr0;
	bit<32> Addr1;
	bit<32> Addr2;
	bit<32> Addr3;
}

header ipv6_t {
	bit<4>		version;
	bit<8>		trafficClass;
	bit<20>	flowLabel;
	bit<16>	payloadLen;
	bit<8>		nextHdr;
	bit<8>		hopLimit;
	ipv6_addr 	src;
	ipv6_addr 	dst;
}

Заголовки без полей varbit имеют фиксированный размер, заголовки с полями varbit — переменный. Размер фиксированного заголовка (в битах) не меняется и равен сумме размеров всех его полей (без учёта бита validity). Для полей заголовка не используется заполнение или выравнивание. Платформы могут вносить свои ограничения для типа header, например, ограничивать размер целым числом байтов. Ниже приведён пример определения для типичного заголовка Ethernet.

header Ethernet_h {
	bit<48> dstAddr;
	bit<48> srcAddr;
	bit<16> etherType;
}

Приведённое ниже объявление переменной использует определение типа Ethernet_h

Ethernet_h ethernetHeader;

Язык анализа P4 предоставляет точный метод извлечения, который можно применять для «заполнения» полей header из заголовков пакета, как описано в параграфе 12.8. Извлечение данных. При успешном извлечении полей для бита validity устанавливается значение true. Ниже приведён пример заголовка IPv4 с опциями переменного размера.

header IPv4_h {
	bit<4>		version;
	bit<4>		ihl;
	bit<8>		diffserv;
	bit<16>	totalLen;
	bit<16>	identification;
	bit<3>		flags;
	bit<13>	fragOffset;
	bit<8>		ttl;
	bit<8>		protocol;
	bit<16>	hdrChecksum;
	bit<32>	srcAddr;
	bit<32>	dstAddr;
	varbit<320>	options;
}

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

7.2.3. Стеки заголовков

Стек заголовков представляет собой массив заголовков, определяемый как

headerStackType
	: typeName '[' expression ']'
	;

Здесь typeName указывает имя заголовка. Для стека заголовков hs[n] значение n указывает максимальный размер и должно быть положительным целым числом, значение которого известно в момент компиляции. Вложенные стеки заголовков не поддерживаются. Во время работы стек содержит n заголовков типа typeName, из которых действительна лишь часть. Выражения со стеками заголовков рассмотрены в параграфе 8.17. Операции над стеком заголовков.

Например, объявление

header Mpls_h {
	bit<20> label;
	bit<3>	tc;
	bit	bos;
	bit<8>	ttl;
}
Mpls_h[10] mpls;

вводит стек заголовков с именем mpls, содержащий 10 элементов типа Mpls_h.

7.2.4. Объединения заголовков

Объединение заголовков представляет собой другой вариант структуры из нескольких заголовков. Объединение можно использовать для представления опций в таких протоколах, как TCP и IP. Объединение также подсказывает компилятору P4, что может присутствовать лишь один вариант, позволяя экономить пространство хранилища.

headerUnionDeclaration
	: optAnnotations HEADER_UNION name
		'{' structFieldList '}'
	;

Это объявление вводит новый тип с указанным именем в текущей области действия. Каждый элемент из списка полей, используемых для объявления объединения заголовков, должен иметь тип header. Однако можно указать пустой список полей.

Представленный ниже тип Ip_h представляет объединение заголовков IPv4 и IPv6.

header_union IP_h {
	IPv4_h v4;
	IPv6_h v6;
}

Объединение заголовков не рассматривается как тип с фиксированным размером.

7.2.5. Структурные типы

Структурные типы P4 определяются, как показано ниже.

structTypeDeclaration
	: optAnnotations STRUCT name '{' structFieldList '}'
	;

Объявление вводит новый тип с указанным именем в текущей области действия. Допускаются пустые структуры. Например, приведённая ниже структура Parsed_headers содержит заголовки, распознаваемые простым анализатором.

header Tcp_h { /* поля опущены */ }
header Udp_h { /* поля опущены */ }
struct Parsed_headers {
	Ethernet_h 	ethernet;
	Ip_h		ip;
	Tcp_h		tcp;
	Udp_h		udp;
}

7.2.6. Кортежи

Кортежи (tuple) похожи на структуры в том, что могут включать много значений. Однако поля кортежей не имеют имён. Тип кортежа с n компонентами типов T1,…,Tn определяется в форме

tuple<T1,/* поля опущены */,Tn>

tupleType
	: TUPLE '<' typeArgumentList '>'
	;

Операторы для работы с tuple описаны в параграфах 8.10. Операции над кортежами и 8.11. Операции над списками.

Тип tuple<> задаёт кортеж без компонентов.

7.2.7. Правила вложенности типов

В таблице указаны все типы, которые могут служить элементами заголовков, объединений заголовков, структур или кортежей. Отметим, что int указывает целое число «бесконечной» точности, размер которого не задан.

Тип контейнера

Тип элемента

header

header_union

struct или tuple

bit<W>

разрешено

ошибка

разрешено

int<W>

разрешено

ошибка

разрешено

varbit<W>

разрешено

ошибка

разрешено

int

ошибка

ошибка

ошибка

void

ошибка

ошибка

ошибка

error

ошибка

ошибка

разрешено

match_kind

ошибка

ошибка

ошибка

bool

разрешено

ошибка

разрешено

enum

разрешено

ошибка

разрешено

header

ошибка

разрешено

разрешено

header stack

ошибка

ошибка

разрешено

header_union

ошибка

ошибка

разрешено

struct

разрешено

ошибка

разрешено

tuple

ошибка

ошибка

разрешено

Тип int не имеет точных требований к хранилищу в отличие от bit<> и int<>. Значения match_kind бесполезно сохранять в переменной, поскольку они служат лишь для задания сопоставлений полей с ключами поиска в таблице, объявляемых во время компиляции. Тип void бесполезен как часть структуры данных. Заголовки должны иметь точно заданные форматы в виде последовательности битов, чтобы их можно было анализировать и собирать заново.

Отметим, что двухаргументный метод extract (12.8.2. Извлечение при переменном размере) для пакетов поддерживает в заголовке лишь одно поле varbit.

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

Базовый тип B

typedef B <name>

type B <name>

bit<W>

разрешено

разрешено

int<W>

разрешено

разрешено

varbit<W>

разрешено

ошибка

int

разрешено

ошибка

void

ошибка

ошибка

error

разрешено

ошибка

match_kind

ошибка

ошибка

bool

разрешено

разрешено

enum

разрешено

ошибка

header

разрешено

ошибка

header stack

разрешено

ошибка

header_union

разрешено

ошибка

struct

разрешено

ошибка

tuple

разрешено

ошибка

Имя typedef

разрешено

разрешено

Имя type

разрешено

разрешено

7.2.8. Синтезируемые типы данных

Для проверки типов компилятор P4 может синтезировать представления некоторых типов, которые пользователь не может выразить напрямую. К таким типам относятся set и function.

7.2.8.1. Тип set

Тип set<T> описывает набор значений типа T и может применяться в ограниченном контексте P4. Например, выражение для диапазона 8w5 .. 8w8 описывает набор 8-битовых чисел 5, 6, 7 и 8, т. е. они имеют тип set<bit<8>>;. Это выражение можно использовать как метку в выражении select (12.6. Выражения для выбора), соответствующую любому числу из диапазона. Типы set не могут быть именованными или объявленными программистом P4, они лишь синтезируются компилятором для проверки типов. Выражения типа set описаны в параграфе 8.13. Операции над set.

7.2.8.2. Тип function

Типы function создаются компилятором P4 для представления функций (явных или внешних) и методов при проверке типов. Тип функции называют также её сигнатурой. Библиотеки могут включать объявления функций и внешних функций. Ниже приведены два примера определений.

extern void random(in bit<5> logRange, out bit<32> value);

bit<32> add(in bit<32> left, in bit<32> right) {
	return left + right;
}

Эти определения описывают два объекта:

  • random, который является типом function и представляет:

    • функция имеет результат типа void;

    • функция принимает два параметра;

    • первый параметр имеет направление in, тип bit<5> и имя logRange;

    • второй параметр имеет направление out, тип bit<32> и имя value;

  • add также является типом function и представляет

    • результат типа bit<32>;

    • функция принимает два параметра;

    • оба параметра имеют направление in и тип bit<32>.

7.2.9. Внешние типы

P4 поддерживает объявления внешних объектов и внешних функций, как показано ниже.

externDeclaration
	: optAnnotations EXTERN nonTypeName optTypeParameters '{' methodPrototypes '}'
	| optAnnotations EXTERN functionPrototype ';'
	;
7.2.9.1. Внешние функции

Объявление внешней функции задаёт имя и сигнатуру типа для функции, не задавая её реализации.

functionPrototype
	: typeOrVoid name optTypeParameters '(' parameterList ')'
	;

Пример объявления внешней функции приведён в параграфе 7.2.8.2. Тип function.

7.2.9.2. Внешние объекты

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

methodPrototypes
	: /* пусто */
	| methodPrototypes methodPrototype
	;

methodPrototype
	: optAnnotations functionPrototype ';'
	| optAnnotations TYPE_IDENTIFIER '(' parameterList ')' ';' // конструктор
	;

typeOrVoid
	: typeRef
	| VOID
	| IDENTIFIER	// может быть переменной типа
	;

optTypeParameters
	: /* пусто */
	| '<' typeParameterList '>'
	;

typeParameterList
	: name
	| typeParameterList ',' name
	;

Например, в основной библиотеке P4 вводятся внешние объекты packet_in и packet_out для операций над пакетами (12.8. Извлечение данных и 15. Сборка пакета). Ниже приведён пример, показывающий вызов этих методов для пакета.

extern packet_out {
	void emit<T>(in T hdr);
}
control d(packet_out b, in Hdr h) {
	apply {
		b.emit(h.ipv4);	// Запись заголовка IPv4 в выходной пакет вызовом emit
}

В P4 «форсирование» поддерживается лишь для функций и методов — в одной области действия может существовать множество одноимённых методов. При использовании форсирования компилятор должен быть способен устранить неоднозначности вызова методов и функций по числу или именам аргументов. Типы аргументов при устранении неоднозначностей не рассматриваются.

Абстрактные методы

Типовые методы объектов extern являются встроенными и реализуются целевой архитектурой. Программы P4 могут лишь вызывать такие методы.

Однако некоторые типы объектов extern могут предоставлять методы, которые можно реализовать в программе P4. Такие методы описываются с помощью ключевого слова abstract перед определением метода.

extern Balancer {     Balancer();
     // Определение числа активных потоков     bit<32> getFlowCount();
     // Возвращает индекс порта для балансировки нагрузки
     // @param address: Адрес IPv4 для источника потока
     abstract bit<4> on_new_flow(in bit<32> address); }

При создании экземпляра такого объекта должна быть представлена реализация всех абстрактных методов (см. 10.3.1. Ограничения для создания экземпляров на верхнем уровне).

7.2.10. Специализация типа

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

specializedType
	: prefixedType '<' typeArgumentList '>'
	;

В приведённом ниже примере объявление extern описывает базовый блок регистров, где тип сохраняемых в регистре элементов является произвольным T.

extern Register<T> {
	Register(bit<32> size);
	T read(bit<32> index);
	void write(bit<32> index, T value);
}

Тип T должен указываться при создании экземпляра набора регистров путём задания типа Register

Register<bit<32>>(128) registerBank;

Создание экземпляра registerBank выполняется с использованием типа Register заданного привязкой bit<32> к аргументу типа T.

Типы struct, header, header_union и стек заголовков (header stack) также могут быть базовыми. Для использования таких базовых типов они должны быть заданы с использованием подобающих аргументов. Например,

// Базовый тип структуры
struct S<T> {
     T field;
     bool valid;
 } 

struct G<T> {
     S<T> s; 
} 
// Специализация S путём замены T на bit<32> 
const S<bit<32>> s = { field = 32w0, valid = false }; 
// Специализация G путём замены T на bit<32> 
const G<bit<32>> g = { s = { field = 0, valid = false } }; 

// generic header type 
header H<T> {
     T field; 
} 
// Специализация H путём замены T на bit<8> 
const H<bit<8>> h = { field = 1 }; 

// Стек заголовков создаётся из специализации базового типа header 
H<bit<8>>[10] stack; 

// Базовый тип header_union 
header_union HU<T> {
     H<bit<32>> h32;
     H<bit<8>>  h8;
     H<T>       ht; 
} 

// Объединение заголовков с типом, получаемым специализацией базового типа header_union 
HU<bit> hu;

7.2.11. Типы анализаторов и блоков управления

Типы parser и control похожи на тип function и описывают сигнатуру анализатора или блока управления. Такие функции не возвращают значений. Объявления анализаторов и блоков управления в архитектуре могут быть базовыми (т. е. иметь параметры типа).

Типы parser, control и package не могут служить типами аргументов для методов, анализаторов, элементов управления, таблиц или действий. Они могут служить типами для аргументов, передаваемых конструкторам (14. Параметризация).

7.2.11.1. Объявление типа анализатора

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

parserTypeDeclaration
	: optAnnotations PARSER name optTypeParameters
	'(' parameterList ')'
	;

Например, ниже показано объявление типа parser с именем P, параметризованное переменной типа H. Анализатор, получивший на входе packet_in со значением b, создаёт на выходе два значения:

  • заданного пользователем типа H;

  • предопределённого типа Counters.

struct Counters { /* поля опущены */ }
parser P<H>(packet_in b,
	out H packetHeaders,
	out Counters counters);
7.2.11.2. Объявление типа блока управления

Объявление типа элемента управления (control) описывает сигнатуру блока управления и похоже на объявление типа parser.

controlTypeDeclaration
	: optAnnotations CONTROL name optTypeParameters
	'(' parameterList ')'
	;

7.2.12. Типы пакетов (package)

Тип package описывает сигнатуру программного пакета.

packageTypeDeclaration
	: optAnnotations PACKAGE name optTypeParameters
	'(' parameterList ')'
;

Все параметры package оцениваются при компиляции и не должны указывать направления (не могут быть in, out, inout). В остальном типы package похожи на parser. Для пакетов могут лишь создаваться экземпляры без управления поведением при работе.

7.2.13. Типы, не имеющие значения (don’t care)

Не имеющие значения типы (_) могут применяться в некоторых обстоятельствах. Их следует использовать лишь там, где возможна запись переменной привязанного типа. Символ подчёркивания может применяться для снижения сложности кода, когда не имеет значения конкретная привязка переменной (например при унификации типа don’t care может комбинироваться с любым другим типом). Пример рассмотрен в параграфе 16.1. Пример описания архитектуры.

7.3. Подразумеваемые значения

Для некоторых типов P4 определены «принятые по умолчанию значения», которые могут автоматически применяться при инициализации данного типа.

  • Для int, bit<N> и int<N> подразумевается 0.

  • Для bool подразумевается false.

  • Для error подразумевается error.NoError (определено в core.p4).

  • Для string подразумевается пустая строка «».

  • Для varbit<N> подразумевается строка нулей (в P4 сейчас нет литерала для этого).

  • Для enum с базовым типом подразумевается 0, даже если 0 реально не зазван среди значений enum.

  • Для enum без базового типа подразумевается первое значение, появляющееся в объявлении типа enum.

  • Для header подразумевается invalid.

  • Для стека заголовков подразумевается, что все элементы являются invalid, а nextIndex = 0.

  • Для header_union подразумевается invalid во всех элементах.

  • Для struct подразумевается структура, где каждое поле имеет принятое по умолчанию значение в соответствии с типом поля, если такое значение определено.

  • Для a tuple подразумевается кортеж, где каждое поле имеет принятое по умолчанию значение в соответствии с типом поля, если такое значение определено.

Отметим, что некоторые типы не имеют подразумеваемых значений, например, это match_kind, set, function, extern, parser, control, package.

7.4. typedef

Объявление typedef можно использовать для создания дополнительного имени типа.

typedefDeclaration
	: optAnnotations TYPEDEF typeRef name ';'
	| optAnnotations TYPEDEF derivedTypeDeclaration name ';'
	;

typedef bit<32> u32;
typedef struct Point { int<32> x; int<32> y; } Pt;
typedef Empty_h[32] HeaderStack;

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

7.5. Создание новых типов

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

	| optAnnotations TYPE typeRef name
	| optAnnotations TYPE derivedTypeDeclaration name

type bit<32> U32;
U32 x = (U32)0;

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

Важным применением таких типов является описание значений P4, которыми нужно обмениваться с плоскостью управления по коммуникационным каналам (например, через API плоскости управления или в передаваемых этой плоскости сетевых пакетах). Архитектура P4 может, например, определять тип для портов коммутатора

type bit<9> PortId_t;

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

8. Выражения

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

Правило грамматики для выражений общего назначение имеет вид

expression
	: INTEGER
	| TRUE
	| FALSE
	| STRING_LITERAL
	| nonTypeName
	| dotPrefix nonTypeName
	| expression '[' expression ']'
	| expression '[' expression ':' expression ']'
	| '{' expressionList '}'
	| '{' kvList '}'
	| '(' expression ')'
	| '!' expression
	| '~' expression
	| '-' expression
	| '+' expression
	| typeName '.' member
	| ERROR '.' member
	| expression '.' member
	| expression '*' expression
	| expression '/' expression
	| expression '%' expression
	| expression '+' expression
	| expression '-' expression
	| expression SHL expression		// SHL - это сдвиг влево (<<)
	| expression '>''>' expression	// символы >> не должны быть разделены
	| expression LE expression		// LE - это меньше или равно (<=)
	| expression GE expression
	| expression '<' expression
	| expression '>' expression
	| expression NE expression		// NE - не равно (!=)
	| expression EQ expression		// EQ - равно (==)
	| expression '&' expression
	| expression '^' expression
	| expression '|' expression
	| expression PP expression	// PP это ++
	| expression AND expression	// AND это &&
	| expression OR expression	// OR это ||
	| expression '?' expression ':' expression
	| expression '<' realTypeArgumentList '>' '(' argumentList ')'
	| expression '(' argumentList ')'
	| namedType '(' argumentList ')'
	| '(' typeRef ')' expression
	;
expressionList
	: /* пусто */
	| expression
	| expressionList ',' expression
	;
member
	: name
	;
argumentList
	: /* пусто */
	| nonEmptyArgList
	;
nonEmptyArgList
	: argument
	| nonEmptyArgList ',' argument
	;
argument
	: expression
	;
typeArg
	: DONTCARE
	| typeRef
	| nonTypeName
	;
typeArgumentList
	: /* пусто */
	| typeArg
	| typeArgumentList ',' typeArg
	;

Полная грамматика P4 приведена в Приложении H.

Приведённая грамматика не показывает очерёдности операций. Порядок действий похож на применяемый в C с одним исключением и некоторыми дополнениями. Приоритет побитовых операций &, | и ^ выше приоритета <, <=, >, >=. Это более естественно с учётом добавления логического типа true в систему типов, поскольку побитовые операции не могут применяться к логическим типам. Конкатенация (++) имеет такой же приоритет, что и инфиксное сложение. «нарезка» битов a[m:l] имеет такой же приоритет как индексирование массива (a[i]).

В дополнение к этому P4 поддерживает выражения выбора select (12.6. Выражения для выбора), которые могут применяться лишь в анализаторах.

8.1. Порядок операций

С учётом составных выражений, где оценивается порядок для субвыражений, важен учёт побочных эффектов в субвыражениях. Выражения в P4 оцениваются, как описано ниже.

  • Логические операторы && и || оцениваются в сокращённом порядке, т. е. второй операнд учитывается лишь при необходимости.

  • В условных операторах e1 ? e2 : e3 оценивается e1, затем e2 или e3.

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

  • Вызовы методов и функций оцениваются в соответствии с параграфом 6.7. Соглашения о вызовах.

8.2. Операции над типом error

Символические имена, заданные определениями ошибок, относятся к пространству имён ошибок. Для типа error поддерживаются лишь операции сравнения «равно» (==) и «не равно» (!=), результатом которых является логическое значение. Например, приведённая ниже строка проверяет наличие определённой ошибки

error errorFromParser;

if (errorFromParser != error.NoError) { /* код опущен */ }

8.3. Операции над типом enum

Символические имена, заданные определениями перечисляемых типов, относятся к пространствам имён, созданным объявлениями enum, а не к пространству верхнего уровня.

enum X { v1, v2, v3 }
X.v1	// ссылка на v1
v1	// ошибка - v1 не относится к пространству имён верхнего уровня

Подобно error, выражения enum без указания базового типа поддерживают лишь операции сравнения равенства (==) и неравенства (!=). Выражения type без указания базового типа нельзя привести к иному типу (или из иного типа).

Для enum можно указать базовый тип, как показано ниже.

enum bit<8> E {
	e1 = 0,
	e2 = 1,
	e3 = 2
}

Можно отобразить несколько символьных значений enum на одно целое число с фиксированным значением.

enum bit<8> NonUnique {
	b1 = 0,
	b2 = 1,	// b2 и b3 имеют одинаковые значения.
	b3 = 1,
	b4 = 2
}

Для enum с базовым типом поддерживается приведение базового типа, например

bit<8> x;
E a = E.e2;
E b;

x = (bit<8>) a; 	// устанавливает x = 1
b = (E) x;		// устанавливает b = E.e2

Значение a, которое было инициализировано как E.e2 приводится к типу bit<8> с использованием заданного представления целого числа без знака с фиксированным размером для E.e2 и значением 1. Затем для переменной b устанавливается символьное значение E.e2, которое соответствует целому числу без знака с фиксированным размером и значением 1.

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

bit<8> x = E.e2; // устанавливает x = 1 (E.e2 автоматически приводится к bit<8>)

E a = E.e2
bit<8> y = a << 3; // устанавливает y = 8 (автоматически приводится к bit<8> и сдвигается)

Неявное приведение базового типа с фиксированным размером к enum не поддерживается.

enum bit<8> E1 {
	e1 = 0, e2 = 1, e3 = 2
}

enum bit<8> E2 {
	e1 = 10, e2 = 11, e3 = 12
}
E1 a = E1.e1;
E2 b = E2.e2;

a = b;	// Ошибка - b автоматически приводится к bit<8>,
	// но bit<8> не приводится автоматически к E1

a = (E1) b; // Корректно
a = E1.e1 + 1; 	// Ошибка - E.e1 автоматически приводится к bit<8>
			// и правая часть выражения имеет тип bit<8>, 
			// который нельзя автоматически привести к E.

a = (E1)(E1.e1 + 1); // Явное приведение типа делает назначение корректным

a = E1.e1 + E1.e2; 	// Ошибка - оба аргумента сложения автоматически
			// приводятся к bit<8>. Сложение корректно, 
			// но присваивание недействительно.

a = (E1)(E2.e1 + E2.e2); // Явное приведение делает присваивание корректным.

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

E1	a = E1.e1;
E2	b = E2.e2;
bit<8> c;

if (a > b) { // Возможно предупреждение о двух автоматический и разных приведениях к bit<8>.
		// Код опущен
}

c = a + b; // Корректно, но разумно предупредить.

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

bit<8> x = 5;
E e = (E) x; // Устанавливает для e значение без имени.

Для e устанавливается неименованное значение, поскольку отсутствует символ, соответствующий целому числу без знака с фиксированным размером и значением 5. Например, в приведённом ниже фрагменте кода может быть достигнута ветвь else в блоке if/else if/else, даже когда сопоставление с x выполнено относительно символов, определённых в MyPartialEnum_t.

enum bit<2> MyPartialEnum_t {
	VALUE_A = 2w0,
	VALUE_B = 2w1,
	VALUE_C = 2w2
}

bit<2> y = < некое значение >;
MyPartialEnum_t x = (MyPartialEnum_t)y;

if (x == MyPartialEnum_t.VALUE_A) {
	// Тот или иной код
} else if (x == MyPartialEnum_t.VALUE_B) {
	// Тот или иной код
} else if (x == MyPartialEnum_t.VALUE_C) {
	// Тот или иной код
} else {	// Компилятор P4 должен предполагать, что эта ветвь может быть выполнена
	// Тот или иной код
}

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

enum bit<16> EtherType {
	VLAN	= 0x8100,
	IPV4	= 0x0800,
	IPV6	= 0x86dd
}

header ethernet {
	// Часть полей опущена
	EtherType etherType;
}

parser my_parser(/* параметры опущены */) {
	state parse_ethernet {
		packet.extract(hdr.ethernet);
		transition select(hdr.ethernet.etherType) {
			EtherType.VLAN : parse_vlan;
			EtherType.IPV4 : parse_ipv4;
			EtherType.IPV6: parse_ipv6;
			default: reject;
		}
	}
}

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

  • В выражениях select следует соответствовать варианту default или _ в выражении набора ключей.

  • В качестве ключа с троичным match_kind в таблице следует соответствовать записи, где для всех битов поля установлено don’t care.

  • В качестве ключа с match_kind lpm следует соответствовать записи, где это поле имеет префикс размера 0.

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

8.4. Логические выражения

Для логических выражений поддерживаются операции И (&&), ИЛИ (||), НЕ (!), равно (==) и не равно (!=). Порядок выполнения операций аналогичен принятому в C и использует сокращение (при очевидном результате расчёт прекращается). P4 не использует неявного приведения логических значений к bit-string и обратно. В результате обычные для C выражения вида

if (x) /* тело опущено */

(x — целочисленный тип) должно записываться в P4 как

if (x != 0) /* тело опущено */

В параграфе 8.9.2. Неявное приведение описана оценка 0 в этом выражении.

8.4.1. Условный оператор

Условные выражения вида e1 ? e2 : e3 ведут себя как в языке C. Как было отмечено выше, сначала оценивается выражение e1, затем e2 или e3 в зависимости от первого результата. Первое субвыражение должно иметь логический тип, а второе и третье должны быть однотипными, но не могут быть целочисленными с бесконечной разрядностью, если само условие не может быть оценено в момент компиляции. Это ограничение предназначено для того, чтобы размер результата условного выражения можно было статически вывести во время компиляции.

8.5. Операции над битовыми типами (целые числа без знака)

В этом разделе рассматриваются все операции, которые могут быть выполнены над выражениями типа bit<W> для заданного W (их называют также битовыми строками).

Арифметические операции «заворачиваются» подобно операциям C над целыми числами без знака (т. е. представление большого значения W битами сохраняет лишь младшие W битов этого значения). В частности, P4 не имеет арифметических исключений и результат арифметической операции определён для всех возможных входных значений.

Архитектура платформ P4 может поддерживать арифметику с насыщением. Все операции с насыщением ограничены фиксированным диапазоном от минимального до максимального значения. Арифметика с насыщением имеет преимущества, особенно при использовании в счётчиках. Результат достижения максимума в счётчике с насыщением значительно ближе к реальному результату, нежели переполнение счётчика и начало отсчёта с 0. Согласно Wikipedia, арифметика с насыщением численно близка к верному ответу, насколько это возможно. Для 8-битовой двоичной арифметики со знаком в случае корректного ответа 130 гораздо менее удивляет получение ответа 127 в арифметике с насыщением, нежели −126 от модульной арифметики. Аналогично для 8-битовой двоичной арифметики без знака при корректном ответе 258 меньшим сюрпризом будет получение ответ 255 от арифметики с насыщением, нежели 2 от модульной арифметики. В настоящее время P4 определяет операции с насыщением лишь для сложения и вычитания. Для целых чисел без знака размером W минимальным значением является 0, а максимальным 2W-1. Приоритет операций сложения и вычитания с насыщением совпадает с приоритетом тех же операций в модульной арифметике.

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

  • Проверка равенства битовых строк одного размера обозначается == и даёт логический результат.

  • Проверка неравенства битовых строк одного размера обозначается != и даёт логический результат.

  • Сравнение беззнаковых чисел одного размера — <, >, <=, >= даёт логический результат.

Перечисленные ниже операции возвращают результат bit-string при работе с битовыми строками одного размера.

  • Отрицание или смена знака (-) выполняется вычитанием значения из 2W. Результатом служит целое число без знака с тем же размером. Семантика совпадает с принятой в C для целых чисел без знака.

  • Унарный плюс (+) реально не делает ничего.

  • Сложение (+) является ассоциативной операцией. Результат получается путём отсечки3 полученной суммы до нужного размера (как в C).

  • Вычитание (-). Результатом является целое число без знака с тем же типом, что и у операндов. Результат вычисляется путём сложения первого операнда с отрицанием второго (как в C).

  • Умножение (*). Результат получается путём отсечки произведения до нужного размера. Архитектура P4 может вносить дополнительные ограничения, например, разрешать умножение лишь на степени 2.

  • Побитовая операция И между двумя операндами одного размера (&).

  • Побитовая операция ИЛИ между двумя операндами одного размера (|).

  • Побитовое дополнение одной битовой строки (~).

  • Побитовая операция Исключительное-ИЛИ (XOR) между двумя операндами одного размера (^).

  • Сложение с насыщением (|+|).

  • Вычитание с насыщением (|-|).

Для битовых строк поддерживаются также описанные ниже операции.

  • Извлечение непрерывного набора битов, называемое «нарезкой» (slice), обозначается [m:l], где m и l должны быть положительными целыми числами, известными при компиляции и m >= l. Результатом является строка битов размером m — l + 1, включая биты от l (младший бит результата) до m (старший) исходного операнда. Выполнение условий 0 <= l < W и l <= m < W проверяется статически (W — размер исходной строки битов). Отметим, что обе конечные точки извлечения включаются в результат. Границы нужны в момент компиляции, чтобы можно было рассчитать размер результата. Нарезки относятся к l-value, поэтому P4 поддерживает для них присваивание e[m:l] = x . В этом случае устанавливаются биты от m до l строки e в соответствии с битами x, а остальные биты не меняются. «Нарезка» числа без знака является числом без знака.

  • Логический сдвиг влево или вправо на известное в процессе работы целое число без знака обозначается << и >>. При сдвиге влево левый операнд является беззнаковым, а правый должен быть выражением типа bit<S> или неотрицательным целочисленным литералом. Результат имеет тот же тип, что был у левого операнда. Сдвиг на величину, превышающую размер, обнуляет все биты.

8.6. Операции над целыми числами фиксированного размера со знаком

В этом разделе рассмотрены все операции, которые могут быть выполнены над выражениями типа int<W> для данного W. Напомним, что int<W> обозначает целые числа со знаком W-bit, представленные дополнением до 2.

В общем случае арифметические операции P4 не детектируют переполнения или исчерпания — операции просто «начинают отсчёт с 0 (wrap around), как в операциях C с целыми числами без знака. Поэтому попытка представить большое число размером W будет сохранять лишь младшие W битов значения.

P4 поддерживает арифметику с насыщением (сложение и вычитание) для целых чисел со знаком. Платформы могут отвергать арифметические операции с насыщением. Для целого числа со знаком размера W минимальным значением является -2(W-1), а максимальным 2(W-1)-1.

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

Все двоичные операции (кроме сдвига) требуют совпадения типа (наличие знака) и размера операндов. В противном случае компилятор сообщает об ошибке. Компилятор не использует неявного приведения для разнотипных операндов. Во всех операциях (кроме сдвига) P4 не позволяет комбинировать операнды со знаком и без знака.

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

Ниже перечислены операции, поддерживаемые для данных типа int<W>. Эти операции требуют однотипных операндов, а результат всегда имеет размер левого операнда.

  • Отрицание или смена знака (-).

  • Унарный плюс (+) реально не делает ничего.

  • Сложение (+).

  • Вычитание (-).

  • Сравнение на равенство (==) и неравенство (!=), дающее логический результат.

  • Численные сравнения <, <=, >, и >=, дающие логический результат.

  • Умножение (*). Размер результата совпадает с размером операндов. Архитектура P4 может вносить дополнительные ограничения, например, умножение лишь на степени 2.

  • Сложение с насыщением (|+|).

  • Вычитание с насыщением (|-|).

  • Арифметический сдвиг влево (<<) и вправо (>>). Левый операнд имеет знак, а правый должен быть беззнаковым типа bit<S> или неотрицательным целочисленным литералом. Результат всегда имеет тип левого операнда. Сдвиг влево ведёт себя точно так же, как для чисел без знака. Сдвиг на число, превышающее размер, ведёт к корректному результату:

    • все нули при сдвиге влево;

    • все нули при сдвиге вправо на положительное значение;

    • все 1 при сдвиге вправо на положительное значение.

  • Извлечение непрерывного набора битов, называемое «нарезкой» (slice), обозначается [m:l], где m и l должны быть положительными целыми числами, известными при компиляции и m >= l. Результатом является целое число без знака размером m — l + 1, включая биты от l (младший бит результата) до m (старший) исходного операнда. Выполнение условий 0 <= l < W и l <= m < W проверяется статически (W — размер исходной строки битов). Отметим, что обе конечные точки извлечения включаются в результат. Границы нужны в момент компиляции, чтобы можно было рассчитать размер результата. Нарезки относятся к l-value, поэтому P4 поддерживает для них присваивание e[m:l] = x . В этом случае устанавливаются биты от m до l строки e в соответствии с битами x, а остальные биты не меняются. «Нарезка» числа без знака является числом без знака.

8.6.1. Конкатенация

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

8.6.2. Замечания о сдвиге

Сдвиги (со знаком или без знака) имеют ряд рассмотренных ниже особенностей.

  • Сдвиг вправо отличается при для чисел со знаком и без него, сдвиг числа со знаком является арифметическим.

  • Сдвиг на отрицательное значение не имеет явной семантики и система типизации P4 считает его некорректным.

  • В отличие от C сдвиг на величину, превышающую размер даёт чётко определённый результат.

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

Рассмотрим несколько примеров.

bit<8> x;
bit<16> y;
bit<16> z = y << x;
bit<16> w = y << 1024;

Как отмечено выше, P4 даёт строго определённый результат при сдвиге, превышающем размер (в отличие от C).

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

8.7. Операции над целыми числами произвольной точности

Тип int обозначает целые числа произвольной точности (разрядности). Для всех выражений типа int значения должны быть известны в момент компиляции. Поддерживаемые для типа int операции P4 перечислены ниже.

  • Отрицание или смена знака (-).

  • Унарный плюс (+) реально не делает ничего.

  • Сложение (+).

  • Вычитание (-).

  • Сравнение на равенство (==) и неравенство (!=), дающее логический результат.

  • Численные сравнения <, <=, >, и >=, дающие логический результат.

  • Умножение (*).

  • Деление одного положительного значения на другое с отсечкой (/).

  • Деление одного положительного значения на другое по модулю (%).

  • Арифметический сдвиг влево (<<) и вправо (>>). Результат сдвига имеет тип int. Правый операнд должен быть положительной константой. Выражение a << b эквивалентно a × 2b, а a >> b — ⌊a/2b ⌋.

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

Все расчёты со значениями int выполняются без потери информации. Например, перемножение двух 1024-битовых значений может дать результат размером 2048 битов (отметим, что конкретное представление значений int не задано). Значения int можно привести к типу bit<w> и int<w>. Приведение int к значению с фиксированные размером будет сохранять соответствующее число младших битов. При потере старших битов компилятору следует выдавать предупреждение.

Отметим, что побитовые операции (|, &, ^, ~) не определены для типа int. Кроме того, не допускаются операции деления (в том числе по модулю) на отрицательное число. Арифметика с насыщением не поддерживается для целых чисел с производной разрядностью.

8.8. Операции над битовыми строками переменного размера

Для поддержки анализа заголовков с полями переменного размера в P4 служит тип varbit. При каждом объявлении этого типа статически задаётся максимальный размер. До инициализации динамический размер битовой строки остаётся неизвестным. Для таких строк поддерживается ограниченный набор операций.

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

  • Сравнение двух однотипных полей varbit на равенство и неравенство. Поля varbit считаются равными при совпадении динамического размера и всех битов в рамках этого размера.

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

  • Анализатор извлекает данные в заголовок переменного размера с использованием двухаргументного метода extract во внешнем объекте packet_in (12.8.2. Извлечение при переменном размере), устанавливая динамический размер объекта.

  • Метод emit внешнего объекта packet_out может выполняться для заголовков и некоторых других типов (15. Сборка пакета), содержащих поля varbit. Вызов emit вставляет битовую строку переменного размера с известным динамическим размером в создаваемый пакет.

8.9. Приведение типов

P4 поддерживает ограниченное приведение типов, записываемое в форме (t) e, где t указывает тип, а e — выражение. Приведение возможно лишь для базовых типов. Это может показаться неудобным для программистов, но обеспечивает ряд преимуществ:

  • однозначное указание намерений пользователя;

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

  • снижается число ситуаций, описываемых в спецификации P4 (некоторые платформы могут не поддерживать приведение типов).

8.9.1. Явное приведение

Ниже перечислены корректные приведения типов в P4:

  • bit<1> <-> bool преобразует 0 в false, 1 — в true и обратно;

  • int<1> -> bool преобразует 0 в false, 1 — в true и обратно (иные значения не приводятся);

  • int<W> -> bit<W> сохраняет все биты неизменными, переводя отрицательные числа в положительные;

  • bit<W> -> int<W> сохраняет все биты неизменными, переводя числа со старшим битом 1 в отрицательные;

  • bit<W> -> bit<X> отсекает значение при W > X и дополняет нулями при W <= X.

  • int<W> -> int<X> отсекает значение при W > X и добавляет бит знака при W < X.

  • int -> bit<W> преобразует целое число в достаточно большое дополнение до 2 для предотвращения потери информации, после чего отсекает результат до размера W; компилятору следует выдавать предупреждение о переполнении или преобразовании в отрицательное число;

  • int -> int<W> преобразует целое число в достаточно большое дополнение до 2 для предотвращения потери информации, после чего отсекает результат до размера W; компилятору следует выдавать предупреждение о переполнении;

  • приведение между парой типов, заданных typedef, эквивалентное одной из приведённых выше комбинаций;

  • приведение между типом, заданным type, и исходным типом;

  • приведение между enum с явным типом и исходным типом.

8.9.2. Неявное приведение

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

enum bit<8> E {
	a = 5;
}
bit<8>		x;
bit<16>	y;
int<8>		z;

компилятор добавит неявные приведения, показанные ниже.

  • x + 1 станет x + (bit<8>)1;

  • z < 0 станет z < (int<8>)0;

  • x << 13 станет 0 с выдачей предупреждения о переполнении;

  • x | 0xFFF станет x | (bit<8>)0xFFF с выдачей предупреждения о переполнении;

  • x + E.a станет x + (bit<8>)E.a.

8.9.3. Недействительные арифметические выражения

Многие из арифметических выражений, доступных в других языках, не разрешены в P4. Для иллюстрации рассмотрим пример.

bit<8>		x;
bit<16>	y;
int<8>		z;

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

Выражение

Причина непригодности

Альтернативы

x + y

Разные размеры

(bit<16>)x + y
x + (bit<8>)y

x + z

Разные знаки

(int<8>)x + z
x + (bit<8>)z

(int<8>)y

Невозможно изменить сразу знак и размер

(int<8>)(bit<8>)y
(int<8>)(int<16>)y

y + z

Разные знаки и размеры

(int<8>)(bit<8>)y + z
y + (bit<16>)(bit<8>)z
(bit<8>)y + (bit<8>)z
(int<16>)y + (int<16>)z

x << z

Левый операнд сдвига не может иметь знака

x << (bit<8>)z

x < z

Разные знаки

X < (bit<8>)z
(int<8>)x < z

1 << x

Размер значения 1 неведом

32w1 << x

~1

Побитовая операция над int

~32w1

5 & -3

Побитовая операция над int

32w5 & -3

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

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

tuple<bit<32>, bool> x = { 10, false };

Доступ к полям кортежа возможен с использованием синтаксиса индексов массива x[0], x[1]. Индексы должны быть константами во время компиляции, чтобы проверка типов могла статически идентифицировать поля.

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

8.11. Операции над списками

Выражения списков указываются в фигурных скобках с перечислением всех элементов через запятую.

expression ...
	| '{' expressionList '}'
expressionList
	: /* пусто */
	| expression
	| expressionList ',' expression
	;

Типом выражения со списком является tuple (7.2.8. Синтезируемые типы данных). Выражения со списками могут присваиваться типам tuple, struct или header, а также передаваться методам в качестве аргументов, однако выражения со списками не являются l-value. Списки могут быть вложенными. Например, приведённый ниже фрагмент кода использует выражение со списком для одновременной передачи нескольких полей заголовка системе обучения.

extern LearningProvider {
	void learn<T>(in T data);
}
LearningProvider() lp;

lp.learn( { hdr.ethernet.srcAddr, hdr.ipv4.src } );

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

struct S {
	bit<32> a;
	bit<32> b;
}
const S x = { 10, 20 }; // a = 10, b = 20

Выражения со списками можно также применять для инициализации переменных с типом tuple.

tuple<bit<32>, bool> x = { 10, false };

Пустой список имеет тип tuple<> — кортеж без элементов.

8.12. Выражения со значением struct

Можно написать выражение, оценка (расчёт) которого даёт тип struct или header. Синтаксис выражения имеет вид

expression ...
	| '{' kvList '}'
	| '(' typeRef ')' expression
	;
kvList
	: kvPair
	| kvList "," kvPair
	;
kvPair
	: name "=" expression
	;

Для такого выражения typeRef задаёт имя типа структуры или заголовка и может быть опущено, если его можно вывести из контекста, например, при инициализации переменной с типом struct. Ниже приведён пример использования выражения в проверке равенства.

struct S {
	bit<32> a;
	bit<32> b;
}
S s;
// Сравнение с выражением типа struct
bool b = s == (S) { a = 1, b = 2 };

Выражения struct можно использовать в правой части операций присваивания, в сравнениях, выражениях полей выбора, а также в качестве аргументов функций, методов или действий. Эти выражения не могут быть l-value.

8.13. Операции над set

Некоторые выражения P4 обозначают наборы значений (set<T> для некого T, 7.2.8.1. Тип set). Эти выражения могут появляться лишь в ограниченном контексте — анализаторах и постоянных записях таблиц. Например, выражение select (12.6. Выражения для выбора) может иметь показанную ниже структуру.

select (expression) {
	set1: state1;
	set2: state2;
	// Остальные метки опущены
}

Здесь выражения set1, set2 и т. д. преобразуются в наборы значений, которые select проверяет на принадлежность к заданным меткам.

keysetExpression
	: tupleKeysetExpression
	| simpleKeysetExpression
	;

tupleKeysetExpression
	: '(' simpleKeysetExpression ',' simpleExpressionList ')'
	;

simpleExpressionList
	: simpleKeysetExpression
	| simpleExpressionList ',' simpleKeysetExpression
	;

simpleKeysetExpression
	: expression
	| DEFAULT
	| DONTCARE
	| expression MASK expression
	| expression RANGE expression
	;

Операторы mask (&&&) и range (..) имеют одинаковый приоритет, который выше приоритета &.

8.13.1. Одноэлементные наборы

В контексте set (набор, множество) выражения обозначают одноэлементные наборы. Например, во фрагменте

select (hdr.ipv4.version) {
	4: continue;
}

метка 4 обозначает набор с единственным элементом 4.

8.13.2. Универсальный набор

В контексте set выражение default или _ обозначает универсальный набор, содержащий все возможные значения данного типа

select (hdr.ipv4.version) {
	4: continue;
	_: reject;
}

8.13.3. Маски

Инфиксный оператор &&& принимает два аргумента типа bit<W> или сериализованных enum и создаёт значение типа set<ltype>, где ltype является типом левого аргумента. Значение справа служит маской, где каждый бит 0 указывает, что соответствующий бит не имеет значения (don’t care). Более формально, набор, обозначенный a &&& b, определяется как

a &&& b = { c of type bit<W>, где a & b = c & b }

Например,

8w0x0A &&& 8w0x0F

Обозначает набор из 16 разных 8-битовых значений с битовой маской XXXX1010, где X может принимать любое значение. Отметим, что может быть много способов указать набор ключей с использованием оператора маскирования, например, 8w0xFA &&& 8w0x0F даст такой же набор, что и приведённое выше выражение.

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

8.13.4. Диапазоны

Инфиксный оператор .. принимает два аргумента одного типа T, в качестве которого может служить bit<W> или int<W> и создаёт значение типа set<T>. Множество содержит все значения от левого до правого операнда включительно. Например,

4w5 .. 4w8

обозначает 4w5, 4w6, 4w7, 4w8.

8.13.5. Произведение множеств

Можно комбинировать множества (set) с помощью декартова произведения

select(hdr.ipv4.ihl, hdr.ipv4.protocol) {
	(4w0x5, 8w0x1): parse_icmp;
	(4w0x5, 8w0x6): parse_tcp;
	(4w0x5, 8w0x11): parse_udp;
	(_, _): accept; }

Типом произведения множеств является множество кортежей.

8.14. Операции над типом struct

Единственной операцией для выражения типа struct является доступ к полям на основе нотации с точкой (.), например, s.field. Если s является l-value, то s.field также будет l-value. P4 позволяет копировать структуры с использованием операторов присваивания, когда источник и назначение одинаковы по структуре. Кроме того, структуру можно инициализировать выражением списка, как описано в параграфе 8.11. Операции над списками, или инициализатором структуры, как описано в следующем параграфе. В обоих случаях должны инициализироваться все поля структуры.

Две структуры можно сравнить на равенство (==) или неравенство (!=), если они имеют один тип и все поля могут быть сравнимы на равенство. Две структуры считаются равными тогда и только тогда, когда в них равны все соответствующие поля.

8.15. Инициализаторы структур

Структуры можно инициализировать с помощью выражений, значениями которых является структура (8.12. Выражения со значением struct), как показано ниже.

struct S {
	bit<32> a;
	bit<32> b;
}
const S x = { a = 32, b = 20 };
const S x = (S){ a = 32, b = 20 }; // эквивалент

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

8.16. Операции над заголовками

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

  • isValid() возвращает значение бита validity в заголовке;

  • setValid() устанавливает для бита validity значение true (применимо лишь к l-value);

  • setInvalid() устанавливает для бита validity значение false (применимо лишь к l-value).

Выражение h.minSizeInBits() определено для любого h с типом header. Значением выражения является сумма размеров всех полей h, при этом поля varbit учитываются с размером 0. Выражение h.minSizeInBits() является константой в момент компиляции и имеет тип int. Выражение h.minSizeInBytes() похоже на h.minSizeInBits(), но возвращает общий размер полей заголовка в байтах с округлением в большую сторону, если размер заголовка не содержит целого числа байтов. h.minSizeInBytes() = (h.minSizeInBits() + 7) >> 3.

Подобно структурам, объект header можно инициализировать выражением со списком (8.11. Операции над списками), где содержатся все поля заголовка в нужном порядке или инициализатором структуры (8.14. Операции над типом struct). Инициализированный заголовок автоматически становится действительным.

header H { bit<32> x; bit<32> y; }
H h;
h = { 10, 12 };		// Это также делает заголовок h действительным
h = { y = 12, x = 10 };	// то же самое

Два однотипных заголовка можно сравнить на равенство (==) или неравенство (!=). Заголовки считаются равными при совпадении значений всех полей, включая validity. В параграфе 8.22. Чтение неинициализированных значений и запись полей в недействительные заголовки описано поведение в случаях считывания полей неинициализированного заголовка или записи в заголовок, который не является действительным.

8.17. Операции над стеком заголовков

Стек заголовков является массивом фиксированного размера с однотипными заголовками. Действительные элементы стека заголовков не обязаны быть непрерывными. P4 поддерживает набор операций для стеков заголовков. Стек заголовков hs типа h[n] можно описать приведённым ниже псевдокодом.

// объявление типа
bit hs_t {
	bit<32> 	nextIndex;
	bit<32> 	size;
	h[n] 		data;	// обычный массив
}

// Объявление и создание экземпляра
hs_t hs;
hs.nextIndex = 0;
hs.size = n;

Интуитивно стек заголовков можно представить как структуру, содержащую обычный массив заголовков hs и счётчик nextIndex, который может служить для упрощения создания анализаторов для стеков заголовков, как описано ниже. Счётчик nextIndex инициализируется значением 0.

Для стека заголовков hs размером n приведённые ниже выражения будут действительны.

  • hs[index] указывает заголовок в конкретной позиции внутри стека. Если hs является l-value, результат также будет l-value. Заголовок может быть недействительным. Некоторые реализации могут требовать, чтобы выражение index было известно при компиляции. Компилятор P4 должен выдавать ошибку, если значение индекса при компиляции выходит за рамки. Доступ к стеку заголовков hs по индексу меньше 0 или больше hs.size возвращает неопределённое значение (8.22. Чтение неинициализированных значений и запись полей в недействительные заголовки).

    Индекс является выражением, которое должно иметь один из указанных ниже типов:

    • int — целое число «бесконечной» точности (7.1.6.5. Целые числа “бесконечной точности”);

    • bit<W> — целое число без знака размером W битов (W >= 1, 7.1.6.2. Целые числа без знака (bit-string));

    • int<W> — целое число со знаком размером W битов (W >= 1, 7.1.6.3. Целые числа со знаком);

    • преобразованный в последовательную форму тип enum с базой bit<W> или int<W> (7.2.1. Перечисляемые типы).

  • hs.size возвращает 32-битовое целое число без знака, указывающее размер стека заголовков (константа в момент компиляции).

  • Присваивание из стека заголовков hs в другой стек требует, чтобы оба стека имели один тип и размер. Копируются все компоненты hs, включая его элементы, биты validity и nextIndex.

Чтобы помочь программистам создавать анализаторы для стеков заголовков, P4 также предлагает операции с автоматическим прохождением стека элементов при синтаксическом анализе.

  • hs.next может применяться только в анализаторах и даёт ссылку на элемент стека с индексом hs.nextIndex. Если nextIndex не меньше размера стека, результатом оценки будет переход в состояние reject с ошибкой error.StackOutOfBounds. Если hs является l-value, индекс hs.next также будет l-value.

  • hs.last может применяться только в анализаторах и даёт ссылку на элемент стека с индексом hs.nextIndex — 1, если такой элемент имеется. Если nextIndex меньше 1 или превышает размер, результатом оценки будет переход в состояние reject с установкой ошибки error.StackOutOfBounds. В отличие от hs.next ссылка никогда не является l-value.

  • hs.lastIndex может применяться только в анализаторах и даёт 32-битовое целое число без знака, которое представляет индекс hs.nextIndex — 1. Если nextIndex = 0, оценка выражение ведёт к неопределённому состоянию.

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

  • hs.push_front(int count) смещает hs «вправо» на count и первые count элементов становятся недействительными, а последние count элементов стека отбрасываются. Счётчик hs.nextIndex увеличивается на count. Аргумент count должен быть положительным целым числом, известным при компиляции. Результат имеет тип void.

  • hs.pop_front(int count) смещает hs «влево» на count (т. е. элемент count копируется в элемент 0). Последние count становятся недействительными, счётчик hs.nextIndex уменьшается на count. Аргумент count должен быть положительным целым числом, известным при компиляции. Результат имеет тип void.

Приведённый ниже псевдокод определяет поведение push_front и pop_front.

void push_front(int count) {
	for (int i = this.size-1; i >= 0; i -= 1) {
		if (i >= count) {
			this[i] = this[i-count];
		} else {
			this[i].setInvalid();
		}
	}
	this.nextIndex = this.nextIndex + count;
	if (this.nextIndex > this.size) this.nextIndex = this.size;
		// this.last, this.next, this.lastIndex корректируются с помощью this.nextIndex
}

void pop_front(int count) {
	for (int i = 0; i < this.size; i++) {
		if (i+count < this.size) {
			this[i] = this[i+count];
		} else {
			this[i].setInvalid();
		}
	}
	if (this.nextIndex >= count) {
		this.nextIndex = this.nextIndex - count;
	} else {
		this.nextIndex = 0;
	}
	// this.last, this.next, this.lastIndex корректируются с помощью this.nextIndex
}

Два стека заголовков можно сравнить на равенство (==) или неравенство (!=) лишь в том случае, когда они имеют элементы одного типа и совпадают по размеру. Два стека считаются одинаковыми, если все их соответствующие элементы равны друг другу. Значение nextIndex не учитывается при проверке равенства.

8.18. Операции над объединениями заголовков

Переменная, объявленная с типом union, исходно недействительна, например

header H1 {
	bit<8> f;
}
header H2 {
	bit<16> g;
}
header_union U {
	H1 h1;
	H2 h2;
}

U u; // u недействительна

Это также предполагает, что каждый из заголовков h1 — hn в объединении заголовков исходно недействителен. В отличие от заголовков объединение невозможно инициализировать. Однако validity для объединения заголовков можно обновить путём присваивания действительного заголовка одному из элементов объединения.

U u;
H1 my_h1 = { 8w0 }; // my_h1 действителен
u.h1 = my_h1;		// u и u.h1 действительны

Можно также присвоить объединению список элементов

U u;
u.h2 = { 16w1 };	// u и u.h2 действительны

или установить биты validity напрямую

U u;
u.h1.setValid();	// u и u.h1 действительны
H1 my_h1 = u.h1;	// my_h1 действителен, но включает неопределённое значение

Отметим, что считывание неинициализированного заголовка даёт неопределённое значение, даже если заголовок действителен. Более формально — если u является выражением типа union U с полями диапазона hi, для манипуляций с u можно использовать указанные ниже операции.

  • u.hi.setValid() устанавливает в битах validity значение true для заголовка hi и false для всех остальных, что означает возврат незаданного значения при чтении этих заголовков.

  • u.hi.setInvalid() — если бит validity для любого члена u имеет значение true, для него устанавливается значение false, что означает возврат незаданного значения при чтении любого заголовка.

Можно считать присваивание объединению заголовков

u.hi = e

эквивалентом

u.hi.setValid();
u.hi = e;

если заголовок e действителен и

u.hi.setInvalid();

в противном случае.

Разрешены операции присваивания между однотипными объединениями заголовков. Присваивание u1 = u2 копирует полное состояние объединения u2 в u1. Если объединение u2 действительно, в нем имеется тот или иной действительный заголовок u2.hi. Присваивание будет вести себя как u1.hi = u2.hi. Если u2 не является действительным, u1 станет недействительным (т. е. все действительные заголовки в u1 станут недействительными).

Метод u.isValid() возвращает true, если действителен любой из элементов объединения и false — в остальных случаях. Методы setValid() и setInvalid() не определены для объединений заголовков.

Предоставление выражения типа union для выдачи (emit) ведёт к выдаче единственного действительного заголовка, если такой имеется. Ниже приведён пример использования объединения заголовков для унифицированного представления IPv4 и IPv6.

header_union IP {
	IPv4 ipv4;
	IPv6 ipv6;
}

struct Parsed_packet {
	Ethernet ethernet;
	IP ip;
}

parser top(packet_in b, out Parsed_packet p) {
	state start {
		b.extract(p.ethernet);
		transition select(p.ethernet.etherType) {
			16w0x0800 : parse_ipv4;
			16w0x86DD : parse_ipv6;
		}
	}

	state parse_ipv4 {
		b.extract(p.ip.ipv4);
		transition accept;
	}

	state parse_ipv6 {
		b.extract(p.ip.ipv6);
		transition accept;
	}
}

Можно также использовать объединения для анализа (выбранных) опций TCP, как показано ниже.

header Tcp_option_end_h {
	bit<8> kind;
}
header Tcp_option_nop_h {
	bit<8> kind;
}
header Tcp_option_ss_h {
	bit<8>	kind;
	bit<32> maxSegmentSize;
}
header Tcp_option_s_h {
	bit<8>	kind;
	bit<24> scale;
}
header Tcp_option_sack_h {
	bit<8>	kind;
	bit<8>	length;
	varbit<256>	sack;
}
header_union Tcp_option_h {
	Tcp_option_end_h	end;
	Tcp_option_nop_h	nop;
	Tcp_option_ss_h	ss;
	Tcp_option_s_h	s;
	Tcp_option_sack_h	sack;
	
typedef Tcp_option_h[10] Tcp_option_stack;

struct Tcp_option_sack_top {
	bit<8> kind;
	bit<8> length;
}

parser Tcp_option_parser(packet_in b, out Tcp_option_stack vec) {
	state start {
		transition select(b.lookahead<bit<8>>()) {
			8w0x0 : parse_tcp_option_end;
			8w0x1 : parse_tcp_option_nop;
			8w0x2 : parse_tcp_option_ss;
			8w0x3 : parse_tcp_option_s;
			8w0x5 : parse_tcp_option_sack;
		}
	}
	state parse_tcp_option_end {
		b.extract(vec.next.end);
		transition accept;
	}
	state parse_tcp_option_nop {
		b.extract(vec.next.nop);
		transition start;
	}
	state parse_tcp_option_ss {
		b.extract(vec.next.ss);
		transition start;
	}
	state parse_tcp_option_s {
		b.extract(vec.next.s);
		transition start;
	}
	state parse_tcp_option_sack {
		bit<8> n = b.lookahead<Tcp_option_sack_top>().length;
		// n указывает общий размер опции TCP SACK в байтах.
		// Размер varbit-поля sack в заголовке 
		// Tcp_option_sack_h составляет, таким образом, n-2 байт.
		b.extract(vec.next.sack, (bit<32>) (8 * n - 16));
		transition start;
	}
}

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

8.19. Вызовы методов и функций

Методы и функции можно вызывать с использованием показанного ниже синтаксиса.

expression
	: ...
	| expression '<' realTypeArgumentList '>' '(' argumentList ')'
	| expression '(' argumentList ')'
argumentList
	: /* пусто */
	| nonEmptyArgList
	;
nonEmptyArgList
	: argument
	| nonEmptyArgList ',' argument
	;
argument
	: expression	/* позиционный аргумент */
	| name '=' expression	/* именованный аргумент */
	| DONTCARE
	;
realTypeArgumentList
	: realTypeArg
	| realTypeArgumentList ',' typeArg
	;
realTypeArg
	: DONTCARE
	| typeRef
	;

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

extern void f(in bit<32> x, out bit<16> y);
bit<32> xa = 0;
bit<16> ya;
f(xa, ya);	// соответствие аргументов по порядку
f(x = xa, y = ya);	// соответствие аргументов по именам
f(y = ya, x = xa);	// соответствие аргументов в произвольном порядке
//f(x = xa);	-- ошибка - недостаточно аргументов
//f(x = xa, x = ya); -- ошибка - аргумент указан дважды
//f(x = xa, ya); ошибка - некоторые аргументы заданы именами
//f(z = xa, w = yz); ошибка - нет параметров с именем z и w
//f(x = xa, y = 0);	ошибка - аргумент y должен быть l-value

При вызовах используется соглашение copy-in/copy-out (6.7. Соглашения о вызовах). Для базовых функций тип аргументов можно явно указывать при вызове функции. Компилятор вставляет неявное приведение для аргументов in в методах и функциях, отмеченных в разделе 8.9. Приведение типов. Типы всех остальных аргументов должны точно совпадать с типами параметров.

Возвращаемый функцией результат отбрасывается при вызове функции в качестве оператора.

Идентификатор _ (не имеет значения) можно использовать лишь в аргументах out, когда возвращаемое в аргументе значение игнорируется в последующих операциях. При использовании в базовых функциях и методах компилятор может отвергать программу, если он не способен вывести тип для аргумента don’t care (_).

8.20. Вызовы конструкторов

Некоторые конструкции P4 обозначают ресурсы, выделяемые при компиляции. Это внешние объекты, анализаторы, блоки управления и пакеты (package). Выделение таких объектов может выполняться двумя способами:

  • вызов конструктора, являющегося выражением, которое возвращает объект соответствующего типа;

  • использование инициаторов, как описано в параграфе 10.3. Создание экземпляров.

Синтаксис вызова конструктора похож на вызов функции и может включать именованные аргументы. Конструкторы полностью оцениваются (вычисляются) при компиляции (17. Абстрактная машина P4 — оценка). Поэтому все аргументы конструктора должны быть выражениями, вычисляемыми во время компиляции.

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

extern ActionProfile {
	ActionProfile(bit<32> size);	// конструктор
}
table tbl {
	actions = { /* тело опущено */ }
	implementation = ActionProfile(1024);	// вызов конструктора
}

8.21. Операции над типами, заданными type

Для значений с типами, заданными ключевым словом type, поддерживается лишь несколько операций:

  • присваивание l-value того же типа;

  • сравнение на равенство или неравенство, если исходный тип поддерживает такое сравнение;

  • приведение к исходному типу и обратно.

type bit<32> U32;
U32 x = (U32)0;			// требуется приведение
U32 y = (U32) ((bit<32>)x + 1);	// приведение нужно для арифметики
bit<32> z = 1;
bool b0 = x == (U32)z; 		// требуется приведение
bool b1 = (bit<32>)x == z;		// требуется приведение
bool b2 = x == y;			// приведение не требуется

8.22. Чтение неинициализированных значений и запись полей в недействительные заголовки

Как отмечено в параграфе 8.17. Операции над стеком заголовков, любая ссылка на элемент стека заголовков hs[index], где index — известное во время компиляции выражение (константа), должно приводить к ошибке, если индекс выходит за пределы диапазона. В этом параграфе также определено поведение при работе выражений hs.next и hs.last и описанное здесь поведение имеет приоритет по отношению ко всем прочим описаниям этих выражений.

Все упоминания элементов стека заголовков в этом параграфе применяются лишь к выражениям hs[index], где индекс является переменной, определяемой в процессе работы, а не при компиляции. Реализации P4 могут не поддерживать hs[index], где индекс определяется переменной во время выполнения, но при поддержке таких выражений реализации следует соответствовать описанному здесь поведению.

В перечисленных ниже случаях считывание значения приведёт к использованию в поле незаданной величины.

  • Чтение поля из недействительного (invalid) в данный момент заголовка.

  • Чтение из действительного заголовка поля, не инициализированного с момента, когда заголовок стал действительным.

  • Чтение любого другого неинициализированного заголовка (например, поля struct), неинициализированной переменной в действии или элементе управления или параметра за пределами вызванного элемента управления или действия, которому не было присвоено значение в процессе выполнения действия или элемента управления (этот список не является исчерпывающим).

  • Чтение поля заголовка, который является элементом стека заголовков, где индекс выходит за пределы стека.

Вызов метода isValid() для элемента стека заголовков с индексом вне диапазона возвращает неопределённое логическое значение (true или false), но спецификация не требует определённого значения и даже согласованности значения при нескольких таких вызовах. Присваивание выходящего за пределы стека заголовков значения другому заголовку h ведёт к неопределённому состоянию h во всех переменных заголовка, включая бит validity.

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

Для неинициализированного поля или переменной типа enum или error считывание незаданного значения может приводить к отличию от значений, определённых для этого типа. Такому неопределённому значению следует по-прежнему вести к предсказуемому поведению в случаях, когда будет подходить любое действительное значение, например, следует соответствовать в приведённых ниже случаях.

  • При использовании в выражении select следует соответствовать default или _ в выражении набора ключей.

  • При использовании в качестве ключа с троичным match_kind в таблице следует соответствовать записи, где все биты поля имеют флаг don’t care.

  • При использовании в качестве ключа match_kind lpm в таблице следует соответствовать записи, где поле имеет префикс размером 0.

Рассмотрим ситуацию, где header_union u1 включает u1.h1 и u1.h2, а в данной точке программы u1.h1 является действительным, u1.h2 — недействительным. При попытке записи в поле недействительного заголовка u1.h2 может измениться любое (или все) поле действительного заголовка u1.h1. Такая запись не должна менять бит validity какого-либо из членов u1 или другие состояния, определённые в данный момент в системе, независимо от места определения этих состояний. При выполнении любого из действий:

  • запись в поле недействительного заголовка (обычного или элемента стека с индексом в пределах диапазона), не входящего в объединение заголовков (header_union);

  • запись в элемент стека заголовков с индексом за пределами диапазона;

  • вызов метода a setValid() или setInvalid() для элемента стека заголовков с индексом за пределами диапазона

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

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

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

struct Empty {    tuple<> t; }

Ниже перечислены типы, которые считаются пустыми:

  • строки битов размером 0;
  • varbit размером 0;

  • пустые кортежи (tuple<>);

  • стеки размером 0;

  • структуры без полей;

  • кортежи, все поля которых относятся к пустым типам;

  • структуры, все поля которых относятся к пустым типам.

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

8.23. Инициализация с принятыми по умолчанию значениями

Значения l-value можно инициализировать автоматически принятыми по умолчанию значениями подходящего типа с использованием синтаксиса … (7.3. Подразумеваемые значения). Значения типа struct, header, tuple можно инициализировать с использованием явно заданных и подразумеваемых значений, применяя нотацию … в инициализаторе выражения списка (не заданные явно поля будут инициализированы принятыми по умолчанию значениями). При инициализации struct, header и tuple с частичным заданием значений … нужно размещать в конце инициализатора.

struct S {
	bit<32> b32;
	bool b;
}

enum int<8> N0 {
	one = 1,
	zero = 0,
	two = 2
}

enum N1 {
	A, B, C, F
}

struct T {
	S s;
	N0 n0;
	N1 n1;
}

header H {
	bit<16> f1;
	bit<8> f2;
}

N0 n0 = ...;	// n0 инициализируется принятым по умолчанию значением 0
N1 n1 = ...;	// n1 инициализируется принятым по умолчанию значением N1.A
S s0 = ...;	// s0 инициализируется принятым по умолчанию значением { 0, false }
S s1 = { 1, ... };	// s1 инициализируется значением { 1, false }
S s2 = { b = true, ... }; // s2 инициализируется значением { 0, true }
T t0 = ...;	// t0 инициализируется значением { { 0, false }, 0, N1.A }
T t1 = { s = ..., ... }; // t1 инициализируется значением { { 0, false }, 0, N1.A }
T t2 = { s = ... }; // ошибка - нет инициализатора для полей n0 и n1
tuple<N0, N1> p = { ... }; // p инициализируется принятым по умолчанию значением { 0, N1.A }
T t3 = { ..., n0 = 2}; // ошибка - ... должно быть в конце
H h1 = ...;	// h1 инициализируется недействительным заголовком
H h2 = { f2=5, ... };	// h2 инициализируется действительным заголовком, f1 0, f2 5
H h3 = { ... };	// h3 инициализируется действительным заголовком, f1 0, f2 0

9. Объявление функции

Функции могут объявляться лишь на верхнем уровне и все параметры должны иметь направление. Язык P4 не позволяет определять рекурсивные функции.

functionDeclaration
	: functionPrototype blockStatement
	;

functionPrototype
	: typeOrVoid name optTypeParameters '(' parameterList ')'
	;

Ниже приведён пример функции, возвращающей большее из двух 32-битовых значений.

bit<32> max(in bit<32> left, in bit<32> right) {
	if (left > right)
		return left;
	return right;
}

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

10. Объявление констант и переменных

10.1. Константы

Для определения констант применяется показанный ниже синтаксис.

constantDeclaration
	: optAnnotations CONST typeRef name '=' initializer ';'
	;

initializer
	: expression
	;

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

const bit<32> COUNTER = 32w0x0;
struct Version {
	bit<32> major;
	bit<32> minor;
}
const Version version = { 32w0, 32w0 };

Выражение инициализатора должно быть известно в момент компиляции.

10.2. Переменные

Локальные переменные объявляются с типом и именем, а также могут указывать инициализатор и аннотацию.

variableDeclaration
	: annotations typeRef name optInitializer ';'
	| typeRef name optInitializer ';'
	;

optInitializer
	: /* пусто */
	| '=' initializer
	;

Объявления переменных без инициализатора не инициализируются (за исключением заголовков и связанных с ними типов, которые инициализируются как недействительные (invalid) так же, как описано для параметров out в параграфе 6.7. Соглашения о вызовах). Язык вносит некоторые ограничения на типы переменных — можно применять большинство типов P4, которые могут быть записаны явно (например, базовые типы, struct, header, стеки заголовков, tuple). Однако невозможно объявить переменные типов, которые синтезируются компилятором (например, set). Кроме того, переменные типов parser, control, package, extern должны объявляться с инициализатором (10.3. Создание экземпляров). Считывание значения неинициализированной переменной даёт неопределённый результат. Компиляторам следует пытаться детектировать такие ситуации и выдавать предупреждения.

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

  • оператор block;

  • состояние анализатора;

  • тело действия (action);

  • блок исполнения управляющего блока;

  • список локальных объявлений анализатора;

  • список локальных объявлений элемента управления.

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

10.3. Создание экземпляров

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

instantiation
	: typeRef '(' argumentList ')' name ';'
	| annotations typeRef '(' argumentList ')' name ';'
	;

Создание экземпляра записывается как вызов конструктора с указанием имени и всегда выполняется во время компиляции (17.1. Известные при компиляции значения). Результатом служит создание объекта с указанным именем и его привязка к результату вызова конструктора. Отметим, что аргументы создания экземпляра можно задавать именами. Например, экземпляр гипотетического банка счётчиков можно создать, как показано ниже.

// Из библиотеки платформы
enum CounterType {
	Packets,
	Bytes,
	Both
}
extern Counter {
	Counter(bit<32> size, CounterType type);
	void increment(in bit<32> index);
}
// Программа пользователя
control c(/* параметры опущены */) {
	Counter(32w1024, CounterType.Both) ctr;	// создание экземпляра
	apply { /* тело опущено */ }
}

10.3.1. Ограничения для создания экземпляров на верхнем уровне

Программы P4 не могут создавать элементы управления и синтаксические анализаторы в пакете верхнего уровня (top-level package). Это ограничение нацелено на то, чтобы обеспечить размещение большинства состояний в самой архитектуре или локальном элементе управления синтаксического анализатора. Ниже приведён пример некорректного создания экземпляра.

// Программа
control c(/* параметры опущены */) { /* тело опущено */ }
c() c1;	// Недопустимое создание экземпляра на верхнем уровне

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

11. Операторы

Каждый оператор P4 (кроме block) должен завершаться точкой с запятой (;). Операторы могут указываться внутри:

  • состояний анализатора;

  • блоков управления;

  • действий.

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

statement
	: assignmentOrMethodCallStatement
	| conditionalStatement
	| emptyStatement
	| blockStatement
	| exitStatement
	| returnStatement
	| switchStatement
	;

assignmentOrMethodCallStatement
	: lvalue '(' argumentList ')' ';'
	| lvalue '<' typeArgumentList '>' '(' argumentList ')' ';'
	| lvalue '=' expression ';'
	;

Кроме того, анализаторам следует поддерживать оператор transition (12.5. Операторы смены (перехода) состояния).

11.1. Оператор присваивания

В операторах присваивания (=) сначала проверяется, относится ли левое выражение к l-value, затем определяется значение правого выражения и результат копируется в l-value. Производные типы (например, struct) копируются рекурсивно с копированием всех полей заголовка, включая биты validity. Присваивание не определено для внешних объектов.

11.2. Пустой оператор

Пустой оператор имеет вид ; (нет операций).

emptyStatement
	: ';'
	;

11.3. Оператор блока

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

blockStatement
	: optAnnotations '{' statOrDeclList '}'
	;

statOrDeclList
	: /* пусто */
	| statOrDeclList statementOrDeclaration
	;

statementOrDeclaration
	: variableDeclaration
	| constantDeclaration
	| statement
	| instantiation
	;

11.4. Оператор возврата

Оператор return незамедлительно прерывает выполнение действия, функции или блока управления. Оператор return не разрешается использовать в анализаторах. В функциях с возвращаемым значением за оператором return следует выражение, тип которого должен соответствовать объявленному типу функции. Любые действия в стиле copy-out, заданные параметрами out или inout во включающем оператор действии, функции или элементе управления, происходят после выполнения оператора return (6.7. Соглашения о вызовах).

returnStatement
	: RETURN ';'
	| RETURN expression ';'
	;

11.5. Оператор выхода

Оператор exit незамедлительно прерывает выполнение всех выполняющихся в данное время блоков. Прерывается текущее действие (если оператор вызван внутри action), текущий элемент управления и все вызывающие их. Оператор exit нельзя использовать в анализаторах и функциях.

Любые действия copy-out, заданные параметрами с направлением out или inout включающего оператор действия или элемента управления и всех вызывающих его, выполняются после выполнения оператора exit (6.7. Соглашения о вызовах.

exitStatement
	: EXIT ';'
	;

11.6. Условный оператор

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

conditionalStatement
	: IF '(' expression ')' statement
	| IF '(' expression ')' statement ELSE statement
	;

Во вложенных конструкциях с условиями else относится к внутреннему (наиболее близкому) оператору if, у которого нет оператора else.

11.7. Оператор выбора

Оператор switch можно применять только в блоках управления.

switchStatement
	: SWITCH '(' expression ')' '{' switchCases '}'
	;

switchCases
	: /* пусто */
	| switchCases switchCase
	;

switchCase
	: switchLabel ':' blockStatement
	| switchLabel ':'	// «пропуск» (fall-through)
	;

switchLabel
	: name
	| DEFAULT
	;

nonBraceExpression
     	: INTEGER
     	| TRUE
     	| FALSE
     	| STRING_LITERAL
     	| nonTypeName
     	| dotPrefix nonTypeName
     	| nonBraceExpression '[' expression ']'
     	| nonBraceExpression '[' expression ':' expression ']'
     	| '(' expression ')'
     	| '!' expression %prec PREFIX
     	| '~' expression %prec PREFIX
     	| '-' expression %prec PREFIX
     	| '+' expression %prec PREFIX
     	| typeName '.' member
     	| ERROR '.' member
     	| nonBraceExpression '.' member
     	| nonBraceExpression '*' expression
     	| nonBraceExpression '/' expression
     	| nonBraceExpression '%' expression
     	| nonBraceExpression '+' expression
     	| nonBraceExpression '-' expression
     	| nonBraceExpression '|+|' expression
     	| nonBraceExpression '|-|' expression
     	| nonBraceExpression '<<' expression
     	| nonBraceExpression '>>' expression
     	| nonBraceExpression '<=' expression
    	| nonBraceExpression '>=' expression
     	| nonBraceExpression '<' expression
     	| nonBraceExpression '>' expression
     	| nonBraceExpression '!=' expression
     	| nonBraceExpression '==' expression
     	| nonBraceExpression '&' expression
     	| nonBraceExpression '^' expression
     	| nonBraceExpression '|' expression
     	| nonBraceExpression '++' expression
     	| nonBraceExpression '&&' expression
     	| nonBraceExpression '||' expression
     	| nonBraceExpression '?' expression ':' expression
     	| nonBraceExpression '<' realTypeArgumentList '>' '(' argumentList ')'
     	| nonBraceExpression '(' argumentList ')'
     	| namedType '(' argumentList ')'
     	| '(' typeRef ')' expression
     	;

Выражение без скобок nonBraceExpression похоже на expression (раздел 8. Выражения), но не включает вариантов, начинающихся с левой (открывающей) скобки { для предотвращения синтаксической неоднозначности в операторах блоков.

Разрешены два типа выражений switch, описанных в двух следующих параграфах.

11.7.1 Оператор switch с выражением action_run

Выражение в операторе switch должно быть результатом вызова таблицы (13.2.2. Вызов блока СД).

Если за меткой оператора switch нет оператора блока, выполняется переход к следующей метке. Однако при наличии оператора блока переход к следующей метке не происходит. Это отличается от операторов выбора в C, где для предотвращения перехода к следующей метке требуется break. Допускается отсутствие действий для некоторых меток и отсутствие метки default. Если в процессе работы не найдено совпадений, просто продолжается выполнение программы. Повторение метки в операторе switch не допускается.

switch (t.apply().action_run) {
	action1:	// переход к action2:
	action2: { /* тело опущено */ }
	action3: { /* тело опущено */ }	// нет перехода от action2 к action3
	default: { /* тело опущено */ }
}

Отметим, что метка default в операторе switch используется для выполнения того или иного действия, независимо от нахождения или отсутствия ключа в таблице. Метка default не указывает отсутствие таблицы и заданное по умолчанию действие (default_action) выполняется. Метка default (при наличии) должна быть последней.

11.7.2 Оператор switch с выражением целочисленного или перечисляемого типа

Для этого варианта оператора switch выражение должно давать в результате один из указанных ниже типов:

  • bit<W>;
  • int<W>;
  • enum с указанным базовым представлением или без него;
  • error.

Все метки switch должны быть выражениями, значения которых известны при компиляции, а также должны иметь тип, который может неявно приводиться к типу выражения switch (8.9.2. Неявное приведение). Меткам switch недопустимо начинаться с левой фигурной скобки { во избежание неоднозначности восприятия блоков.

// Предположим, что выражение hdr.ethernet.etherType имеет тип bit<16> 
switch (hdr.ethernet.etherType) {
    0x86dd: { /* тело опущено */ }
    0x0800:          // пропуск с переходом к следующему телу.
    0x0802: { /* тело опущено */ }
    0xcafe: { /* тело опущено */ }
    default: { /* тело опущено */ } }

11.7.3 Замечания для всех операторов switch

Если две метки оператора switch совпадают, возникает ошибка при компиляции. Значениям меток switch не обязательно включать все возможные значения выражения switch и можно иметь принятый по умолчанию вариант (метку) switch, который при его наличии должен быть последним в операторе.

Если за меткой switch не следует оператор блока, выполняется переход к следующей метке. Однако при наличии оператора блока такого перехода не происходит. Отметим, что это отличается от операторов switch в языке C, где для предотвращения перехода в следующей метке требуется break. Если за последней меткой switch нет оператора блока, это обрабатывается как наличие пустого блока { }.

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

Если ни одна из меток не совпадает со значением выражения switch:

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

  • если метка default не задана, не выполняется ни один из вариантов switch и исполнение продолжается после завершения оператора switch без побочных эффектов (если их нет при вычислении выражения switch).

Обработка обобщённых операторов описана в отдельном файле.

12. Анализ пакета

В этом разделе описаны конструкции P4 относящиеся к синтаксическому анализу пакетов.

12.1. Состояния анализатора


Рисунок 8. Структура FSM.

Синтаксический анализатор P4 описывает конечный автомат с одним стартовым и двумя финальными состояниями. Начальное состояние всегда именуется start. Два финальных состояния называются accept (успешный анализ) и reject (отказ при анализе). Состояние start является частью анализатора, а состояния accept и reject отличаются от состояний, задаваемых программистом, и логически находятся за пределами анализатора. На рисунке 8 показана общая структура конечного автомата анализатора (FSM).

12.2. Объявление анализатора

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

parserTypeDeclaration
	: optAnnotations PARSER name optTypeParameters
	 '(' parameterList ')'
	;
parserDeclaration
	: parserTypeDeclaration optConstructorParameters
	  '{' parserLocalElements parserStates '}'
	;
parserLocalElements
	: /* пусто */
	| parserLocalElements parserLocalElement
	;
parserStates
	: parserState
	| parserStates parserState
	;

Описание optConstructorParameters, полезных при создании параметризованных анализаторов, приведено в разделе 14. Параметризация.

В отличие от объявления типа анализатора, объявление самого анализатора не может быть базовым. Например, приведённое ниже определение недействительно.

parser P<H>(inout H data) { /* тело опущено */ }

Поэтому при использовании в контексте parserDeclaration правило создания parserTypeDeclaration не должно давать параметры типа.

В любом анализаторе должно присутствовать по меньшей мере одно состояние — start. Не разрешается определять несколько состояний с одним именем, а также не допускается явное создание в анализаторе состояний с именами accept и reject — эти состояния логически отличаются от определяемых программистом.

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

parserLocalElement
	: constantDeclaration
	| variableDeclaration
	| valueSetDeclaration
	| instantiation
	;

Пример с полным объявлением анализатора приведён в параграфе 5.3. Полная программа VSS.

12.3. Абстрактная машина синтаксического анализа

Семантику синтаксического анализатора P4 можно выразить через абстрактную машину, манипулирующую структурой данных ParserModel. Ниже эта машина описана псевдокодом. Выполнение анализатора начинается из состояния start и завершается по достижении состояния reject или accept.

ParserModel {
	error	parseError;
	onPacketArrival(packet p) {
		ParserModel.parseError = error.NoError;
		goto start;
	}
}

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

12.4. Состояния анализатора

Состояния анализатора объявляются в виде

parserState
	: optAnnotations STATE name
	'{' parserStatements transitionStatement '}'
	;

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

  • объявления локальных переменных;

  • операторы присваивания;

  • вызовы методов, включая:

    • исполнение функций (например, verify для проверки действительности уже проанализированных данных);

    • исполнение методов (например, извлечение данных из пакета или расчёт контрольной суммы) и других анализаторов (12.10. Субанализаторы);

  • условные операторы;

  • переходы в другое состояние (12.5. Операторы смены (перехода) состояния).

Синтаксис операторов для анализатора использует приведённые ниже правила.

parserStatements
	: /* пусто */
	| parserStatements parserStatement
	;
parserStatement
	: assignmentOrMethodCallStatement
	| directApplication
	| variableDeclaration
	| constantDeclaration
	| parserBlockStatement
	| emptyStatement
	| conditionalStatement
	;
parserBlockStatement
	: optAnnotations '{' parserStatements '}'
	;

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

В ParserModel операторы в том или ином состоянии выполняются последовательно.

12.5. Операторы смены (перехода) состояния

Последним оператором в состоянии анализатора является необязательный оператор transition, переводящий элемент управления в иное состояние (возможно, accept или reject). Синтаксис оператора transition показан ниже.

transitionStatement
	: /* пусто */
	| TRANSITION stateExpression
	;

stateExpression
	: name ';'
	| selectExpression
	;

Выполнение оператора transition вызывает оценку (вычисление) stateExpression и переход в соответствующее состояние. В ParserModel семантику перехода можно формализовать в виде

goto eval(stateExpression)

Например, оператор

transition accept;

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

Если тело блока состояний не включает оператора transition, подразумевается переход в состояние reject.

12.6. Выражения для выбора

Выражение select ведёт к выбору состояния и использует показанный ниже синтаксис.

selectExpression
	: SELECT '(' expressionList ')' '{' selectCaseList '}'
	;

selectCaseList
	: /* пусто */
	| selectCaseList selectCase
	;

selectCase
	: keysetExpression ':' name ';'
	;

selectCase
	: keysetExpression ':' name ';'
	;

Если в выражении select expressionList имеет тип tuple<T>, каждое из выражений keysetExpression должно иметь тип set<tuple<T>>.

В ParserModel выражение select

select(e) {
	ks[0]: s[0];
	ks[1]: s[1];
	/* остальные варианты опущены */
	ks[n-2]: s[n-1];
	_ : sd;	// ks[n-1] используется по умолчанию
}

можно представить в виде псевдокода

key = eval(e);
for (int i=0; i < n; i++) {
	keyset = eval(ks[i]);
	if (keyset.contains(key)) return s[i];
}
verify(false, error.NoMatch);

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

Приведённый пример предполагает, что все метки после default или _ не используются. Компилятор в таких случаях должен выдавать предупреждение. Это показывает важное различие между выражениями select и операторами switch в других языках, поскольку keyset в выражениях select могут «перекрываться».

Типичным примером использования select является сравнение недавно извлечённого поля заголовка с набором констант, как показано ниже

header IPv4_h { bit<8> protocol; /* другие поля опущены */ }
struct P { IPv4_h ipv4; /* другие поля опущены */ }
P headers;
select (headers.ipv4.protocol) {
	8w6	: parse_tcp;
	8w17 	: parse_udp;
	_	: accept;
}
select (p.tcp.port) {
	16w0 &&& 16w0xFC00: well_known_port;
	_: other_port;
}

Выражение 16w0 &&& 16w0xFC00 описывает набор 16-битовых значений и 0 в шести старших битах.

Некоторые платформы могут поддерживать наборы значений в анализаторах (12.11. Набор значений анализатора). Для параметра типа T в наборе значений типом набора будет set<T>. Тип набора значений должен совпадать с типом всех других keysetExpression в данном выражении select и при наличии расхождений компилятор должен выдавать ошибку. В наборе значений должен использоваться тип bit<>, tuple или struct.

Например, чтобы позволить API плоскости управления задавать порты TCP в процессе работы, можно использовать

struct vsk_t {
	@match(ternary)
	bit<16> port;
}
value_set<vsk_t>(4) pvs;
select (p.tcp.port) {
	pvs: runtime_defined_port;
	_: other_port;
}

Приведённый пример позволяет API в процессе работы заполнить до 4 разных keysetExpression в value_set. Если value_set принимает в качестве параметра типа struct, API может использовать имена полей struct для указания объектов в наборе значений. Тип совпадения для поля struct задаётся аннотацией @match. Если эта аннотация не задана для поля struct, предполагается @match(exact). Одиночное поле без точного совпадения должно помещаться в struct самим полем, желательно с аннотацией @match.

12.7. Оператор verify

Оператор verify обеспечивает простую форму обработки ошибок и может вызываться лишь из анализаторов. Синтаксически использование оператора похоже на вызов функции

extern void verify(in bool condition, in error err);

Если первый аргумент имеет значение true, выполнение оператора не имеет побочных эффектов. Однако при значении false оператор вызывает незамедлительный переход в состояние reject с прерыванием анализа и установкой в parserError, связанного с анализатором, значения второго аргумента. В ParserModel семантика verify имеет вид

ParserModel.verify(bool condition, error err) {
	if (condition == false) {
		ParserModel.parserError = err;
		goto reject;
	}
}

12.8. Извлечение данных

Основная библиотека P4 включает объявление встроенного extern типа packet_in, представляющего входные пакеты из сети. Этот тип является особым и пользователь не может явно создать его экземпляр. Архитектура представляет отдельный экземпляр packet_in при создании каждого экземпляра анализатора.

extern packet_in {
	void extract<T>(out T headerLvalue);
	void extract<T>(out T variableSizeHeader, in bit<32> varFieldSizeBits);
	T lookahead<T>();
	bit<32> length();	// Метод поддерживается не всеми архитектурами
	void advance(bit<32> bits);
}

Для извлечения данных из пакета, представленного аргументом b типа packet_in, анализатор вызывает методы извлечения для b. Имеется два варианта метода извлечения — с одним аргументом для заголовков фиксированного размера и с двумя аргументами для заголовков переменного размера. Поскольку эти операции могут приводить к отказам проверок во время работы, выполнение их возможно лишь из синтаксических анализаторов.

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

Некоторые платформы могут выполнять обработку «на лету» (cut-through), т. е. начинать обработку до того, как станет известен размер пакета (пакет ещё не принят полностью). На таких платформах вызов метода packet_in.length() не может быть реализован и попытки таких вызовов должны помечаться как ошибки (во время компиляции back-end или при попытке загрузки скомпилированной программы P4 на платформе, не поддерживающей этот метод).

В ParserModel семантику packet_in можно представить с использованием абстрактной модели пакетов

packet_in {
	unsigned nextBitIndex;
	byte[] data;
	unsigned lengthInBits;
	void initialize(byte[] data) {
		this.data = data;
		this.nextBitIndex = 0;
		this.lengthInBits = data.sizeInBytes * 8;
	}
	bit<32> length() { return this.lengthInBits / 8; }
}

12.8.1. Извлечение при фиксированном размере

Метод извлечения с одним аргументом, применяемый для заголовков фиксированного размера, объявлен в форме

void extract<T>( out T headerLeftValue );

Выражение headerLeftValue должно оцениваться в l-value (6.6. Выражения для левой части) типа header с фиксированным размером. При успешном выполнении метода headerLvalue заполняется данными из пакета и для бита validity устанавливается значение true. Метод может приводить к отказам, например, при нехватке в пакете битов для заполнения заголовка. Ниже приведён фрагмент программы для извлечения заголовка Ethernet.

struct Result { Ethernet_h ethernet;	/* другие поля опущены */ }
parser P(packet_in b, out Result r) {
	state start {
		b.extract(r.ethernet);
	}
}

В ParserModel семантику извлечения с одним аргументом можно представить приведённым ниже псевдокодом. Специальный идентификатор valid$ служит для скрытого флага validity, isNext$ — для индикации получения l-value с использованием next, а nextIndex$ — для указания соответствующих свойств стека заголовков.

void packet_in.extract<T>(out T headerLValue) {
	bitsToExtract = sizeofInBits(headerLValue);
	lastBitNeeded = this.nextBitIndex + bitsToExtract;
	ParserModel.verify(this.lengthInBits >= lastBitNeeded, error.PacketTooShort);
	headerLValue = this.data.extractBits(this.nextBitIndex, bitsToExtract);
	headerLValue.valid$ = true;
	if headerLValue.isNext$ {
		verify(headerLValue.nextIndex$ < headerLValue.size, error.StackOutOfBounds);
		headerLValue.nextIndex$ = headerLValue.nextIndex$ + 1;
	}
	this.nextBitIndex += bitsToExtract;
}

12.8.2. Извлечение при переменном размере

Извлечение с двумя аргументами для заголовков переменного размера объявляется в P4 в форме

void extract<T>(out T headerLvalue, in bit<32> variableFieldSize);

Выражение headerLvalue должно быть l-value и представлять заголовок с единственным полем varbit. Выражение variableFieldSize должно оцениваться в значение bit<32>, указывающее число битов, извлекаемых в уникальное поле varbit переменной header (т. е. это не размер заголовка, а размер поля varbit). В ParserModel семантику извлечения с двумя аргументами можно выразить псевдокодом, приведённым ниже.

void packet_in.extract<T>(out T headerLvalue,
					in bit<32> variableFieldSize) {
	// платформы могут, но не обязаны включать строку проверки 
	// verify(variableFieldSize[2:0] == 0, error.ParserInvalidArgument);
	bitsToExtract = sizeOfFixedPart(headerLvalue) + variableFieldSize;
	lastBitNeeded = this.nextBitIndex + bitsToExtract;
	ParserModel.verify(this.lengthInBits >= lastBitNeeded, error.PacketTooShort);
	ParserModel.verify(bitsToExtract <= headerLvalue.maxSize, error.HeaderTooShort);
	headerLvalue = this.data.extractBits(this.nextBitIndex, bitsToExtract);
	headerLvalue.varbitField.size = variableFieldSize;
	headerLvalue.valid$ = true;
	if headerLValue.isNext$ {
		verify(headerLValue.nextIndex$ < headerLValue.size, error.StackOutOfBounds);
		headerLValue.nextIndex$ = headerLValue.nextIndex$ + 1;
	}
	this.nextBitIndex += bitsToExtract;

}

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

// Заголовок IPv4 без опций
header IPv4_no_options_h {
	bit<4>		version;
	bit<4>		ihl;
	bit<8>		diffserv;
	bit<16>	totalLen;
	bit<16>	identification;
	bit<3>		flags;
	bit<13>	fragOffset;
	bit<8>		ttl;
	bit<8>		protocol;
	bit<16>	hdrChecksum;
	bit<32>	srcAddr;
	bit<32>	dstAddr;
}
header IPv4_options_h {
	varbit<320> options;
}
struct Parsed_headers {
	// некоторые поля опущены
	IPv4_no_options_h ipv4;
	IPv4_options_h	ipv4options;
}

error { InvalidIPv4Header }

parser Top(packet_in b, out Parsed_headers headers) {
	// некоторые состояния опущены
	state parse_ipv4 {
		b.extract(headers.ipv4);
		verify(headers.ipv4.ihl >= 5, error.InvalidIPv4Header);
		transition select (headers.ipv4.ihl) {
			5: dispatch_on_protocol;
			_: parse_ipv4_options;
		}
	}
	state parse_ipv4_options {
		// используется информация из заголовка IPv4 для расчёта
		// числа извлекаемых битов
		b.extract(headers.ipv4options,
				(bit<32>)(((bit<16>)headers.ipv4.ihl - 5) * 32));
		transition dispatch_on_protocol;
	}
}

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

Метод lookahead, обеспечиваемый абстракцией packet_in, оценивает набор битов из входящего пакета без указателя nextBitIndex. Подобно extract, он будет переводить в состояние reject и возвращать ошибку, если в пакете недостаточно битов. Вызов метода имеет вид

b.lookahead<T>()

где T должен быть типом фиксированного размера. При успешной оценке lookahead возвращает значение типа T. В ParserModel семантика lookahead может выть выражена приведённым ниже псевдокодом.

T packet_in.lookahead<T>() {
	bitsToExtract = sizeof(T);
	lastBitNeeded = this.nextBitIndex + bitsToExtract;
	ParserModel.verify(this.lengthInBits >= lastBitNeeded, error.PacketTooShort);
	T tmp = this.data.extractBits(this.nextBitIndex, bitsToExtract);
	return tmp;
}

Пример с опциями TCP из параграфа 8.18. Операции над объединениями заголовков также служит иллюстрацией к применению lookahead.

state start {
	transition select(b.lookahead<bit<8>>()) {
		0: parse_tcp_option_end;
		1: parse_tcp_option_nop;
		2: parse_tcp_option_ss;
		3: parse_tcp_option_s;
		5: parse_tcp_option_sack;
	}
}
// некоторые состояния опущены
state parse_tcp_option_sack {
	bit<8> n = b.lookahead<Tcp_option_sack_top>().length;
	b.extract(vec.next.sack, (bit<32>) (8 * n - 16));
	transition start;
}

12.8.4. Пропуск битов

P4 обеспечивает два способа пропуска битов во входном пакете без передачи их в заголовок (header). Один способ заключается в извлечение в переменную _, явно задающую тип данных

b.extract<T>(_)

Другим способом служит использование метода advance, когда число пропускаемых битов известно. В ParserModel метод advance можно выразить приведённым ниже псевдокодом.

void packet_in.advance(bit<32> bits) {
	// платформы могут, но не обязаны включать строку проверки 
	// verify(bits[2:0] == 0, error.ParserInvalidArgument);
	lastBitNeeded = this.nextBitIndex + bits;
	ParserModel.verify(this.lengthInBits >= lastBitNeeded, error.PacketTooShort);
	this.nextBitIndex += bits;
}

12.9. Стеки заголовков

Стеки заголовков имеют два свойства — next и last, которые можно использовать при анализе. Рассмотрим пример, определяющий стек для представления пакетов, содержащих до 10 заголовков MPLS.

header Mpls_h {
	bit<20> label;
	bit<3>	tc;
	bit	bos;
	bit<8>	ttl;
}
Mpls_h[10] mpls;

Выражение mpls.next представляет l-value типа Mpls_h со ссылкой на элемент стека заголовков. Исходно mpls.next указывает первый элемент стека и автоматически перемещается вперёд при каждом успешном извлечении заголовка. Свойство mpls.last указывает элемент, непосредственно предшествующий следующему, если такой элемент существует. Попытка доступа к mpls.next при nextIndex не меньше размера стека вызывает переход в состояние reject и ошибку error.StackOutOfBounds. Аналогично, попытка доступа к mpls.last при nextIndex = 0 вызывает переход в состояние reject и ошибку error.StackOutOfBounds. Ниже приведён пример простого анализатора для обработки MPLS.

struct Pkthdr {
	Ethernet_h ethernet;
	Mpls_h[3] mpls;
	// другие заголовки опущены
}

parser P(packet_in b, out Pkthdr p) {
	state start {
		b.extract(p.ethernet);
		transition select(p.ethernet.etherType) {
			0x8847: parse_mpls;
			0x0800: parse_ipv4;
		}
	}
	state parse_mpls {
		b.extract(p.mpls.next);
		transition select(p.mpls.last.bos) {
			0: parse_mpls; // создаёт цикл
			1: parse_ipv4;
		}
	}
	// другие состояния опущены
}

12.10. Субанализаторы

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

parser callee(packet_in packet, out IPv4 ipv4) { /* тело опущено */ }
parser caller(packet_in packet, out Headers h) {
	callee() subparser;
 	// экземпляр вызываемого анализатора
	state subroutine {
		subparser.apply(packet, h.ipv4);	// вызов субанализатора
		transition accept;	// если субанализатор завершился состоянием accept
	}
}

Семантику вызова субанализатора можно описать следующим образом (рисунок 9):

  • состояние, вызывающее субанализатор делится на два полусостояния в операторе вызова анализатора;

  • верхняя половина включает переход в состояние start субанализатора;

  • состояние субанализатора accept ведёт к переходу в нижнюю половину текущего состояния;

  • состояние субанализатора reject переводит текущий анализатор в состояние reject.


Рисунок 9. Семантика вызова субанализатору — сверху исходная программа, снизу эквивалент.

Поскольку P4 требует объявления перед использованием, невозможно создать (взаимно) рекурсивные анализаторы.

Архитектура может (статически или динамически) ограничивать число состояний, которые анализатор может проходить при разборе пакета. Например, компилятор для конкретной платформы может отвергать анализаторы с циклом, который нельзя развернуть во время компиляции. Если анализатор прерывает работу динамически в результате исчерпания разрешённого для обработки времени, ему следует перейти в состояние reject с ошибкой error.ParserTimeout.

12.11. Набор значений анализатора

В некоторых случаях значения, определяющие переход анализатора из одного состояния в другое, нужно определять во время работы. MPLS является одним из примеров, где поле метки MPLS служит для определения того, что следует за тегом MPLS и это отображение может меняться во время работы. Для поддержки такой функциональности в P4 используется набор значений анализатора (Parser Value Set) — именованный набор значений с API среды выполнения для добавления и удаления элементов. Наборы значений объявляются локально в анализаторе. Значения следует объявлять до ссылки на них в keysetExpression и они могут применяться в выражениях select. Синтаксис объявления показан ниже.

valueSetDeclaration
	: optAnnotations
		VALUESET '<' baseType '>' '(' expression ')' name ';'
	| optAnnotations
		VALUESET '<' tupleType '>' '(' expression ')' name ';'
	| optAnnotations
		VALUESET '<' typeName '>' '(' expression ')' name ';'
	;

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

value_set<bit<16>>(4) pvs;

создаёт value_set размера 4 с записями типа bit<16>.

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

13. Блоки управления

Анализаторы P4 отвечают за извлечение битов пакета в заголовки (header), которые вместе с метаданными могут служить для манипуляций блоков управления. Тело блока управления представляет собой традиционную императивную программу. Внутри блока могут вызываться блоки СД для преобразования данных, представляемые в P4 конструкциями, которые называют таблицами.

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

controlDeclaration
	: controlTypeDeclaration optConstructorParameters
		/* controlTypeDeclaration не может включать параметры типа */
		'{' controlLocalDeclarations APPLY controlBody '}'
	;

controlLocalDeclarations
	: /* пусто */
	| controlLocalDeclarations controlLocalDeclaration
	;

controlLocalDeclaration
	: constantDeclaration
	| variableDeclaration
	| actionDeclaration
	| tableDeclaration
	| instantiation
	;

controlBody
	: blockStatement
	;

В блоках управления не допускается создание экземпляров анализаторов. Описание параметров optConstructorParameters, которые могут применяться для создания параметризованных блоков управления, дано в разделе 14. Параметризация.

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

control C<H>(inout H data) { /* тело опущено */ }

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

13.1. Действия

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



Рисунок 10. Действия включают код (P4) и данные, задаваемые плоскостью управления. Параметры задаются плоскостью данных.

actionDeclaration
	: optAnnotations ACTION name '(' parameterList ')' blockStatement
	;

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

action Forward_a(out bit<9> outputPort, bit<9> port) {
	outputPort = port;
}

Параметры действия не могут иметь тип extern. Не имеющие направления параметры действия (например, port в предыдущем примере) указывают «данные действия». Все такие параметры должны указываться в конце списка параметров. При использовании в таблице СД (13.2.1.2. Действия) эти параметры будут предоставляться плоскостью управления (например, как указано плоскостью управления, свойством таблицы default_action или свойством const entries в
таблице).

Тело действия состоит из операторов и объявлений. Операторы switch не допускаются в действиях — грамматика разрешает их, но семантическим проверкам следует отвергать. Некоторые платформы могут вносить дополнительные ограничения, например, разрешать лишь линейный код без условных операторов и выражений.

13.1.1. Вызов действия

Действия могут выполняться двумя способами.

  • Неявно таблицами в процессе обработки СД.

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

13.2. Таблицы

Таблица описывает блоки «сопоставление-действие» (СД). Структура таблицы показана на рисунке 11. Обработка пакета с использованием таблицы СД состоит из нескольких этапов:

  • создание ключа;

  • поиск ключа в таблице (match), результатом чего является действие (action);

  • выполнение действия (action) над входными данными, ведущее к изменению данных.


Рисунок 11. Поток данных блока СД.

Объявление table создаёт экземпляр этой таблицы. Для получения нескольких экземпляров таблицы они должны объявляться в блоке управления, создаваемом в нескольких экземплярах.

Таблица поиска является конечным отображением, содержимое которого меняется асинхронно (чтение и запись) плоскостью управления целевой платформы с использованием отдельного API плоскости управления (рисунок 11). Отметим, что термин «таблица» служит как для обозначения таблиц в программах P4, так и внутренних таблиц целевой платформы. Для устранения путаницы иногда будут использоваться термин «блок СД».

Синтаксически таблица определяется в терминах набора пар (свойств) «ключ-значение». Некоторые из этих свойств являются «стандартными», но набор свойств может быть при необходимости расширен компилятором платформы.

tableDeclaration
	: optAnnotations TABLE name '{' tablePropertyList '}'
	;

tablePropertyList
	: tableProperty
	| tablePropertyList tableProperty
	;

tableProperty
	: KEY '=' '{' keyElementList '}'
	| ACTIONS '=' '{' actionList '}'
	| CONST ENTRIES '=' '{' entriesList '}' /* неизменяемые записи */
	| optAnnotations CONST nonTableKwName '=' initializer ';'
	| optAnnotations nonTableKwName '=' initializer ';'
	;

nonTableKwName
	: IDENTIFIER
	| TYPE_IDENTIFIER
	| APPLY
	| STATE
	| TYPE
	;

Стандартные свойства таблицы включают:

  • ключ (KEY) — выражение, описывающее создание ключа для поиска в таблице;

  • действия (ACTIONS) — список всех действий, которые могут быть найдены в таблице.

В дополнение к этому для таблицы могут быть определены следующие свойства:

  • действие по умолчанию (default_action), выполняемое в случаях отсутствия в таблице записи для данного ключа;

  • размер (size) — целое число, указывающее желаемый размер таблицы.

Компилятор должен устанавливать для по умолчанию действия значение NoAction (а также помещать его в список actions) в таблицах, которые не определяют должным образом свойство default_action (это согласуется с семантикой параграфа 13.2.1.3. Принятое по умолчанию действие). Поэтому все таблицы можно считать имеющими принятое по умолчанию действие, заданное явно или неявно. В этом документе предполагается наличие корректного default_action во всех таблицах.

Таблицы могут также включать зависимые от архитектуры свойства (13.2.1.6. Дополнительные свойства).

Свойства, указанные как const, не могут динамически изменяться плоскостью управления. Свойства key, actions, size всегда являются постоянными, поэтому для них не требуется ключевое слово const.

13.2.1. Свойства таблицы

13.2.1.1. Ключи

Ключ является свойством таблицы, задающим значения плоскости данных, используемые для поиска записей в таблице. Ключ представляет собой список пар (e : m), где e — выражение, описывающее данные для сопоставления с таблицей, а m — константа match_kind, описывающая алгоритм сопоставления (7.1.3. Тип match_kind).

keyElementList
	: /* пусто */
	| keyElementList keyElement
	;

keyElement
	: expression ':' name optAnnotations ';'
	;

Рассмотрим в качестве примера фрагмент программы

table Fwd {
	key = {
		ipv4header.dstAddress : ternary;
		ipv4header.version	: exact;
	}
	// другие поля опущены
}

Здесь ключ содержит два поля заголовка ipv4header — dstAddress и version, а match_kind служит трём целям:

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

  • создание API плоскости управления для заполнения таблицы;

  • использование компилятором back-end при выделении ресурсов для реализации таблицы.

Основная библиотека P4 содержит три предопределённых идентификатора match_kind.

match_kind {
	exact,
	ternary,
	lpm
}

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

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

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

13.2.1.2. Действия

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

actionList
	: /* пусто */
	| actionList optAnnotations actionRef ';'
	;

actionRef
	: prefixedNonTypeName
	| prefixedNonTypeName '(' argumentList ')'
;

Для иллюстрации вернёмся к примеру VSS из параграфа 5.1. Архитектура VSS.

action Drop_action() {
	outCtrl.outputPort = DROP_PORT;
}
action Rewrite_smac(EthernetAddress sourceMac) {
	headers.ethernet.srcAddr = sourceMac;
}
table smac {
	key = { outCtrl.outputPort : exact; }
	actions = {
		Drop_action;
		Rewrite_smac;
	}
}
  • Записи таблицы smac могут включать два действия — Drop_action и Rewrite_mac.

  • Действие Rewrite_smac имеет один параметр — sourceMac, который задаётся плоскостью управления.

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

action a() {}
control c() {
	action a() {}
	// Некорректная таблица - имена двух действий совпадают
	table t { actions = { a; .a; } }
}

Каждый параметр с направлением (in, inout, out) должен быть привязан в списке спецификации действий, а параметры без направления не могут быть привязаны к этому списку. Выражения, представленные как аргументы, не оцениваются до вызова действия.

action a(in bit<32> x) { /* тело опущено */ }
bit<32> z;
action b(inout bit<32> x, bit<8> data) { /* тело опущено */ }
table t {
	actions = {
		// a; -- недействительно, параметр x должен быть привязан
		a(5);	// привязка параметра x из a - 5
		b(z);	// привязка параметра x из b - z
		// b(z, 3); недействительная привязка параметра без направления
		// b(); -- недействительно, параметр x должен быть привязан
	}
}
13.2.1.3. Принятое по умолчанию действие

Принятое по умолчанию действие вызывается для таблицы блоком СД автоматически, если в таблице не найдено записи для представленного ключа. При наличии свойства default_action оно должно указываться после свойства action. Оно может быть объявлено как константа, что препятствует динамической замене действия плоскостью управления. Действие, принятое по умолчанию, должно быть одним из указанных в списке actions. В частности, выражения, переданные как параметры in, out или inout должны быть синтаксически идентичны выражениям, использованным в одном из элементов списка действий.

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

const default_action = Rewrite_smac(48w0xAA_BB_CC_DD_EE_FF);

Отметим, что заданное действие по умолчанию должно предоставлять аргументы для привязанных плоскостью управления параметров (параметры без направления), поскольку принятое по умолчанию действие синтезируется во время компиляции. Выражения, представленные как аргументы для параметров с направлениям (in, inout, out), оцениваются при вызове действия, а выражения для параметров без аргументов — во время компиляции.

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

default_action = a(5); // корректно, нет параметров плоскости управления
// default_action = a(z); -- некорректно, параметр x для a уже привязан к значению 5
default_action = b(z,8w8); // корректно, параметр data для b привязан к 8w8
// default_action = b(z); -- некорректно, параметр data для b не привязан
// default_action = b(x, 3); -- некорректно, параметр x для b привязан к x вместо z

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

13.2.1.4. Записи

Хотя записи таблиц обычно создаются плоскостью управления, возможна инициализация таблиц во время компиляции с использованием набора записей. Это полезно в ситуациях, где таблицы служат для реализации фиксированных алгоритмов — статическое задание таблиц позволяет задать эти алгоритмы в P4, а это даёт компилятору возможность понять реальное использование таблицы и принять более эффективное решение о выделении ограниченных ресурсов платформы. Записи, объявленные в коде P4, включаются в таблицу при загрузке программы на целевой платформе. Синтаксис определения записей таблиц показан ниже.

tableProperty
	: const ENTRIES '=' '{' entriesLlist '}' /* неизменные записи */

entriesList
	: entry
	| entriesList entry
	;

entry
	: keysetExpression ':' actionRef optAnnotations ';'
	;

Записи таблиц неизменны (const), т. е. могут лишь считываться и плоскость управления не может изменить или удалить их. Из этого следует неизменность таблиц, определяющих записи в коде P4. Такой выбор имеет важное влияние на среду выполнения P4, поскольку не нужно отслеживать различные типы записей в таблице (изменяемые и статические). В будущих версиях P4 может быть добавлена возможность смешивать изменяемые и статические записи в одной таблице путём объявления дополнительных свойств записей без ключевого слова const.

Компонент записи keysetExpression является кортежем, который должен обеспечивать поле для каждого ключа в таблице (13.2.1. Свойства таблицы). Тип ключа таблицы должен соответствовать типу элемента в наборе. Компонент actionRef должен быть действием, которое присутствует в списке действий таблицы со всеми привязанными аргументами.

Если API среды выполнения требует приоритета для записей таблицы (например, при использовании P4 Runtime API таблицы хотя бы с одним троичным полем ключа поиска), записи сопоставляются в порядке указания в программе с остановкой на первой совпадающей записи. Архитектуре следует определять значимость порядка записей (если он имеется) для других типов таблиц.

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

Для иллюстрации рассмотрим приведённый ниже пример.

header hdr {
	bit<8>	e;
	bit<16> t;
	bit<8>	l;
	bit<8>	r;
	bit<1>	v;
}

struct Header_t {
	hdr h;
}

struct Meta_t {}

control ingress(inout Header_t h, inout Meta_t m,
			inout standard_metadata_t standard_meta) {
	action a() { standard_meta.egress_spec = 0; }
	action a_with_control_params(bit<9> x) { standard_meta.egress_spec = x; }

	table t_exact_ternary {
		key = {
			h.h.e : exact;
			h.h.t : ternary;
		}
		actions = {
			a;
			a_with_control_params;
		}
		default_action = a;
		const entries = {
			(0x01, 0x1111 &&& 0xF) : a_with_control_params(1);
			(0x02, 0x1181) : a_with_control_params(2);
			(0x03, 0x1111 &&& 0xF000) : a_with_control_params(3);
			(0x04, 0x1211 &&& 0x02F0) : a_with_control_params(4);
			(0x04, 0x1311 &&& 0x02F0) : a_with_control_params(5);
			(0x06, _) : a_with_control_params(6);
			_	: a;
		}
	}
}

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

13.2.1.5. Размер

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

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

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

13.2.1.6. Дополнительные свойства

Объявление таблицы определяет важные интерфейсы плоскостей управления и данных — ключи и действия. Однако лучший способ реализации таблицы на деле может зависеть от природы записей, создаваемых в процессе работы (например, таблица может быть плотной или редкой, может быть реализована как хэш-таблица, ассоциативная память, дерево и т. п.). Кроме того, архитектура может поддерживать дополнительные свойства, семантика которых выходит за рамки данной спецификации. Например, в архитектуре со статическим выделением ресурсов таблиц может потребоваться задание в программе свойства size, которое компилятор back-end может использовать для выделения ресурсов хранения. Однако такие зависимые от архитектуры свойства не могут менять семантику поиска в таблицах, который всегда находит нужное действие или отсутствие такового. Можно лишь изменить интерпретацию результата поиска в плоскости данных. Это ограничение нужно для того, чтобы обеспечить возможность понять поведение таблиц во время компиляции.

В качестве другого примера свойство реализации можно использовать для передачи дополнительной информации компилятору back-end. Значение этого свойства может быть экземпляром внешнего блока, выбранного из подходящей библиотеки. Например, базовая функциональность конструкции action_profile в таблице P414 может быть реализована, как показано ниже.

extern ActionProfile {
	ActionProfile(bit<32> size); // число предполагаемых разных действий
}
table t {
	key = { /* тело опущено */ }
	size = 1024;
	implementation = ActionProfile(32);	// вызов конструктора
}

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

13.2.2. Вызов блока СД

Таблицу можно вызвать с помощью метода apply. Вызов этого метода для экземпляра таблицы возвращает значение типа struct с двумя полями. Эта структура создаётся компилятором автоматически. Для каждой таблицы T компилятор синтезирует enum и struct, как показано ниже.

enum action_list(T) {
	// одно поле для каждого действия из списка action в таблице T
}
struct apply_result(T) {
	bool hit;
	action_list(T) action_run;
}

Оценка метода apply устанавливает в поле hit значение true, а в miss — false, если в таблице найдено совпадение. В противном случае устанавливается hit = false и miss = true. Эти биты могут применяться в потоке управления вызвавшего таблицу блока управления.

if (ipv4_match.apply().hit) {
	// найдено совпадение (hit)
} else {
	// совпадения не найдено (miss)
}
if (ipv4_host.apply().miss) {
	ipv4_lpm.apply(); // поиск маршрута при отсутствии записи в таблице host
}

Поле action_run показывает тип выполняемого действия (независимо от hit или miss) и может использоваться в операторе switch, как показано ниже.

switch (dmac.apply().action_run) {
	Drop_action: { return; }
}

13.2.3. Семантика выполнения блока СД

Семантика оператора вызова таблицы показана ниже

m.apply();

и может быть представлена показанным ниже псевдокодом (см. рисунок 11).

apply_result(m) m.apply() {
	apply_result(m) result;
	var lookupKey = m.buildKey(m.key); // использование блока ключей
	action RA = m.table.lookup(lookupKey);
	if (RA == null) {	// нет в таблице поиска (miss)
		result.hit = false;
		RA = m.default_action;	// используется принятое по умолчанию действие
	} else {
		result.hit = true;
	}
	result.action_run = action_type(RA);
	evaluate_and_copy_in_RA_args(RA);
	execute(RA);
	copy_out_RA_args(RA);
	return result;
}

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

bit<8> f1 (in bit<8> a, inout bit<8> b) {
	b = a + 5;
	return a >> 1;
}
bit<8> x;
bit<8> y;
table t1 {
	key = {
		y & 0x7	: exact @name("masked_y");
		f1(x, y)	: exact @name("f1");
		y		: exact;
	}
	// ... здесь определяются остальные свойства таблицы, на связанные с примером
}
apply {
	// здесь присваиваются значения x и y, на связанные с примером
	t1.apply();
}

Это эквивалентно поведению другого определения таблицы и вызову apply.

// такие же определения f1, x, y как в предыдущем примере
bit<8> tmp_1;
bit<8> tmp_2;
bit<8> tmp_3;
table t1 {
	key = {
		tmp_1 : exact @name("masked_y");
		tmp_2 : exact @name("f1");
		tmp_3 : exact @name("y");
	}
	// ... здесь определяются остальные свойства таблицы, на связанные с примером
}
apply {
	// здесь присваиваются значения x и y, на связанные с примером
	tmp_1 = y & 0x7;
	tmp_2 = f1(x, y);
	tmp_3 = y;
	t1.apply();
}

Отметим, что второй пример приведён для задания поведения первого примера. Реализация может выбрать любой вариант, обеспечивающий такое поведение4.

13.3. Абстрактная машина конвейера СД

Можно описать вычислительную модель конвейера СД, воплощённого в блоке управления — тело блока выполняется аналогично традиционным императивным программам:

  • в среде выполнения операторы блока применяются в порядке их следования;

  • выполнение оператора return незамедлительно прерывает исполнение текущего блока и возвращает управления в точку вызова;

  • выполнение оператора exit незамедлительно прерывает исполнение текущего блока и всех блоков, в которых он содержится (откуда вызван);

  • использование таблицы выполняет соответствующий блок СД, как описано выше.

13.4. Вызов элемента управления

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

control Callee( inout IPv4 ipv4) { /* тело опущено */ }
control Caller(inout Headers h) {
	Callee() instance;	// экземпляр вызываемого блока
	apply {
		instance.apply(h.ipv4);	// вызов блока управления
	}
}

14. Параметризация

Для поддержки библиотек полезных компонентов P4 анализаторы и блоки управления можно параметризовать с помощью параметров конструктора. Рассмотрим синтаксис объявления конструктора

parserDeclaration
	: parserTypeDeclaration optConstructorParameters
		'{' parserLocalElements parserStates '}'
	;

optConstructorParameters
	: /* пусто */
	| '(' parameterList ')'
	;

Из этого правила можно вывести возможность наличия у конструктора двух наборов параметров:

  • параметры среды выполнения (parameterList);

  • необязательные параметры конструктора (optConstructorParameters).

Параметры конструктора должны быть ненаправленными (не могут быть in, out, inout) и при создании экземпляра анализатора должна быть возможность полной оценки выражений, представленных для этих параметров, во время компиляции. Рассмотрим пример

parser GenericParser(packet_in b, out Packet_header p)
			(bool udpSupport) {	// параметры конструктора
	state start {
		b.extract(p.ethernet);
		transition select(p.ethernet.etherType) {
			16w0x0800: ipv4;
		}
	}
	state ipv4 {
		b.extract(p.ipv4);
		transition select(p.ipv4.protocol) {
			6: tcp;
			17: tryudp;
		}
	}
	state tryudp {
		transition select(udpSupport) {
			false: accept;
			true : udp;
		}
	}
	state udp {
		// тело опущено
	}
}

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

// topParser - это GenericParser, где udpSupport = false
GenericParser(false) topParser;

14.1. Прямой вызов типа

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

control Callee(/* параметры опущены */) { /* тело опущено */ }
control Caller(/* параметры опущены */)(/* параметры опущены */) {
	apply {
		Callee.apply(/* аргументы опущены */); // callee считается экземпляром
	}
}

Определение Caller эквивалентно приведённому ниже.

control Caller(/* параметры опущены */)(/* параметры опущены */) {
	@name("Callee") Callee() Callee_inst; // локальный экземпляр Callee
	apply {
		Callee_inst.apply(/* аргументы опущены */);	// применение Callee_inst
	}
}

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

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

  • В одной области действия прямые вызовы типа приводят к созданию своего локального экземпляра для каждого вызова, однако однотипные экземпляры будут иметь одно глобальное имя через аннотацию @name (17.3.2. Аннотации, управляющие именами). Если тип содержит управляемые элементы, неоднократные непосредственные вызовы в одной области действия недопустимы, поскольку будут создаваться несколько экземпляров управляемых элементов с одним именем.

15. Сборка пакета

Сборка пакетов (deparsing) в каком-то смысле обратна их анализу. P4 не поддерживает отдельного языка для сборки пакетов и она выполняется в блоках управления, имеющих по меньшей мере один параметр packet_out. Приведённый ниже фрагмент кода записывает поочерёдно заголовки Ethernet и IPv4 в packet_out.

control TopDeparser(inout Parsed_packet p, packet_out b) {
	apply {
		b.emit(p.ethernet);
		b.emit(p.ip);
	}
}

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

15.1. Вставка данных в пакет

Тип packet_out определён в основной библиотеке P4 и это определение приведено ниже. Тип обеспечивает метод добавления данных в выходной пакет, называемый emit:

extern packet_out {
	void emit<T>(in T data);
}

Метод emit поддерживает добавления данных в заголовок, стек или объединение заголовков для выходного пакета.

  • При использовании с заголовком emit добавляет данные в заголовок пакета, если этот заголовок действителен, и ничего не делает в противном случае (no-op).

  • При использовании со стеком заголовков emit вызывается рекурсивно для каждого элемента стека.

  • При использовании со структурой или объединением заголовков emit рекурсивно вызывается для каждого поля. Отметим, что в struct не допускаются поля типа error и enum, поскольку они не сериализуются.

Недопустим вызов emit для выражений базового типа, enum или error.

Вызов emit можно описать приведённым ниже псевдокодом.

packet_out {
	byte[] data;
	unsigned lengthInBits;
	void initializeForWriting() {
		this.data.clear();
		this.lengthInBits = 0;
	}
	/// Добавляются данные в пакет. T может быть заголовком, стеком или
	/// объединением заголовков и структурой из таких типов.
	void emit<T>(T data) {
		if (isHeader(T))
			if (data.valid$) {
				this.data.append(data);
				this.lengthInBits += data.lengthInBits;
			}
		else if (isHeaderStack(T))
			for (e : data)
				emit(e);
		else if (isHeaderUnion(T) || isStruct(T))
			for (f : data.fields$)
				emit(e.f)
		// Другие типы T недействительны
	}
}

Здесь применяются специальные идентификаторы valid$ для скрытого бита validity в заголовках и fields$ для списка полей struct или объединения заголовков. Применяется также стандартная нотация для итераций по элементам стека (e : data) и списку полей объединений заголовков или struct (f : data.fields$). Для struct итерации выполняются в порядке указания полей при определении типа.

16. Описание архитектуры

Описание архитектуры должно предоставляться производителем платформы в форме исходного кода библиотеки P4, который содержит по меньшей мере одно объявление пакета. Экземпляр этого пакета пользователь должен создать для своей программы. Примером может служить описание VSS в параграфе 5.1. Архитектура VSS.

Файл описания архитектуры может определять типы данных, константы, реализации вспомогательных программ (package) и ошибки. Он должен объявлять типы всех программируемых блоков, которые могут появляться на целевой платформе (анализаторы и блоки управления). Программируемые блоки могут группироваться в пакеты (package), которые могут быть вложенными.

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

16.1. Пример описания архитектуры

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

parser Parser<IH>(packet_in b, out IH parsedHeaders);
// входной конвейер СД
control IPipe<T, IH, OH>(in IH inputHeaders,
				in InControl inCtrl,
				out OH outputHeaders,
				out T toEgress,
				out OutControl outCtrl);
// выходной конвейер СД
control EPipe<T, IH, OH>(in IH inputHeaders,
				in InControl inCtrl,
				in T fromIngress,
				out OH outputHeaders,
				out OutControl outCtrl);
control Deparser<OH>(in OH outputHeaders, packet_out b);
package Ingress<T, IH, OH>(Parser<IH> p,
				IPipe<T, IH, OH> map,
				Deparser<OH> d);
package Egress<T, IH, OH>(Parser<IH> p,
				EPipe<T, IH, OH> map,
				Deparser<OH> d);
package Switch<T>(Ingress<T, _, _> ingress, Egress<T, _, _> egress);

Из этих объявлений можно получить полезную информацию об архитектуре описываемого коммутатора даже без чтения точного описания архитектуры (рисунок 12).


  • Рисунок 12. Фрагмент примера коммутатора.

    Коммутатор содержит два отдельных пакета Ingress и Egress.

  • Блоки Parser, IPipe, Deparser в пакете Ingress соединены в цепочку. Кроме того, блок Ingress.IPipe имеет ввод типа Ingress.IH, который является выводом Ingress.Parser.

  • Аналогично пакет Egress включает блоки Parser, EPipe, Deparser.

  • Ingress.IPipe соединён с Egress.EPipe, поскольку первый даёт на выход значение типа T, которое служит вводом для второго. Отметим, что экземпляры типа T создаются также в пакете Switch. Напротив, входной (Ingress) тип IH и выходной (Egress) тип IH могут различаться. Чтобы они совпадали, можно вместо объявления IH и OH на уровне коммутатора задать

    package Switch<T,IH,OH>(Ingress<T, IH, OH> ingress, Egress<T, IH, OH> egress).

Эта архитектура моделирует коммутатор, содержащий два разных канала между входным и выходным конвейером.

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

  • Канал опосредованной передачи с использованием анализатора с сериализацией данных в пакет и обратно.

16.2. Пример программы для архитектуры

Для работы на определённой архитектуре программа P4 должна создать экземпляр пакета верхнего, уровня передавая значения для всех его аргументов и создавая переменную с именем main в пространстве имён верхнего уровня. Типы аргументов должны соответствовать типам параметров после подходящей подстановки типов переменных. Подстановка типа может быть выражена напрямую с использованием специализации типа или выведена компилятором с использованием алгоритма унификации, подобного Hindley-Milner. Например, с объявлениями типов

parser Prs<T>(packet_in b, out T result);
control Pipe<T>(in T data);
package Switch<T>(Prs<T> p, Pipe<T> map);

и следующими объявлениями

parser P(packet_in b, out bit<32> index) { /* тело опущено */ }
control Pipe1(in bit<32> data) { /* тело опущено */ }
control Pipe2(in bit<8> data) { /* тело опущено */ }

Ниже приведено действительное объявление для целевой платформы верхнего уровня

Switch(P(), Pipe1()) main;

Следующее определение недействительно

Switch(P(), Pipe2()) main;

поскольку анализатор P требует для T тип bit<32>, а Pipe2 требует от T тип bit<8>.

Пользователь может явно задать значения переменных типа (иначе компилятор выведет их

Switch<bit<32>>(P(), Pipe1()) main;

16.3. Модель фильтра пакетов

Для демонстрации универсальности языка описания архитектуры P4 рассмотрим пример фильтрации пакетов, где решения принимаются исключительно по результатам анализатора P4, как показано на рисунке 13.


Рисунок 13. Модель фильтра пакетов.

Эту модель можно применить для фильтрации пакетов в ядре Linux. Например, можно заменить язык tcpdump более мощным языком P4, что позволит поддерживать новые протоколы с обеспечением полной «безопасности типов» при обработке пакетов. Для такой платформы компилятор P4 может генерировать программу eBPF (Extended Berkeley Packet Filter), которая инжектируется утилитой tcpdump в ядро Linux и выполняется EBPF kernel JIT.

Для цели в виде ядра Linux и архитектурной модели фильтра пакетов можно объявить

parser Parser<H>(packet_in packet, out H headers);
control Filter<H>(inout H headers, out bool accept);

package Program<H>(Parser<H> p, Filter<H> f);

17. Абстрактная машина P4 — оценка

Оценка программы P4 выполняется в два этапа:

  • статическая оценка происходит во время компиляции программы P4 путём анализа и создания экземпляров всех блоков с состоянием;

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

17.1. Известные при компиляции значения

  • Целочисленные, логические и строковые литералы.

  • Идентификаторы из объявления error, enum, match_kind.

  • Идентификатор default.

  • Поле size значения с типом стека заголовков.

  • Идентификатор _ при использовании в выражениях select.

  • Идентификаторы, представляющие объявленные типы, действия, таблицы, анализаторы, элементы управления, пакеты.

  • Списки, в которых все компоненты имеют известные при компиляции значения.

  • Выражения инициализации структуру, где все поля известны при компиляции.

  • Экземпляры, создаваемые объявлениями (10.3. Создание экземпляров) и вызовами конструкторов.

  • Выражения +, -, *, / , %, cast, !, &, |, &&, ||, << , >> , ~ , >, <, ==, !=, <=, >=, ++, [:], где все операнды известны при компиляции.

  • Идентификаторы, объявленные как константы с использованием ключевого слова const.

  • Выражения в форме e.minSizeInBits() и e.minSizeInBytes().

17.2. Оценка при компиляции

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

  • Все объявления (например, анализаторы, элементы управления, типы, константы) оценивают сами себя.

  • Для каждой таблицы оценивается экземпляр.

  • Вызовы конструкторов оцениваю объекты с состоянием соответствующего типа. Для этого все аргументы конструктора оцениваются рекурсивно и привязываются к параметрам конструктора. Аргументы конструктора должны быть известны при компиляции. Порядок оценки аргументов конструктора не должен играть роли, поскольку он не влияет на результат.

  • Экземпляры оценивают именованные объекты с состоянием.

  • Экземпляр анализатора или элемента управления рекурсивно оценивает все экземпляры с состоянием, объявленные в блоке.

  • Результатом оценки программы является значение переменной верхнего уровня main.

Отметим, что все значения с состоянием оцениваются во время компиляции.

В качестве примера рассмотрим фрагмент программы, приведённый ниже.

// объявления архитектуры
parser P(/* параметры опущены */);
control C(/* параметры опущены */);
control D(/* параметры опущены */);

package Switch(P prs, C ctrl, D dep);
extern Checksum16 { /* тело опущено */}

// пользовательский код
Checksum16() ck16; // экземпляр блока контрольных сумм
parser TopParser(/* параметры опущены */)(Checksum16 unit) { /* тело опущено */}
control Pipe(/* параметры опущены */) { /* тело опущено */}
control TopDeparser(/* параметры опущены */)(Checksum16 unit) { /* тело опущено */}

Switch(TopParser(ck16), Pipe(), TopDeparser(ck16)) main;

Оценка этой программы происходит в описанном ниже порядке.

  1. Объявления P, C, D, Switch, Checksum16 оценивают себя сами.

  2. Экземпляр Checksum16() ck16 оценивается и создаёт объект ck16 типа Checksum16.

  3. Объявления TopParser, Pipe, TopDeparser оценивают себя сами.

  4. Выполняется оценка экземпляра переменной :

    1. рекурсивно оцениваются аргументы конструктора;

    2. вызывается конструктор TopParser(ck16)

    3. аргументы оцениваются рекурсивно, оценивается объект ck16;

    4. оценивается сам конструктор, что ведёт к созданию объекта типа TopParser;

    5. аналогично Pipe() и TopDeparser(ck16) оцениваются как вызовы конструктора;

    6. оцениваются все аргументы конструктора пакета Switch (экземпляры TopParser, Pipe, TopDeparser) и их сигнатуры сопоставляются с определением Switch;

    7. оценивается конструктор Switch, результатом чего является экземпляр пакет Switch (prs типа TopParser является первым параметром, ctrl типа Pipe — вторым, dep типа TopDeparser — третьим).

  5. Результатом оценки программы является значение переменной main — экземпляра пакета Switch.


Рисунок 14. Результат оценки.

На рисунке 14 показан результат оценки в графической форме, представляющий собой граф экземпляров. Имеется 1 экземпляр Checksum16 (ck16), совместно используемый TopParser и TopDeparser (конкретная архитектура может потребовать использования разных блоков контрольной суммы).

17.3. Имена элементов управления

Каждый управляемый объект, раскрываемый программой P4, должен иметь уникальное полное имя, которое плоскость управления может использовать для взаимодействия с объектом. Управляемые объекты включают таблицы, ключи, действия, экземпляры extern. Полное имя состоит из локального имени управляемого объекта с префиксом из имени включающего его пространства имён. Поэтому программные конструкции с элементами управления также должны иметь уникальные полные имена. Это экземпляры элементов управления и анализаторов. Оценка может создавать множество однотипных экземпляров, каждый из которых должен иметь уникальное полное имя.

17.3.1. Вычисление имён элементов управления

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

17.3.1.1. Таблицы

Для каждой конструкции table её синтаксическое имя становится локальным именем таблицы. Например, определение

control c(/* параметры опущены */)() {
	table t { /* тело опущено */ }
}

создаст таблицу с локальным именем t.

17.3.1.2. Ключи

Синтаксически ключи таблицы являются выражениями. Для простых выражений локальное имя может создаваться из самого выражения. Ниже приведён пример таблицы t, ключи которой названы data.f1 и hdrs[3].f2.

table t {
	keys = {
		data.f1 : exact;
		hdrs[3].f2 : exact;
	}
	actions = { /* тело опущено */ }
}

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

Выражение

Пример

Имя

Метод isValid()

h.isValid()

«h.isValid()»

Доступ к массиву

header_stack[1]

«header_stack[1]»

Константа

1

«1»

Проекция поля

data.f1

«data.f1»

Нарезка

F1[3:0]

«f1[3:0]»

Все прочие выражения должны аннотироваться с использованием @name (18.3.3. Аннотации API плоскости управления), как показано ниже.

table t {
	keys = {
		data.f1 + 1 : exact @name("f1_mask");
	}
	actions = { /* тело опущено */ }
}

Здесь аннотация @name(«f1_mask») назначает ключу локальное имя «f1_mask».

17.3.1.3. Действия

Для конструкции action локальным именем действия является синтаксическое имя action. Например,

control c(/* параметры опущены */)() {
	action a(...) { /* тело опущено */ }
}

создаёт локальное имя a.

17.3.1.4. Экземпляры

Локальные имена экземпляров extern, parser и control выводятся на основе использования экземпляра. Если экземпляр привязан к имени, оно становится локальным именам для плоскости управления. Например, при объявлении control C

control C(/* параметры опущены */)() { /* тело опущено */ }

и создании экземпляра

C() c_inst;

локальным именем будет c_inst. Если экземпляр создаётся в качестве аргумента, его локальным именем будет имя формального параметра, к которому экземпляр привязан. Например при объявлении extern E и control C

extern E { /* тело опущено */ }
control C( /* параметры опущены */ )(E e_in) { /* тело опущено */ }

и создании экземпляра

C(E()) c_inst;

локальным именем экземпляра extern будет e_in.

Если создаваемая конструкция передаётся как аргумент пакету (package), имя экземпляра выводится из представленного пользователем объявления, когда это возможно. В приведённом ниже примере локальным именем MyC будет c, а локальным именем extern — e2, а не e1.

extern E { /* тело опущено */ }
control ArchC(E e1);
package Arch(ArchC c);

control MyC(E e2)() { /* тело опущено */ }
Arch(MyC()) main;

Отметим, что в этом примере архитектура будет представлять экземпляр extern при передаче экземпляра MyC пакету Arch. Полным именем этого экземпляра будет main.c.e2.

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

control Callee() {
	table t { /* тело опущено */ }
	apply { t.apply(); }
}
control Caller() {
	Callee() c1;
	Callee() c2;
	apply {
		c1.apply();
		c2.apply();
	}
}
control Simple();
package Top(Simple s);


Рисунок 15. Оценка программы с несколькими экземплярами компонентов.

Top(Caller()) main;

Оценка этой программы при компиляции создаёт структуру, показанную на рисунке 15. Отметим наличие двух экземпляров таблицы t, которые (оба) должны быть раскрыты плоскости управления. Для именования объектов в этой иерархии используется компонент пути имён, содержащих экземпляры. В данном случае две таблицы будут называться s.c1.t и s.c2.t, где s — имя аргумента для создания экземпляра пакета, которое выводится из имени соответствующего формального параметра.

17.3.2. Аннотации, управляющие именами

Аннотации, относящиеся к плоскости управления (18.3.3. Аннотации API плоскости управления), могут менять видимые плоскости управления имена.

  • Аннотация @hidden скрывает управляемый элемент от плоскости управления. Это единственный случай, когда управляемому объекту не требуется уникальное полное имя.

  • Можно использовать аннотацию @ для смены локального имени управляемого объекта.

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

17.3.3. Рекомендации

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

control c( /* параметры опущены */)() {
	action a ( /* параметры опущены */ ) { /* тело опущено */ }
	table t {
		keys = { /* тело опущено */ }
		actions = { a; } 
	}
}
c() c_inst;

Программы плоскости управления могут указывать действие c_inst.a как a при вставке правил в таблицу c_inst.t, поскольку это ясно из определения таблица, к которой относится действие.

Не все однозначные сокращения можно рекомендовать. Рассмотрим первый пример из параграфа 17.3. Имена элементов управления. Можно подумать о ссылке на s.c1 как c1, поскольку в программе нет другого объекта c1. Однако это сделает программу «хрупкой», поскольку её новые версии не смогут создавать экземпляр с именем c1 или включать библиотеки P4, где имеется объект с таким именем.

17.4. Динамическая оценка

Динамическая оценка программу P4 организуется архитектурной моделью. Каждая модель должна задавать порядок и условия динамического выполнения различных компонентов программы P4. Например, в VSS из раздела 5.1. Архитектура VSS поток выполнения имеет вид Parser->Pipe->Deparser. При вызове блока исполнения P4 он работает до завершения (прерывания) в соответствии с описанной здесь семантикой.

17.4.1. Модель одновременной работы

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

Каждый анализатор или блок управления верхнего уровня выполняется в форме отдельного потока (thread) создаваемого архитектурой. Все параметры и локальные переменные блока доступны лишь этому потоку. Это относится к параметрам анализаторов и сборщиков packet_in и packet_out. Поскольку блок P4 использует лишь свои локальные ресурсы (метаданные, заголовки, переменные), его поведение при одновременной работе не отличается от изолированного поведения и чередование операторов из разных блоков не должно влиять на результаты.

Внешние блоки, экземпляры которых создаются программой P4, являются глобальными и используются всеми потоками. Если внешние блоки участвуют в доступе к состоянию (счётчики, регистры), т. е. к методам чтения и записи состояний, эти операции являются «состязательными». P4 требует атомарного (неделимого) выполнения вызовов методов и экземпляров extern. Для атомарного выполнения больших блоков кода в P4 применяется аннотация @atomic для блока операторов, состояния анализатора, блока управления или анализатора целиком. Рассмотрим пример.

extern Register { /* тело опущено */ }
control Ingress() {
	Register() r;
	table flowlet { /* чтение состояния r в действии (action) */ }
	table new_flowlet { /* запись состояния r в действии (action) */ }
	apply {
		@atomic {
			flowlet.apply();
			if (ingress_metadata.flow_ipg > FLOWLET_INACTIVE_TIMEOUT)
				new_flowlet.apply();
}}}

Программа обращается к внешнему объекту r типа Register в действиях из таблиц flowlet (чтение) и new_flowlet (запись). Без аннотации @atomic эти операции не будут выполняться атомарно и для второго пакета состояние r может быть считано до того, как первый изменит его.

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

18. Аннотации

Аннотации похожи на атрибуты C# и аннотации Java. Это просто механизм ограниченного расширения языка P4 без изменения грамматики. В какой-то степени аннотации включают #pragma из языка C. Аннотации присоединяются к типам, полям, переменным и т. п. с использованием синтаксиса @ (как показано явно в грамматике P4). Неструктурированные аннотации или просто аннотации могут не иметь тела, для структурированных тело обязательно и должно содержать хотя бы одну пару скобок [].

optAnnotations
	: /* пусто */
	| annotations
	;
annotations
	: annotation
	| annotations annotation
	;
annotation
	: '@' name
	| '@' name '(' annotationBody ')'
	| '@' name '[' structuredAnnotationBody ']'
	;

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

Действительные аннотации

@my_anno(1) table T { /* тело опущено */ }
@my_anno[2] table U { /* тело опущено */ } // разные области с предыдущей my_anno

Недействительные аннотации

@my_anno(1)
@my_anno[2] table U { /* тело опущено */ } // ошибка — изменён тип anno для элемента

Для данного элемента может задаваться множество неструктурированных аннотаций с одним именем — они аккумулируются и все будут связаны с этим элементом. Структурированная аннотация с данным именем для элемента может быть лишь одна и наличие нескольких аннотаций создаст ошибку.

Действительные аннотации

@my_anno(1)
@my_anno(2) table U { /* тело опущено */ }	// неструктурированные аннотации аккумулируются

Недействительные аннотации

@my_anno[1]
@my_anno[2] table U { /* тело опущено */ } // ошибка — та же структурированная аннотация

18.1. Тело неструктурированной аннотации

Гибкость неструктурированных аннотаций P4 обусловлена минимальной структурой, требуемой грамматикой P4 — тело неструктурированной аннотации может содержать любую последовательность терминалов при условии сбалансированности круглых скобок. В приведённом ниже фрагменте грамматики нетерминальный элемент annotationToken представляет любой терминал, созданный лексером, включая идентификаторы, ключевые слова, строки, и целочисленные литералы, но исключая круглые скобки.

annotationBody
	: /* пусто */
	| annotationBody '(' annotationBody ')'
	| annotationBody annotationToken

Неструктурированные аннотации могут иметь ту или иную структуру в своём теле, не определяемую языком P4. Например, спецификация P4Runtime определяет аннотацию @pkginfo, предполагающую пару ключ-значение.

18.2. Тело структурированных аннотаций

В отличие от неструктурированных аннотаций структурированные используют скобки […] и формат их ограничен. Обычно такие аннотации служат для объявления пользовательских метаданных, состоящих из списков выражений или списков пар ключ-значение (но не обоих). Элемент expressionList может быть пустым или содержать список разделённых запятыми выражений. Элемент kvList включает одну или несколько пар kvPair, каждая из которых включает ключ и значение. Синтаксис выражения описан ниже (Приложение H. Грамматика P4).

Все выражения в structuredAnnotationBody должны иметь известные при компиляции значения — литералы или выражения, которые должны быть вычислены при компиляции, с типом результата string, int с неограниченной разрядностью или boolean. Структурированные выражения (например, выражения с expressionList, kvList и т. п.) не допускаются. Отметим, что информация P4Runtime (P4Info) может предусматривать дополнительные ограничения, например, целочисленные выражения могут быть ограничены 64-битовыми значениями. Не допускается дублирование ключей в kvList структурированной аннотации.

structuredAnnotationBody
	: expressionList
	| kvList
	;
...
expressionList
	: /* пусто */
	| expression
	| expressionList ',' expression
	;
...
kvList
	: kvPair
	| kvList ',' kvPair
	;
kvPair
: name '=' expression
;

18.2.1. Примеры структурированных аннотаций

Пустой список выражений имеет пустую аннотацию

@Empty[]
table t { /* тело опущено */ }

Смешанный список выражения будет иметь аннотацию вида

[1,"hello",true, false, 11]
#define TEXT_CONST "hello"
#define NUM_CONST 6
@MixedExprList[1,TEXT_CONST,true,1==2,5+NUM_CONST]
table t { /* тело опущено */ }

Список строк kvList

@Labels[short="Short Label", hover="My Longer Table Label to appear in hover-help"]
table t { /* тело опущено */ }

Список смешанных выражений kvList имеет аннотацию

[label="text", my_bool=true, int_val=6]
@MixedKV[label="text", my_bool=true, int_val=2*3]
table t { /* тело опущено */ }

Список смешанных kvPair и expressionList будет недействительным, поскольку в нем смешаны kvPair и выражения

@IllegalMixing[key=4, 5] // недопустимое смешивание
table t { /* тело опущено */ }

Недействительное дублирование ключа

@DupKey[k1=4,k1=5] // недопустимое дублирование ключа
table t { /* тело опущено */ }

Недопустимое дублирование структурированных аннотаций

@DupAnno[k1=4]
@DupAnno[k2=5] // недопустимое дублирование имени
table t { /* тело опущено */ }

Недопустимое использование структурированной и неструктурированной аннотации

@MixAnno("Anything")
@MixAnno[k2=5] // недопустимое использование обоих типов аннотаций
table t { /* тело опущено */ }

18.3. Предопределённые аннотации

Имена аннотаций, начинающиеся со строчной буквы зарезервированы для стандартной библиотеки и архитектуры. Этот документ определяет «стандартные» аннотации в Приложении C. Предполагается, что этот список будет расти. Для архитектуры рекомендуется определять аннотации, начинающиеся с префикса производителя, например, организация X может использовать для аннотаций имена вида @X_annotation

18.3.1. Аннотации необязательных параметров

Параметр для пакета, внешнего метода, функции или объекта аннотируется с помощью @optional для указания того, что параметр не требует соответствующего аргумента. Значение параметра без аргумента зависит от платформы.

18.3.2. Аннотации списка действий таблицы

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

  • @tableonly указывает, что действие может присутствовать лишь в таблице и не применяется по умолчанию;

  • @defaultonly указывает, что действие может применяться лишь по умолчанию, а не в таблице.

table t {
	actions = {
		a,		// может применяться везде
		@tableonly b,	// может применяться лишь в таблице
		@defaultonly c, 	// может использоваться лишь по умолчанию
	}
	/* тело опущено */
}

18.3.3. Аннотации API плоскости управления

Аннотация @name указывает компилятору использовать другое локальное имя при генерации внешних API для манипуляций с объектом из плоскости управления. Телом аннотации является строковый литерал. В приведённом примере таблица имеет полное имя c_inst.t1.

control c( /* параметры опущены */ )() {
	@name("t1") table t { /* тело опущено */ }
	apply { /* тело опущено */ }
}
c() c_inst;

Аннотация @hidden скрывает управляемый элемент (например, таблицу, ключ, действие или extern) от плоскости управления, удаляя по сути полное имя (17.3. Имена элементов управления). Аннотация не имеет тела.

18.3.3.1. Ограничения

Для каждого элемента можно применять не более одной аннотации @name или @hidden, а каждое имя плоскости управления должно указывать не более одного управляемого объекта. Это вызывает озабоченность при использовании абсолютной аннотации @name — если тип, содержащий аннотацию @name с абсолютным путём (начинается с .) создаётся неоднократно, это приведёт к одному имени у нескольких управляемых элементов.

control noargs();
package top(noargs c1, noargs c2);
control c() {
	@name(".foo.bar") table t { /* тело опущено */ }
	apply { /* тело опущено */ }
}
top(c(), c()) main;

Без аннотации @name эта программа будет создавать два управляемых элемента с полными именами main.c1.t и main.c2.t. Однако аннотация @name(«.foo.bar») переименуют в обоих экземплярах таблицу t в foo.bar и имена двух управляемых элементов совпадут,что недопустимо.

18.3.4. Аннотации одновременных элементов управления

Аннотация @atomic (17.4.1. Модель одновременной работы) позволяет обеспечить неделимость блока операций.

18.3.5. Аннотации наборов значений

Аннотация @match (12.6. Выражения для выбора) служит для задания match_kind, отличного принятого по умолчанию, для точного значения поля value_set.

18.3.6. Аннотации внешних функций и методов

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

  • @pure описывает функцию, зависящую лишь от значений параметров и не оказывающую никакого влияния, кроме возврата значения и поведения copy-out для параметров out и inout. Между вызовами не записывается скрытых состояний и значение не зависит от скрытого состояния, которое могут менять другие вызовы. Примером является хэш-функция, которая рассчитывает детерминированную свёртку своих аргументов и возвращаемое значение не зависит от доступных для записи плоскости управления состояний или значения вектора инициализации. Функция @pure, результат которой не используется, может быть исключена без каких-либо неблагоприятных последствий, а множество вызовов с одними аргументами можно объединить в один вызов (с учётом ограничений поведения copy-out для параметров out и inout). Порядок вызова функций @pure можно менять относительно других расчётов, которые не зависят от данных.

  • @noSideEffects слабее, чем @pure, и описывает функции, не меняющие скрытых состояний, но зависящие от таковых. Примером является хэш-функция, рассчитывающая детерминированную свёртку аргументов с учётом некого внутреннего состояния, которое может быть изменено через API плоскости управления (например, вектор инициализации). Другим примером служит чтение одного элемента массива регистров объекта extern. Такая функция может быть исключена и можно изменить её порядок по отношению к другим вызовам @noSideEffects и @pure (с учётом ограничений поведения copy-out для параметров out и inout), но не к вызовам других функций, которые могут воздействовать на данную.

18.3.7. Аннотация отмены

Аннотация @deprecated должна включать строку аргумента с сообщением, выводимым компилятором при использовании в программе отменённой конструкции. Это полезно в библиотеках, объявляющих конструкции типа extern.

@deprecated("Please use the 'check' function instead")
extern Checker { /* тело опущено */ }

18.3.8. Отключение предупреждений

Аннотация noWarn имеет обязательный строковый аргумент, который указывает подавляемые предупреждения компилятора. Например @noWarn(«unused») будет предотвращать вывод предупреждений компилятора о неиспользуемых объявлениях.

18.4. Зависимые от платформы аннотации

Каждая реализация компилятора P4 может определять свои аннотации с учётом целевой платформы. Синтаксис этих аннотаций должен соответствовать приведённым выше описаниям, семантика зависит от платформы. Аннотации можно применять аналогично pragma в других языках. Компилятору P4 следует выдавать:

  • ошибку при некорректном использовании аннотаций (например, отсутствие или некорректный тип параметра);

  • предупреждения при неизвестных аннотациях.

Приложение A. История выпусков

Версия

Дата

Изменения

1.0.0

17.05. 2017

Исходная версия.

1.1.0

26.11.2018

Добавлены функции верхнего уровня, необязательные и именованные параметры, представления enum, наборы значений анализатора, определения типов, арифметика с насыщением и структурированные аннотации. Исключена аннотация globalname, добавлено свойство таблицы size. Разъяснена семантика операций с недействительными заголовками, добавлены ограничения для аргументов вызова, изменён порядок выполнения побитовых операторов.

1.2.0

14.10.2019

Добавлена ошибка ParserInvalidArgument, порядок записей const, методы size для заголовков, 1-битовые значения со знаком, нарезки битов со знаком, пустые кортежи, аннотация @deprecated, аннотации в свободной форме, тип int для table.apply().miss, тип string.

1.2.1

11.06.2020

Добавлены выражения со значением struct, принятые по умолчанию значения, конкатенация, структурированные аннотации. Стандартизовано несколько новых аннотаций, обобщено правило типизации для масок, ограничено правило типизации для сдвига с операндами неограниченного размера. Разъяснён порядок оценки для ключей таблиц, поведение copy-out behavior, семантика недействительных стеков заголовков, семантика инициализации. Исправлено несколько мелких проблем в грамматике.

1.2.2

17.05.2021

Добавлена поддержка доступа к кортежам, универсальных (базовых) структур, дополнительных перечисляемых типов, абстрактных методов, условных и пустых операторов в синтаксических анализаторах, дополнительных приведений типов, типов с размером 0.
Уточнена семантика заданных по умолчанию действий, заголовков, пустых типов и данных действий (action).
Исправлены опечатки и несогласованности в грамматике.

A.1. Изменения в версии 1.2.2

  • Добавлена поддержка доступа к полям кортежей (8.10. Операции над кортежами).

  • Добавлена поддержка базовых структур (7.2.10. Специализация типа).

  • Добавлена поддержка целочисленных значений, enum и error в операторах switch (11.7. Оператор выбора).

  • Добавлена поддержка дополнительных перечисляемых типов (7.2.1. Перечисляемые типы).

  • Добавлена поддержка абстрактных методов (7.2.9.2. Внешние объекты)5.

  • Добавлена поддержка условных и пустых операторов а синтаксических анализаторах (12.4. Состояния анализатора).

  • Добавлена поддержка приведения int к bool (8.9.1. Явное приведение).

  • Добавлена поддержка битовых строк и varbit нулевого размера (8.22. Чтение неинициализированных значений и запись полей в недействительные заголовки).

  • Указано, что default_action имеет значение NoAction, если не указано иное (13.2. Таблицы).

  • Указаны типы выражений, которые могут служить индексами в стеке заголовков (8.17. Операции над стеком заголовков).
  • Разъяснено представление пустых типов (8.22. Чтение неинициализированных значений и запись полей в недействительные заголовки).
  • Разъяснено, что данные действия могут быть заданы плоскостью управления, свойством таблицы dafault_entry и свойством таблицы const entries (13.1. Действия).
  • Исправлены опечатки и несоответствия в грамматике (Приложение H. Грамматика P4).
  • Исключены (обязательные) аннотации записей const в грамматике (Приложение H. Грамматика P4).

A.2. Изменения в версии 1.2.1

  • Добавлены выражения со значением struct (8.12. Выражения со значением struct).

  • Добавлена поддержка принятых по умолчанию значений (7.3. Подразумеваемые значения).

  • Добавлена поддержка конкатенации строк (8.6.1. Конкатенация).

  • Добавлены аннотации key-value и со структурой списка (18. Аннотации).

  • Добавлены аннотации @pure и @noSideEffects (18.3.6. Аннотации внешних функций и методов).

  • Добавлены аннотации @noWarn (18.3.8. Отключение предупреждений).

  • Обобщена типизация масок для сериализации enum (18.3.3. Аннотации API плоскости управления).

  • Ограничены положительными константами правые операнды битового сдвига с участием int (8.7. Операции над целыми числами произвольной точности).

  • Разъяснено поведение copy-out для return (11.4. Оператор возврата) и exit (11.5. Оператор выхода).

  • Разъяснена семантика недействительных стеков заголовков (8.17. Операции над стеком заголовков).

  • Разъяснена семантика инициализации (6.6. Выражения для левой части, 6.7. Соглашения о вызовах), в частности, для заголовков и локальных переменных.

  • Разъяснён порядок оценки ключей таблицы (13.2.3. Семантика выполнения блока СД).

  • Уточнена грамматика для анализа сдвига вправо (>>) для поддержки пустых операторов в анализаторе (12.4. Состояния анализатора) и исключения аннотаций для записей const (13.2.1.4. Записи).

  • Разъяснено представление логических значений в заголовках (7.2.2. Типы заголовков).

A.3. Изменения в версии 1.2.0

  • Добавлено table.apply().miss (13.2.2. Вызов блока СД).

  • Добавлен тип string (7.1.5. Строки).

  • Добавлено неявное приведение для значений типа enum (8.3. Операции над типом enum).

  • Добавлены 1-битовые значения со знаком.

  • Нарезка битов из значений со знаком и без знака определена как беззнаковая.

  • Ограничено местоположение метки default в операторах switch.

  • Разрешены пустые кортежи.

  • Добавлена аннотация @deprecated.

  • Смягчены требования к структуре тела аннотаций.

  • Исключена аннотация @pkginfo, перенесённая в спецификацию P4Runtime.

  • Добавлен тип int (7.1.6.5. Целые числа “бесконечной точности”).

  • Добавлена ошибка ParserInvalidArgument (12.8.2. Извлечение при переменном размере, 12.8.4. Пропуск битов).

  • Разъяснена значимость порядка элементов в записях const (13.2.1.4. Записи).

  • Добавлены методы расчёта размера заголовков (8.16. Операции над заголовками).

A.4. Изменения в версии 1.1.0

  • Разрешено объявление функций на верхнем уровне программ P4 (9. Объявление функции).

  • Разрешено задавать параметры по именам, с использованием принятого по умолчанию значения и делать параметры необязательными (6.7. Соглашения о вызовах)l.

  • Добавлены перечисляемые значения — enum (8.3. Операции над типом enum).

  • Добавлены наборы значений анализатора — value_set для программируемых плоскостью управление меток select (12.11. Набор значений анализатора).

  • Разрешено определять новые типы в программах (7.5. Создание новых типов).

  • Добавлена поддержка арифметики с насыщением для некоторых платформ (8.5. Операции над битовыми типами (целые числа без знака)).

  • Добавлены структурированные аннотации как списки пар ключ-значение (18. Аннотации).

  • Удалена аннотация globalname (17.3.2. Аннотации, управляющие именами).

  • Добавлено необязательное свойство таблицы size (13.2.1.5. Размер).

  • Разъяснена семантика операций с недействительными заголовками (8.16. Операции над заголовками).

  • Добавлены ограничения на типы значений аргументов при вызовах (Приложение F. Ограничения для вызовов при компиляции и работе).

  • Изменён порядок побитовых операторов (Приложение H. Грамматика P4) — &, | и ^ имеют более высокий приоритет, нежели <, >, <=, >=.

  • Добавлена поддержка задания размера типов bit и varbit с использованием выражений (7.1. Базовые типы).

Приложение B. Зарезервированные слова P4

Ниже приведён список зарезервированных (ключевых) слов P4. Некоторые слова являются зарезервированными лишь в определённом контексте (например, actions).

action

apply

bit

bool

const

control

default

else

enum

error

extern

exit

false

header

header_union

if

in

inout

int

match_kind

package

parser

out

return

select

state

string

struct

switch

table

transition

true

tuple

typedef

varbit

verify

void

Приложение C. Зарезервированные аннотации P4

Аннотация

Назначение

Параграф

atomic

Задаёт неделимое (атомарное) выполнение

17.4.1

defaultonly

Действие может использоваться лишь по умолчанию (default).

18.3.2

hidden

Скрывает управляемый объект от плоскости управления.

17.3.2

match

Задаёт поле match_kind в value_set.

18.3.5

name

Назначает локальное имя плоскости управления.

17.3.2

optional

Указывает необязательный параметр.

18.3.1

tableonly

Действие не может использоваться по умолчанию (default).

18.3.2

deprecated

Указывает отменённую (устаревшую) конструкцию.

18.3.7

pure

«Чистая» функция.

18.3.6

noSideEffects

Функция без побочных эффектов.

18.3.6

noWarn

Отключает предупреждения компилятора (аргумент типа string)

18.3.8

Приложение D. Основная библиотека P4

Основная библиотека P4 содержит объявления, нужные большинству программ. Например, она включает определения внешних объектов packet_in и packet_out, применяемых анализаторами и сборщиками при работе с пакетом.

/// Стандартные коды ошибок. Пользователи могут добавлять свои коды.
error {
	NoError,		/// Нет ошибок.
	PacketTooShort,	/// В пакете недостаточно битов для извлечения.
	NoMatch,		/// Выражение select не имеет совпадений.
	StackOutOfBounds,	/// ссылка на недействительный элемент стека заголовков.
	HeaderTooShort,	/// Извлечение излишнего числа битов в поле varbit.
	ParserTimeout,	/// Превышено время работы анализатора.
	ParserInvalidArgument	/// Операция анализатора вызвана с неподдерживаемым
					/// реализацией значением.
}
extern packet_in {
	/// Чтение заголовка из пакета в заголовок фиксированного размера @hdr
	/// и перемещение указателя. Может вызывать ошибку PacketTooShort или
	/// StackOutOfBounds. @T - тип заголовка с фиксированным размером.
	void extract<T>(out T hdr);
	/// Чтение битов из пакета в заголовок переменного размера @variableSizeHeader
	/// и перемещение указателя. Заголовок @T должен содержать 1 поле varbit.
	/// Может вызывать ошибки PacketTooShort, StackOutOfBounds, HeaderTooShort.
	void extract<T>(out T variableSizeHeader,
		in bit<32> variableFieldSizeInBits);
	/// Чтение битов из пакета без перемещения указателя. @returns содержит
	/// прочитанные биты T может быть произвольным фиксированным заголовком.
	T lookahead<T>();
	/// Перемещение указателя на заданное число битов.
	void advance(in bit<32> sizeInBits);
	/// @return - размер пакета в байтах. Метод поддерживается не всеми
	/// архитектурами.
	bit<32> length();
}
extern packet_out {
	/// запись @data в выходной пакет с пропуском недействительных заголовков
	/// и перемещением указателя. @T может быть заголовком, стеком или
	/// объединением заголовков, а также struct с полями этих типов.
	void emit<T>(in T data);
}
action NoAction() {}
/// Стандартные типы сопоставления для полей ключей в таблице. Некоторые 
/// архитектуры могут поддерживать не все типы сопоставления. Архитектура
/// может задавать свои типы.
match_kind {
	exact,		/// Точное сопоставление.
	ternary,	/// Троичное сопоставление с использованием маски.
	lpm		/// Наибольший совпадающий префикс.
}

Приложение E. Контрольные суммы

В P416 нет встроенных конструкций для работы с контрольными суммами. Предполагается выполнение таких операций внешними объектами, обеспечиваемыми зависимыми от платформы библиотеками. Библиотеке стандартной архитектуры следует включать блоки работы с контрольными суммами. Например, можно предоставить блок инкрементного расчёта контрольных сумм Checksum16 (5.2.4. Доступные внешние блоки) для 16-битовых контрольных сумм с дополнением до 1 с использованием внешнего объекта, как показано ниже.

extern Checksum16 {
	Checksum16();		// конструктор
	void clear();		// подготовка блока к расчётам
	void update<T>(in T data);	// добавление данных в контрольную сумму
	void remove<T>(in T data);	// исключение данных из контрольной суммы
	bit<16> get(); 	// расчёт контрольной суммы для данных, добавленных после очистки
}

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

ck16.clear();		// подготовка блока контрольной суммы
ck16.update(h.ipv4);	// запись заголовка
verify(ck16.get() == 16w0, error.IPv4ChecksumError); // проверка значения 0

Расчёт контрольной суммы IP можно выполнить в форме

h.ipv4.hdrChecksum = 16w0;
ck16.clear();
ck16.update(h.ipv4);
h.ipv4.hdrChecksum = ck16.get();

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

ck16.clear();
ck16.update(h.ipv4.hdrChecksum);	// исходная контрольная сумма
ck16.remove( { h.ipv4.ttl, h.ipv4.proto } );
h.ipv4.ttl = h.ipv4.ttl - 1;
ck16.update( { h.ipv4.ttl, h.ipv4.proto } );
h.ipv4.hdrChecksum = ck16.get();

Приложение F. Ограничения для вызовов при компиляции и работе

В этом приложении описаны ограничения при компиляции и работе программ., многие из которых уже упоминались.

Объектами с состоянием в P416 являются пакеты (package), анализаторы, элементы управления, внешние объекты (extern), таблицы и наборы значений. Функции P416 также относятся к этой группе, даже если они зависят лишь от своих аргументов (pure). Все остальные типы здесь называются типами значений (value type).

Некоторые базовые принципы перечислены ниже.

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

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

  • Внешним элементам не разрешено вызывать анализаторы и элементы управления, поэтому нет смысла передавать им такие объекты.

  • Экземпляры таблиц всегда создаются напрямую во включающих таблицы элементах управления и не могут создаваться на верхнем уровне. Синтаксис задания параметров таблиц не определяется. Таблица предназначена для использования лишь в определившем её элементе управления.

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

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

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

Может быть параметром конструктора для типа

Тип

package

parser

control

extern

package

да

нет

нет

нет

parser

да

да

нет

нет

control

да

нет

да

нет

extern

да

да

да

да

function

нет

нет

нет

нет

table

нет

нет

нет

нет

value-set

нет

нет

нет

нет

Типы значений

да

да

да

да

В следующей таблице показаны ограничения на создание экземпляров (10.3. Создание экземпляров) разных типов. Ответы «нет» в столбце означают, что нет создания экземпляров «внутри пакета» в P416. Можно явно вызвать конструктор и использовать экземпляры типов с состояниями при создании экземпляра пакета с учётом приведённых ниже ограничений. Для типов extern можно указать лишь интерфейс в P416, но не реализацию, поэтому экземпляры внутри extern не создаются. Можно объявить переменные и константы любого из типов значений внутри анализатора, элемента управления или функции (10.2. Переменные). Такое объявление отличается от создания экземпляра, поэтому с таблице указано «-». Переменные нельзя объявлять на верхнем уровне программы, а константы можно.

Экземпляр может создаваться в

Тип

Верхний уровень

package

parser

control

extern

function

package

да

нет

нет

нет

нет

нет

parser

нет

нет

да

нет

нет

нет

control

нет

нет

нет

да

нет

нет

extern

да

нет

да

да

нет

нет

function

да

нет

нет

нет

нет

нет

table

нет

нет

нет

да

нет

нет

value-set

да

нет

да

нет

нет

нет

Типы значений

В следующей таблице приведены ограничения для типов, которые могут передаваться в качестве параметров при работе другим элементам, способным принимать такие параметры (parser, control, extern, action, function).

Может быть параметром в среде выполнения для вызова

Тип

parser

control

method

action

function

package

нет

нет

нет

нет

нет

parser

нет

нет

нет

нет

нет

control

нет

нет

нет

нет

нет

extern

да

да

да

нет

нет

table

нет

нет

нет

нет

нет

value-set

нет

нет

нет

нет

нет

action

нет

нет

нет

нет

нет

function

нет

нет

нет

нет

нет

Типы значений

да

да

да

да

да

Вызовы метода extern могут возвращать лишь типы значений или не возвращать ничего (return void).

В следующей таблице показаны ограничения для вызовов, доступных из разных мест программы P4. Вызов анализатора, элемента управления или таблицы означает применение метода apply(), вызов value-set — использование в выражении select. Строка для extern указывает, откуда можно вызывать внешние методы. Одним из способов вызова extern с верхнего уровня анализатора или элемента управления является выражение инициализатора для объявленной переменной, например, bit<32> x = rand.get();.

Может вызываться при работе из указанного места программы P4

Тип

Состояние анализатора

Метод apply элемента управления

Верхний уровень анализатора или элемента управления

action

extern

function

package

parser

да

нет

нет

нет

нет

нет

control

нет

да

нет

нет

нет

нет

extern

да

да

да

да

нет

нет

table

нет

да

нет

нет

нет

нет

value-set

да

нет

нет

нет

нет

нет

action

нет

да

нет

да

нет

нет

function

да

да

нет

да

нет

да

Типы значений

Вызовы не допускают рекурсии ни напрямую, ни опосредованно (взаимная рекурсия). Методы extern не могут вызывать другие типы программных объектов P4 (6.7.1. Обоснование). Действия могут вызываться напрямую из блока apply элементов управления.

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

Приложение G. Нерешенные проблемы

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

G.1. Обобщённое поведение оператора switch

P416 включает операторы switch (11.7. Оператор выбора) и выражения select (12.6. Выражения для выбора). Они реально различаются в текущей версии языка. Оператор должен оцениваться в значение состояния. Предлагается обобщенный оператор switch, соответствующий принятым в большинстве языков программирования — условие со множеством вариантов, из которых выбирается первый подходящий.

switch(e1,/* параметры опущены */,en) {
	pat_1 : stmt1;
	/* тело опущено */
	pat_m : stmtm;
}

В примере проверяемое значение задано кортежем (e1,/* параметры опущены */,en), а варианты — выражениями, обозначающими наборы значений. Значение соответствует варианту (branch), если оно входит в набор, заданный выражением. В отличие от C и C++, здесь не применяется оператор break для предотвращения перехода к следующему варианту и такой переход возможен лишь при несоответствии значения текущей ветви (метке).

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

Обобщено также устройство обработки для таблиц совпадений и отсутствия (hit/miss) и действий в блоках управления, путём генерации неявных типов для действий и результатов.

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

G.2. Неопределённое поведение

Неопределённость поведения вызывает множество проблем в таких языках, как C и HTML, включая ошибки и серьёзные уязвимости защиты. Есть несколько мест, где оценка программы P4 может приводить к неопределённому поведению — параметры out, неинициализированные переменные, доступ к полям недействительных заголовков или к стекам заголовков за пределами границы стека. Нужно сделать все возможное для устранения неопределённостей, в P416, поэтому предлагается усиливать формулировки спецификации, чтобы исключить описанное выше поведение в принятых по умолчанию случаях. С учётом заботы о производительности предлагается определить флаги компиляции и/или pragma для переопределения заданного по умолчанию поведения. Однако предполагается, что программистам следует создавать защищённые программы и более серьёзно относиться к вопросам безопасности.

G.3. Структурированные итерации

Введение итератора в стиле foreach для работы со стеками заголовков снижает необходимость использования директив препроцессора C для определения размера стеков заголовков. Например,

foreach hdr in hdrs { /// операции над HDR }

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

Приложение H. Грамматика P4

Грамматика P416 описана на языке YACC/bison и не задаёт приоритет операций. Грамматика в реальности неоднозначна, поэтому лексер и синтаксический анализатор должны работать совместно. В частности, лексер должен различать ранее введённые идентификаторы типов (маркеры TYPE_IDENTIFIER) и обычные идентификаторы (маркер IDENTIFIER). Анализатор должен использовать таблицу символов, чтобы указывать лексеру, как следует разбирать последовательные идентификаторы. Например, для приведённого ниже фрагмента

typedef bit<4> t;
struct s { /* тело опущено */}
t x;
parser p(bit<8> b) { /* тело опущено */ }

лексер возвратит показанные ниже виды терминалов

t — TYPE_IDENTIFIER
s — TYPE_IDENTIFIER
x — IDENTIFIER
p — TYPE_IDENTIFIER
b — IDENTIFIER

На эту грамматику оказывают существенное влияние ограничения инструмента генерации анализаторов Bison.

Несколько других терминалов констант присутствуют в приведённых ниже правилах

MASK — это &&&
RANGE — это ..
DONTCARE — это _

Маркер STRING_LITERAL соответствует строковому литералу в двойных кавычках (6.3.3.3. Строковые литералы).

Все остальные терминалы являются представлением ключевых слов заглавными буквами. Например, RETURN — это терминал, возвращаемый лексером при анализе ключевого слова return.

p4program
	: /* пусто */
	| p4program declaration
	| p4program ';'	/* пустое объявление */
	;

declaration
	: constantDeclaration
	| externDeclaration
	| actionDeclaration
	| parserDeclaration
	| typeDeclaration
	| controlDeclaration
	| instantiation
	| errorDeclaration
	| matchKindDeclaration
	| functionDeclaration
	;

nonTypeName
	: IDENTIFIER
	| APPLY
	| KEY
	| ACTIONS
	| STATE
	| ENTRIES
	| TYPE
	;

name
	: nonTypeName
	| TYPE_IDENTIFIER
	;

nonTableKwName
	: IDENTIFIER
	| TYPE_IDENTIFIER
	| APPLY
	| STATE
	| TYPE
	;

optAnnotations
	: /* пусто */
	| annotations
	;

annotations
	: annotation
	| annotations annotation
	;

annotation
	: '@' name
	| '@' name '(' annotationBody ')'
	| '@' name '[' structuredAnnotationBody ']'
	;

parameterList
	: /* пусто */
	| nonEmptyParameterList
	;

nonEmptyParameterList
	: parameter
	| nonEmptyParameterList ',' parameter
	;

parameter
	: optAnnotations direction typeRef name
	| optAnnotations direction typeRef name '=' expression
	;

direction
	: IN
	| OUT
	| INOUT
	: /* пусто */
	;

packageTypeDeclaration
	: optAnnotations PACKAGE name optTypeParameters
	'(' parameterList ')'
	;
nonBraceExpression
    	: INTEGER
    	| STRING_LITERAL
    	| TRUE
    	| FALSE
    	| THIS
    	| nonTypeName
    	| dotPrefix nonTypeName
    	| nonBraceExpression '[' expression ']'
    	| nonBraceExpression '[' expression ':' expression ']'
    	| '(' expression ')'
    	| '!' expression %prec PREFIX
    	| '~' expression %prec PREFIX
    	| '-' expression %prec PREFIX
    	| '+' expression %prec PREFIX
    	| typeName '.' member
    	| ERROR '.' member
    	| nonBraceExpression '.' member
    	| nonBraceExpression '*' expression
    	| nonBraceExpression '/' expression
    	| nonBraceExpression '%' expression
    	| nonBraceExpression '+' expression
    	| nonBraceExpression '-' expression
    	| nonBraceExpression '|+|' expression
    	| nonBraceExpression '|-|' expression
    	| nonBraceExpression '<<' expression
        | nonBraceExpression '>>' expression
    	| nonBraceExpression '<=' expression
        | nonBraceExpression '>=' expression
    	| nonBraceExpression '<' expression
        | nonBraceExpression '>' expression
    	| nonBraceExpression '!=' expression
    	| nonBraceExpression '==' expression
    	| nonBraceExpression '&' expression
    	| nonBraceExpression '^' expression
    	| nonBraceExpression '|' expression
    	| nonBraceExpression '++' expression
    	| nonBraceExpression '&&' expression
    	| nonBraceExpression '||' expression
    	| nonBraceExpression '?' expression ':' expression
    	| nonBraceExpression '<' realTypeArgumentList '>' '(' argumentList ')'
    	| nonBraceExpression '(' argumentList ')'
    	| namedType '(' argumentList ')'
    	| '(' typeRef ')' expression
    	;

Перевод на русский язык

Николай Малых

nmalykh@protokols.ru

1Перевод статьи доступен на сайте www.protokols.ru. Прим. перев.

2Very Simple Switch — очень простой коммутатор.

3Старших битов. Прим. перев.

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

5В оригинале ошибочно дана ссылка на раздел 7. Прим. перев.

Рубрика: Сетевое программирование | Оставить комментарий

RFC 8991 GeneRic Autonomic Signaling Protocol Application Program Interface (GRASP API)

Internet Engineering Task Force (IETF)                      B. Carpenter
Request for Comments: 8991                             Univ. of Auckland
Category: Informational                                      B. Liu, Ed.
ISSN: 2070-1721                                      Huawei Technologies
                                                                 W. Wang
                                                                 X. Gong
                                                         BUPT University
                                                                May 2021

GeneRic Autonomic Signaling Protocol Application Program Interface
(GRASP API)

Интерфейс GRASP API

PDF

Аннотация

Этот документ содержит концептуальную схему интерфейса с прикладными программами (Application Programming Interface или API) для базового протокола автоматической сигнализации (GeneRic Autonomic Signaling Protocol или GRASP). Такой интерфейс нужен агентам автономных служб (Autonomic Service Agent или ASA), вызывающим модуль протокола GRASP, для обмена сообщениями автономной сети (Autonomic Network) с другими агентами ASA. Поскольку протокол GRASP рассчитан на поддержку асинхронных операций, интерфейс API нужно приспосабливать к поддержке асинхронной работы в различных языках программирования и операционных системах.

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

Документ не содержит какой-либо спецификации (Internet Standards Track) и публикуется с информационными целями.

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

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

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

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

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

1. Введение

Как определено в [RFC8993], агент автономной службы (Autonomic Service Agent или ASA) — это неделимая (atomic) сущность автономной функции, создаваемая на самоуправляемых (autonomic) узлах. Эти узлы являются частью защищённой автономной плоскости управления (Autonomic Control Plane или ACP), такой, как определена в [RFC8994].

При взаимодействии между агентами ASA им следует применять базовый протокол автономной сигнализации (GeneRic Autonomic Signaling Protocol или GRASP) [RFC8990]. GRASP полагается на конфиденциальность и целостность, обеспечиваемые ACP, поэтому все узлы данной самоуправляемой сети (Autonomic Network) используют общую границу доверия, т. е. границу ACP. Узлы, не присоединившиеся к ACP, не могут передавать, принимать или перехватывать сообщения GRASP через ACP и не могут использовать адреса ACP. Агент ASA работает на узле ACP и при передаче сообщений через ACP использует свойства защиты, т. е., целостность и конфиденциальность сообщений, а также невозможность присоединения к ACP неуполномоченных узлов. В результате этого все ASA в данной самоуправляемой сети могут доверять сообщениям от других узлов. Поэтому определённый в документе интерфейс API не включает явных функций защиты.

Важным свойством GRASP является концепция задачи GRASP. Это структура данных, закодированная как и все сообщения GRASP в краткое представление бинарного объекта (Concise Binary Object Representation или CBOR) [RFC8949]. Основным содержимым структуры является имя и значение, как описано в разделе «Терминология» [RFC8990]. Когда задача передаётся от одного агента ASA к другому с использованием GRASP, значение переносится в одном направлении (синхронизация или лавинная отправка) или согласуется между двумя сторонами. Семантика значения не разбирается (opaque) GRASP и, следовательно, API. Каждая задача должна быть точно задана в выделенной спецификации, как указано в параграфе 2.10 «Опции задачи» [RFC8990]. В частности, спецификация задаёт синтаксис и семантику значения задачи, определяет поддержку согласования и режима пробного использования (dry-run), а также другие детали, требуемые для функциональной совместимости. Использование CBOR с языком краткого определения данных (Concise Data Definition Language или CDDL) [RFC8610] в качестве языка определения данных позволяет передавать значение между ASA независимо от применяемых языков программирования. За хранение и согласованность данных в процессе их согласования отвечают участвующие агенты ASA. Кроме того, протоколу GRASP требуется кэшировать последние значения задач, полученные лавинным путём.

На рисунке показана реализация GRASP с несколькими подуровнями. Нижним уровнем является модуль базового протокола GRASP, который отвечает лишь за передачу и приём сообщений GRASP и поддержку общих структур данных. Над ним размещается базовый интерфейс API, описанный в этом документе. Верхний уровень содержит некоторые необязательные функции API, основанные на базовом протоколе GRASP. Например, в [GRASP-DISTRIB] описана одна из возможных функций расширения.

 +--------------+          +--------------+
 |  Агенты ASA  |          |  Агенты ASA  |
 +--------------+          +--------------+
   |          |                    |
   | +------------------+          |
   | | API расширенных  |          |
   | | функций GRASP    |          |
   | +------------------+          |
   |          |                    |
+------------------------------------------+
|       Библиотека базового GRASP API      |
+------------------------------------------+
                    |
            IPC или системный вызов
                    |
+------------------------------------------+
|  Ядро GRASP                              |
|  (функции, структуры данных, демоны      |
+------------------------------------------+

Рисунок . Программная схема.


Несколько ASA на одном узле будут совместно использовать один экземпляр GRASP, подобно использованию одного стека TCP/IP множеством приложений. Этот аспект скрыт от индивидуальных ASA интерфейсом API и далее не рассматривается.

Желательно создавать ASA в форме переносимых программ пользовательского пространства, применяющих системно-независимый API. Во многих реализациях код GRASP в результате разделён между пользовательским пространством и ядром. В пользовательском пространстве библиотечные функции обеспечивают API и напрямую взаимодействуют с ASA. В ядре демон или набор субслужб предоставляет не зависящие от конкретных ASA функции ядра GRASP, такие как обработка групповой передачи и ретрансляция, а также общие структуры данных, такие как кэш обнаружения. Библиотека GRASP API должна взаимодействовать с ядром GRASP через IPC3 или системные вызовы. Детяли этих взаимодйствий зависят от системы.

Библиотеку GRASP и модули расширенных функций следует делать доступными для ASA. Однако расширенные функции могут добавляться постепенно, поэтому они могут быть описаны в будущих документах, а здесь описывается лишь базовый интерфейс GRASP API.

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

Помимо компонентов автономной инфраструктуры, описанных в [RFC8994] и [RFC8995], простой самонастраиваемый узел может содержать лишь несколько ASA. Такой узел может напрямую включать стек GRASP в свой код и не требовать установки API. Однако в этом случае программистам придётся вникать в детали GRASP глубже, чем при работе через API.

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

2. GRASP API для ASA

2.1. Допущения при разработке

Предполагается, что агент ASA должен вызывать отдельную реализацию GRASP, которая обрабатывает протокольные детали (защита, отправка и прослушивание сообщений GRASP, ожидание, кэширование результатов обнаружения, циклы согласования, передача и приём при синхронизации данных и т. п.), но ничего не знает о конкретных задачах GRASP (см. параграф 2.10 в [RFC8990]). Семантика задач GRASP неизвестна протоколу и обрабатывается только агентами ASA. Это является абстрактным интерфейсом API для использования агентами ASA. Привязки к конкретным языкам следует задавать в отдельных документах.

Разные ASA могут применять функции GRASP по своему для:

  • обнаружения;

  • согласования в качестве инициатора (клиент);

  • согласования в качестве ответчика;

  • согласования в качестве инициатора или ответчика;

  • синхронизации в качестве инициатора (получатель);

  • синхронизации в качестве ответчика и/или выполняющего лавинную отправку;

  • синхронизации в качестве инициатора, ответчика и/или выполняющего лавинную отправку.

API также предполагает возможность поддержки одним агентом ASA множества задач. Ничто не мешает ASA использовать одни задачи для синхронизации, а другие — для согласования.

Устройство API предполагает, что операционная система и язык программирования обеспечивают механизмы для одновременных асинхронных операций, как описано в параграфе 2.2.

Некоторые аспекты не включены в данную версию, поскольку они требуют практического опыта:

  • предоставление полномочий агентам ASA не определено как часть GRASP и требует изучения;

  • предоставляемые пользователем явные локаторы задач не поддерживаются; ядро GRASP предоставляет локатор, используя IP-адрес соответствующего узла;

  • быстрый режим GRASP (параграф 2.5.4 в [RFC8990]) не поддерживается.

2.2. Асинхронные операции

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

2.2.1. Варианты асинхронных механизмов

Некоторые ASA должны поддерживать асинхронные операции, поэтому ядро протокола GRASP должно делать это. В зависимости от операционной системы и применяемого языка программирования имеется несколько вариантов параллельной работы, три из которых рассмотрены ниже (многопоточность, циклы событий с использованием опроса, структура цикла событий с использованием обратных вызовов — callback).

  1. При многопоточности операционная система и язык программирования обеспечивают требуемую поддержку асинхронных операций, включая создание новых потоков (thread), переключение контекста между потоками, очереди, блокировки и неявные состояния ожидания. В этом случае вызовы API можно считать просто синхронными вызовами в рамках потока, даже если функция включает состояния ожидания, блокировки и очередей. Одновременные операции выполняются в своих потоках. Например, вызов discover() может не возвращать управления, пока не поступит результат обнаружения или не возникнет тайм-аут. Если у ASA есть другая работа для выполнения, вызов discover() следует выполнять в отдельном потоке.

  2. При реализации цикла событий с опросом блокирующие вызовы недопустимы, поэтому все вызовы должны быть неблокирующими, а главный цикл может поддерживать несколько сессий GRASP параллельно, периодически опрашивая каждую на предмет смены состояния. Для этого в реализации API предусматриваются неблокирующие версии всех функций, которые иначе могли бы включать блокировку и постановку в очередь. В этих вызовах будет возвращаться код noReply вместо блокировки, пока не произойдет ожидаемое событие (или отказ). Например, вызов discover() будет возвращать noReply вместо ожидания обнаружения или тайм-аута. Вызов discover() будет повторяться в каждой итерации главного цикла, пока он не завершится. По сути это становится опросом.

  3. Выше было отмечено, что некоторые сообщения GRASP не являются идемпотентными. В частности, это относится к каждому этапу сеансов согласования — отправка одного сообщения дважды может приводить к нежелательным побочным эффектам. Этого не возникает в опросе цикла событий — повторный вызов после получения noReply не повторяет сообщение, а просто проверяет наличие отклика.

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

2.2.2. Несколько сессий согласования

Устройство GRASP позволяет реализовать описанный ниже сценарий. Рассмотрим ASA A, выступающий распределителем ресурсов для некой задачи. Агент ASA B запускает согласование с A для получения или освобождения некоторого объёма ресурса. Пока это согласование происходит, B решает запустить согласование с агентом A другого объёма того же ресурса. В результате агент A должен поддерживать два отдельных сеанса согласования, не смешивая их.

Отметим, что агенты ASA могут быть спроектированы так, чтобы избегать таких ситуаций, т. е. разрешать лишь 1 сеанс согласования в каждый момент для данной задачи, но это является произвольным ограничением, не требуемым протоколом GRASP. На деле GRASP предполагает, что для любого ASA, управляющего ресурсом, может потребоваться поддержка нескольких параллельный согласований, возможно, с одним и тем же партнёром. Схемы взаимодействия могут быть очень сложными, когда в группе агентов ASA согласования между собой перекрываются, как описано в [ANIMA-COORD]. Поэтому устройство API разрешает такие сценарии.

В модели с обратными вызовами для описанного выше сценария агенты A и B будут предоставлять два экземпляра callback-функции (по 1 для каждой сессии). По этой причине каждый агент ASA должен уметь различать сессии, но IP-адреса партнёра для этого недостаточно. Небезопасно и полагаться на номера транспортных портов, поскольку в будущих версиях GRASP могут применяться общие порты вместо отдельного порта для каждой сессии. Поэтому протокол GRASP включает Session ID. Таким образом, при необходимости в API различать одновременные сессии GRASP между парой партнёров используется дескриптор сессии (handle).

2.2.3. Перекрытие сессий и операций

Сессия GRASP состоит из конечной последовательности сообщений (для обнаружения, синхронизации или согласования) между парой ASA. Сессия однозначно указывается в линии псевдослучайным идентификатором Session ID и IP-адресом инициатора сессии. Дополнительные сведения приведены в параграфе 2.7 «Идентификатор сессии (Session ID)» [RFC8990].

При первом вызове в новой сессии GRASP интерфейс API возвращает дескриптор session_handle, однозначно указывающий сессию внутри API, что позволяет различать перекрывающиеся сеансы. Вероятная реализация дескриптора заключается в его формировании из базовых GRASP Session ID и адреса IP. Этот дескриптор должен применяться во всех последующих вызовах в рамках этой сессии (см. параграф 2.3.2.8).

Дополнительным механизмом повышения эффективности реализации опроса является добавление вызова общего назначений, скажем, notify(), который проверяет статус всех незавершённых операций для вызывающего агента ASA и возвращает значения session_handle для всех сеансов с изменившимся состоянием. Это избавит от необходимости повторных вызовов отдельных функций, возвращающих noReply. Этот вызов не описывается более подробно, поскольку его детали явно будут зависеть от реализации.

Следствием изложенного выше для всех реализаций GRASP является необходимость хранения ядром GRASP состояния каждой выполняемой операции GRASP, наиболее вероятно, указываемое GRASP Session ID и адресом инициатора сессии. Даже в потоковой реализации ядру GRASP требуются такие состояния для внутренней работы. Параметр session_handle раскрывает этот аспект реализации.

2.2.4. Завершение сессии

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

2.3. Определение API

2.3.1. Обзор функций

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

Registration — регистрация

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

Discovery — обнаружение

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

Negotiation — согласование

Эти функции позволяют ASA выступать инициатором (запрашивающий) или ответчиком (слушающий) для сессии согласования GRASP. После инициирования согласование является симметричным процессом и большинство функций может использовать любая из сторон.

Synchronization — синхронизация

Эти функции позволяют ASA выступать инициатором (запрашивающий) или ответчиком (слушающий) для сессии синхронизации GRASP.

Flooding — лавинная отправка

Эти функции позволяют ASA передавать и принимать задачу, рассылаемую лавинно всем узлам ACP.

В [ASA-GUIDE] представлены примеры логических потоков для управляющего ресурсами агента ASA, которые могут помочь разобраться с приведёнными ниже описаниями. В следующем параграфе описаны параметры и структуры данных, применяемые для вызовов API, а затем рассматриваются различные группы функций API. API, для которых не указаны асинхронные механизмы, неявно являются синхронными по своему поведению.

2.3.2. Параметры и структуры данных

2.3.2.1. Целые числа

В этом API целочисленные значения предполагаются 32-битовыми числами без знака (uint32_t), если не указано иное.

2.3.2.2. Коды ошибок

Все функции API имеют целое число errorcode в качестве кода возврата (первое возвращаемое значение в языках, позволяющих возвращать несколько значений). Значение errorcode = 0 указывает успешное выполнение, все остальные — ошибку. Три первых кода ошибок имеют особое значение, как указано ниже.

1 — Declined (отклонено)

Другая сторона передала сообщение GRASP Negotiation End (M_END) с опцией Decline (O_DECLINE).

2 — No reply (нет ответа)

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

3 — Unspecified error (неуказанная ошибка)

Используется в случаях отсутствия подходящего кода ошибки.

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

2.3.2.3. Тайм-аут

Значения параметра timeout указываются в миллисекундах целым числом без знака. При нулевом значении параметра применяется заданный по умолчанию тайм-аут GRASP (GRASP_DEF_TIMEOUT [RFC8990]). Исключением является функция discover(), для которой нулевой тайм-аут интерпретируется иначе. Если в интервале timeout не получено ответа, вызов считается завершившимся отказом (когда явно не указано иное).

2.3.2.4. Задача

Параметр objective является структурой данных с описанными ниже полями.

name (UTF-8 string)

Имя задачи.

neg (Boolean flag)

True, если задача поддерживает согласование (по умолчанию False)

synch (Boolean flag)

True, если задача поддерживает синхронизацию (по умолчанию False)

dry (Boolean flag)

True, если задача поддерживает пробное (dry-run) согласование (по умолчанию False)
Примечание 1. Значение True может иметь лишь один из флагов synch и neg.
Примечание 2. Флаг Key не может иметь значения True, пока не задано neg = True.
Примечание 3. В некоторых языках программирования может быть предпочтительно указание флагов Boolean битами одного байта, который затем кодируется в сообщения GRASP. В других языках может быть предпочтительным перечисляемое значение (enumeration).

loop_count (целое число без знака, uint8_t)

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

value

Конкретная структура данных, указывающая значение задачи. Структура зависит от языка программирования с учётом ограничений CBOR [RFC8949].
Важным преимуществом CBOR является то, что значение задачи может быть совершенно непонятным (opaque) для ядра GRASP, но при этом должно передаваться в агент ASA и из него. Хотя ядро GRASP должно проверять формат и синтаксис сообщений GRASP, оно не может проверять значение задачи и способно проверить лишь корректность формата CBOR. Обработка при декодировании зависит от применяемой библиотеки CBOR, но соответствующий код ошибки (CBORfail) задаётся в API и возвращается агенту ASA, если ошибочное сообщение может быть отнесено к текущей сессии GRASP. Однако каждый агент ASA отвечает за проверку значения полученной задачи, как указано в параграфе 5.3 [RFC8949]. Если используется подходящий объектно-ориентированный язык программирования, GRASP API может десериализовать значение и представить его ASA как задачу. В иных случаях значение представляется как объект данных CBOR. В любом случае синтаксис и семантика значения задачи относятся к зоне ответственности ASA.
Требованием ко всем привязкам к языку и реализациям API является возможность использования в качестве значения необработанного элемента данных CBOR, независимо от наличия других вариантов представления. API «оборачивает» его с тегом CBOR Tag 24 как элемент данных в кодировке CBOR для передачи через GRASP и «разворачивает» при получении. Это обеспечивает агентам ASA возможность взаимодействия, не зависящего от языка программирования.

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

Ниже представлен пример определения структуры данных для задачи на языке C с использованием версии не ниже C99 в предположении использования библиотеки CBOR [libcbor].

    typedef struct {
       unsigned char *name;
       uint8_t flags;            // Биты флагов, определённые GRASP
       uint8_t loop_count;
       uint32_t value_size;      // Размер значения в байтах
       cbor_mutable_data cbor_value;
                                // CBOR bytestring (libcbor/cbor/data.h)
                    } objective;

Ниже представлен пример определения структуры данных для задачи на языке Python (версия 3.4 или выше).

    class objective:
       """A GRASP objective"""
       def __init__(self, name):
           self.name = name        #Уникальное имя (string)
           self.negotiate = False  #True, если поддерживается согласование
           self.dryrun = False     #True, если поддерживается dry-run
           self.synch = False      #True, если поддерживается синхронизация
           self.loop_count = GRASP_DEF_LOOPCT  # Принятое по умолчанию стартовое значение
           self.value = None       #Владелец (любой объект Python)
2.3.2.5. asa_locator

Параметр asa_locator является структурой данных с описанными ниже полями.

locator

Фактический локатор (адрес IP или строка ASCII).

ifi (целое число без знака)

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

expire (тип зависит от системы)

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

Ниже указаны все типы локаторов, поддерживаемые GRASP в настоящее время.

is_ipaddress (Boolean)

True, если локатором является адрес IP.

is_fqdn (Boolean)

True, если локатором является полное доменное имя (Fully Qualified Domain Name или FQDN).

is_uri (Boolean)

True, если локатором является URI.

Эти варианты являются взаимоисключающими. В зависимости от языка программирования они могут быть представлены битовыми шаблонами или перечисляемыми значениями.

diverted (Boolean)

True, если локатор обнаружен с помощью опции Divert.

protocol (целое число без знака)

Применяемый транспортный протокол (IPPROTO_TCP или IPPROTO_UDP). Эти константы заданы в CDDL-спецификации GRASP [RFC8990].

port (целое число без знака)

Применяемый номер порта.

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

Следует отметить, что при обнаружении ASA значения asa_locator другого агента не применяется явной проверки подлинности. В соответствии с моделью доверия защищённой плоскости ACP агенты ASA предполагаются предоставляющими при обнаружении корректные локаторы. Дополнительные сведения приведены в параграфе 2.9.5 «Опции локации» [RFC8990].

2.3.2.6. tagged_objective

Параметр tagged_objective является структурой данных с описанными ниже полями.

objective

Задача.

locator

Связанный с задачей параметр asa_locator или значение null.
2.3.2.7. asa_handle

Хотя схемы проверки подлинности и полномочий для ASA не определены, API обеспечивает очень простую ловушку для такой схемы. При старте ASA агент регистрируется в ядре GRASP, которое предоставляет ему неинтерпретируемый (opaque) дескриптор, не имеющий криптографической защиты, но сложный для предсказания посторонними. Агент ASA должен предоставлять этот дескриптор при последующих вызовах. Этот механизм предотвращает некоторые элементарные ошибки и тривиальные атаки, такие как манипуляции с задачами со стороны незарегистрированных ASA.

Таким образом, параметр asa_handle требуется для большинства вызовов. Он создаётся при регистрации ASA в GRASP и агент ASA должен сохранять asa_handle и применять его при каждом последующем вызове GRASP. Вызовы с непригодным дескриптором будут завершаться отказом. Дескриптор является 32-битовым неинтерпретируемым значением (например, uint32_t). Поскольку дескриптор применяется лишь локально без передачи в сообщениях GRASP, его уникальность должна обеспечиваться лишь в рамках экземпляра GRASP. Дескриптор действует до завершения работы ASA. Дескриптор следует делать непредсказуемым, например, с использованием того же механизма, который применяется GRASP для создания Session ID (параграф 2.3.2.8).

2.3.2.8. session_handle и обратные вызовы

В некоторых вызовах требуется параметр session_handle, который является структурой данных, не интерпретируемой (opaque) ASA, и служит для индикации вызовов API, связанных с конкретной сессией GRASP (см. параграф 2.2.3). Параметр применяется в обратных вызовах (callback). Кроме указания конкретной сессии этот параметр позволяет GRASP обнаруживать и игнорировать вызовы из несуществующих и просроченных сессий.

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

discover() с обратным вызовом discovery_received();

request_negotiate() с обратным вызовом negotiate_step_received();

negotiate_step() с обратным вызовом negotiate_step_received();

listen_negotiate() с обратным вызовом negotiate_step_received();

synchronize() с обратным вызовом synchronization_received().

Детали обратных вызовов зависят от реализации.

2.3.3. Регистрация

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

register_asa()

Все агенты ASA должны использовать этот вызов до обращения к каким-либо иным функциям API.
  • Входной параметр:
    имя (name) ASA (UTF-8 string).
  • Возвращаемое значение:
    errorcode (целое число без знака)
    asa_handle (целое число без знака)
  • Функция инициализирует в модуле GRASP состояние для вызывающего элемента (ASA). При успешном выполнении функция возвращает дескриптор asa_handle, который агент ASA должен предоставлять в последующих вызовах. В случае отказа ASA не получает полномочий и не может работать. Значение asa_handle будет неопределённым.

deregister_asa()

  • Входные параметры:
    asa_handle (целое число без знака);
    имя (name) ASA (UTF-8 string).
  • Возвращаемое значение:
    errorcode (целое число без знака).
  • Удаляет из модуля GRASP все состояния для вызывающего элемента (ASA) и отменяет регистрацию всех зарегистрированных им задач. Эти действия должны выполняться автоматически при завершении работы ASA.
  • Имя ASA, строго говоря, является избыточным в таких вызовах, но сохранено для обнаружения и отклонения ошибочных отмен регистрации.

register_objective()

Агенты ASA должны использовать этот вызов для любой задачи, которая передаётся при согласовании, синхронизации или лавинной отправке.
  • Входные параметры:
    asa_handle (целое число без знака);
    objective (structure);
    ttl (целое число без знака, по умолчанию GRASP_DEF_TIMEOUT);
    discoverable (Boolean, по умолчанию False);
    overlap (Boolean, по умолчанию False);
    local (Boolean, по умолчанию False).
  • Возвращаемое значение:
    errorcode (целое число без знака).
  • Функция регистрирует задачу, которую этот агент ASA может изменять и передавать другим ASA при лавинной рассылке или согласовании. Не требуется регистрировать задачи, которые лишь принимаются GRASP при синхронизации или лавинной рассылке. Задача (objective) становится кандидатом для обнаружения. Однако отклики на обнаружение не следует разрешать, пока ASA не вызовет функцию listen_negotiate() или listen_synchronize(), показывающую способность агента выступать ответчиком. ASA может согласовывать задачу, передавать данные синхронизации или рассылать данные лавинно. Регистрация не требуется для операций лишь чтения (read-only), когда ASA хочет лишь принимать данные синхронизации или лавинной рассылки для соответствующей задачи.
  • Параметр ttl указывает действительный срок действия (время жизни) в миллисекундах любого отклика на обнаружение, созданного для этой задачи. По умолчанию следует применять заданный по умолчанию тайм-аут GRASP (GRASP_DEF_TIMEOUT, см. [RFC8990]).
  • Если discoverable = True, задача сразу же становится доступной для обнаружения. Это предназначено для задач, которые определены лишь для обнаружения GRASP и не поддерживают согласование и синхронизацию.
  • Если overlap = True, эта задача может регистрироваться несколькими ASA в одном экземпляре GRASP. Это имеет значение для управления жизненным циклом агентов ASA [ASA-GUIDE] и должно применяться согласованно для данной задачи (всегда True или всегда False).
  • Если local = True, обнаружение должно возвращать адрес локального канала (link-local). Это предназначено для задач, которые должны быть ограничены локальным каналом.
  • Этот вызов может повторяться для нескольких задач.

deregister_objective()

  • Входные параметры:
    asa_handle (целое число без знака);
    objective (structure).
  • Возвращаемое значение:
    errorcode (целое число без знака).
  • Задача objective должна быть зарегистрирована вызовом ASA, в противном случае этот вызов ведёт к отказу. При дерегистрации удаляются все состояния в модулей GRASP для данной задачи.

2.3.4. Обнаружение

discover()

Эту функцию может применять любой агент ASA для обнаружения партнёров, обрабатывающих данную задачу.
  • Входные параметры:
    asa_handle (целое число без знака);
    objective (structure);
    timeout (целое число без знака);
    minimum_TTL (целое число без знака).
  • Возвращаемые значения:
    errorcode (целое число без знака);
    locator_list (structure).
  • Функция возвращает список asa_locator для данной задачи, пустой список говорит о том, что за время ожидания (timeout) локаторов не найдено. Структура включает поля, указанные в параграфе 2.3.2.5.
  • Параметр minimum_TTL должен быть не меньше 0. Все кэшированные локаторы для задачи, срок действия которых в миллисекундах не превышает значения minimum_TTL, удаляются, поэтому при значении minimum_TTL = 0 исключаются все записи. Отметим, что это не влияет на продолжающиеся сессии, которые используют удаляемые локаторы.
  • Если timeout = 0, сразу же возвращаются все остающиеся локально кэшированные локаторы для задачи и других действий не выполняется. Поэтому вызов с minimum_TTL = 0 и timeout = 0 не имеет смысла.
  • Если timeout > 0, выполняется обнаружение GRASP и возвращаются все результаты, полученные до завершения времени ожидания (timeout). Если результатов нет, после тайм-аута возвращается пустой список и это не считается ошибкой. Обнаружение GRASP не является детерминированным процессом. Если имеется несколько узлов, обрабатывающих задачу до истечения тайм-аута могут быть обнаружены все, часть или ни одного из таких узлов.
  • Асинхронные механизмы

    Потоковая реализация

    Если нужна асинхронная операцию, эту функцию следует вызывать в отдельном потоке.

    Реализация цикла событий

    Используется дополнительный параметр session_handle. Если errorcode имеет значение 2 (noReply), это говорит, что отклик ещё не получен. Параметр session_handle должен указываться при последующих вызовах. При ненулевом времени ожидания можно использовать обратный вызов (callback).

2.3.5. Согласование

Инициатор                         Ответчик
---------                         --------
                                  listen_negotiate() \ Ожидание запроса

request_negotiate()
          M_REQ_NEG      ->       negotiate_step()   \ Создание сессии,
                         <-      M_NEGOTIATE         / начало согласования
negotiate_step()
        M_NEGOTIATE      ->       negotiate_step()   \ Продолжение
                         <-      M_NEGOTIATE         / согласования
                         ...
negotiate_wait()                                     \ Вставка
        M_WAIT           ->                          / задержки
negotiate_step()
        M_NEGOTIATE      ->       negotiate_step()   \ Продолжение
                         <-      M_NEGOTIATE         / согласования
negotiate_step()
        M_NEGOTIATE      ->       end_negotiate()    \ Конец
                         <-      M_END               / согласования

                                                     \ Результаты процесса

Рисунок . Последовательность согласования.


Механизм согласования отличается от типичного обмена между клиентом и сервером, поэтому на рисунке показана последовательность вызовов и сообщений GRASP при согласовании. Отметим, что после первого протокольного обмена процесс становится симметричным и шаги согласования строго чередуются между двумя сторонами. Согласование может завершить любая из сторон. Кроме того, сторона, которой нужно отвечать следующей, может в любой момент внести задержку, для продления времени ожидания другой стороны. Это может применяться, например, если ASA требуется согласование с третьей стороной для продолжения текущего согласования.

Счётчик циклов, встроенный в задачу, являющийся предметом согласования, инициализируется агентом ASA, начинающим согласование, и декрементируется ядром GRASP на каждом шаге перед отправкой сообщения M_NEGOTIATE. При достижении 0 согласование завершается отказом и каждая сторона получает код ошибки.

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

Отказ при согласовании, тайм-аут или обнуление счётчика цикла могут завершать сеанс согласования, но это не считается отказом протокола.

request_negotiate()

Эта функция применяется агентом ASA для инициирования согласования задачи GRASP в качестве запрашивающей стороны (клиента).
  • Входные параметры:
    asa_handle (целое число без знака);
    objective (structure);
    peer (asa_locator);
    timeout (целое число без знака).
  • Возвращаемые значения:
    errorcode (целое число без знака);
    session_handle (structure) (не определена до успешного завершения);
    proffered_objective (structure) (не определена до успешного завершения);
    reason (string) (пуста, пока согласование не отвергнуто).
  • Функция открывает сеанс согласования между парой ASA. Отметим, что GRASP с настоящее время не поддерживает многосторонние согласования, которые требуется добавить в виде расширенной функции.
  • Параметр objective должен включать запрашиваемое значение, а для его счётчика цикла агенту ASA следует устанавливать подходящее значение. В противном случае будет использоваться принятое по умолчанию значение GRASP.
  • Отметим, что данный сеанс согласования может (но не обязан) быть пробным (dry-run); два режима недопустимо смешивать в одной сессии.
  • Параметр peer указывает целевой узел, это должно быть значение asa_locator, возвращённое функцией discover(). При пустом значении peer сначала автоматически выполняется обнаружение GRASP для нахождения подходящего партнёра (т. е., любого узла, поддерживающего рассматриваемую задачу).
  • Параметр timeout описан в параграфе 2.3.2.3.
  • Если в errorcode возвращается значение 0, это говорит об успешном начале согласования. Здесь возможны два случая.
    1. Пустой параметр session_handle. Согласование завершилось за 1 обмен и партнёр воспринял запрос. Возвращённая структура proffered_objective содержит значение, воспринятое партнёром, которое, следовательно, совпадает с objective в запросе. Дескриптор сессии не нужен, так как она завершена.
    2. Непустой параметр session_handle. Согласование должно продолжаться и в последующих шагах должно указываться значение session_handle. Возвращённая структура proffered_objective содержит первое значение, предпочтённое партнёром обмене сообщениями, иными словами, встречное предложение. Содержимое этого экземпляра objective должно использоваться для подготовки следующего шага согласования (см. negotiate_step() ниже), поскольку в нем указан счётчик цикла от партнёра. Код GRASP автоматически декрементирует счётчик на 1 при каждом шаге и возвращает ошибку при достижении 0. Поскольку обнуление счётчика прерывает согласование, на другой стороне возникает тайм-аут, прерывающий сессию.
За этой функцией должны следовать вызовы negotiate_step, negotiate_wait, end_negotiate, пока согласование не завершится. После этого можно вызвать request_negotiate для нового согласования.
  • Значение errorcode = 1 (declined) указывает, что партнёр отверг согласование (M_END и O_DECLINE в GRASP). Строка reason содержит сведения о причине отказа (для информирования и диагностики), но может быть пустой. При этой и других ошибках рекомендуется экспоненциально увеличивать интервал до следующего вызова (см. раздел 3).
  • Асинхронные механизмы

    Потоковая реализация

    Для асинхронных операций функцию следует вызывать в отдельном потоке.

    Реализация цикла событий

    Параметр session_handle служит для различения одновременных сессий. Значение errorcode = 2 (noReply) указывает, что отклик ещё не получен. В последующих вызовах должен применяться параметр session_handle.
  • Использование режима dry-run должно быть согласовано с сессией GRASP. Состояние флага Key в исходном вызове request_negotiate() должно сохраняться при последующих вызовах в той же сессии. Семантика режима пробного запуска (dry-run) встроена в ASA, а GRASP лишь передаёт бит флага.
  • Для агентов ASA инфраструктуры ACP вполне вероятна необходимость обнаружения и согласования с партнёрами в каждом из соседей по каналу связи (on-link). Поэтому агенту нужно знать не только адрес link-local IP, но также физический интерфейс и транспортный порт для каждого соседа. Одним из вариантов реализации этого является включение таких деталей в структуру данных session_handle, не интерпретируемую (opaque) обычными ASA.

listen_negotiate()

Эту функцию агент ASA использует для начала своей работы в качестве ответчика при согласовании (слушающий) для данной задачи GRASP.
  • Входные параметры:
    asa_handle (целое число без знака);
    objective (structure).
  • Возвращаемые значения:
    errorcode (целое число без знака);
    session_handle (structure) (не определена до успешного завершения);
    requested_objective (structure) (не определена до успешного завершения).
  • Эта функция указывает GRASP прослушивать запросы согласования для задачи objective, а также включает отклики на запросы обнаружения данной задачи, как указано в описании register_objective() (параграф 2.3.3).
  • Асинхронные механизмы

    Потоковая реализация

    Функция блокируется в состоянии ожидания входящего запроса, поэтому её следует вызывать в отдельном потоке, если нужна асинхронная операция. Если не возникло неожиданного отказа, вызов возвращает управление только после получения входящего запроса на согласование. Если ASA поддерживает несколько одновременных транзакций, для каждой новой сессии должен запускаться новый субпоток, чтобы можно было сразу вызвать listen_negotiate().

    Реализация цикла событий

    Для различения сессий применяется параметр session_handle. Если ASA поддерживает несколько одновременных транзакций, для каждой новой сессии должен внедряться новый цикл событий, чтобы можно было сразу вызвать listen_negotiate().
  • Этот вызов возвращает управление (потоковая модель) или вызывает срабатывание триггера (цик событий) лишь после получения входящего запроса. Когда это происходит, requested_objective содержит первое значение, запрашиваемое партнёром. Содержимое этого экземпляра задачи (objective) должно использоваться при последующих вызовах, поскольку в нем указан счётчик цикла от партнёра по согласованию. Параметр session_handle должен указываться во всех последующих шагах согласования.
  • За этой функцией должен следовать вызов negotiate_step, negotiate_wait, end_negotiate, пока согласование не завершится.
  • Если агент ASA способен одновременно обслуживать несколько согласований, он может вызвать listen_negotiate в нескольких потоках одновременно или вставить несколько событий. API и реализация GRASP должны поддерживать реентерабельное использование статуса прослушивания и вызовов согласования. Одновременные сессии будут различаться по самим потокам или событиям, дескрипторам сессий GRASP и базовыми транспортными сокетами (индивидуальными — unicast).

stop_listen_negotiate()

Эту функцию ASA вызывает для остановки работы в качестве ответчика (слушающего) для данной задачи GRASP.
  • Входные параметры:
    asa_handle (целое число без знака);
    objective (structure).
  • Возвращаемое значение:
    errorcode (целое число без знака).
  • Указывает GRASP прекратить прослушивание запросов на согласование для данной задачи, т. е. отменить listen_negotiate().
  • Асинхронные механизмы

    Потоковая реализация

    Должна вызваться из другого потока, нежели listen_negotiate().

    Реализация цикла событий

    Нет специальных условий.

negotiate_step()

Эту функцию ASA применяет в сеансе согласования для выполнения следующего шага.
  • Входные параметры:
    asa_handle (целое число без знака);
    session_handle (structure);
    objective (structure);
    timeout (целое число без знака), как описано в параграфе 2.3.2.3.
  • Возвращаемые значения:
    Как для вызова request_negotiate().
  • Выполняет следующий шаг согласования с партнёром. Параметр objective содержит следующее значение, предлагаемое ASA на этом шаге, а также должен включать последнее значение loop_count, полученное при вызове request_negotiate() или negotiate_step().
  • Асинхронные механизмы

    Потоковая реализация

    Обычно функция вызывается в одном потоке с предшествующим request_negotiate или listen_negotiate с тем же значением session_handle.

    Реализация цикла событий

    Должно использоваться значение session_handle, возвращённое предыдущим вызовом request_negotiate() или listen_negotiate().

negotiate_wait()

Эту функцию вызывает любой из участвующих в согласовании агентов ASA для задержки следующего шага.
  • Входные параметры:
    asa_handle (целое число без знака);
    session_handle (structure);
    timeout (целое число без знака).
  • Возвращаемое значение:
    errorcode (целое число без знака).
  • Запрос к удалённому партнёру задержать сеанс согласования на timeout миллисекунд сверх исходного времени ожидания. Эта функция просто вызывает отправку сообщения GRASP Confirm Waiting [RFC8990].
  • Асинхронные механизмы

    Потоковая реализация

    Вызывается в одном потоке с предшествующим request_negotiate() или listen_negotiate() с тем же session_handle.

    Реализация цикла событий

    Должно использоваться значение session_handle, полученное из предыдущего вызова request_negotiate() или listen_negotiate().

end_negotiate()

Эту функцию использует любой из участвующих в согласовании агентов ASA для завершения сессии.
  • Входные параметры:
    asa_handle (целое число без знака);
    session_handle (structure);
    result (Boolean);
    reason (UTF-8 string);
  • Возвращаемое значение:
    errorcode (целое число без знака).
  • Завершение сеанса согласования:
    result = True при успешном согласовании, False при отказе (отклонении);
    reason = строка, указывающая причину отклонения (может быть пустой, при успехе игнорируется).
  • Асинхронные механизмы

    Потоковая реализация

    Вызывается в одном потоке с предшествующим request_negotiate() или listen_negotiate() с тем же session_handle.

    Реализация цикла событий

    Должно использоваться значение session_handle, полученное из предыдущего вызова request_negotiate() или listen_negotiate().

2.3.6. Синхронизация и лавинная рассылка

synchronize()

Эту функцию агент ASA использует для запуска синхронизацию задачи GRASP, будучи ответчиком (клиентом).
  • Входные параметры:
    asa_handle (целое число без знака);
    objective (structure);
    peer (asa_locator);
    timeout (целое число без знака).
  • Возвращаемые значения:
    errorcode (целое число без знака);
    result (structure) (не определена до успешного завершения).
  • Этот вызов запрашивает синхронизированное значение данной задачи (objective).
  • Если параметр peer пуст и задача уже доступна в локальном кэше, рассылаемая лавинно задача возвращается сразу в параметре result. Значение timeout в этом случе игнорируется.
  • Если параметр peer непуст или задача недоступна в локальном кэше, выполняется синхронизация с найденным агентом ASA. При успешном выполнении найденная задача возвращается в параметре result.
  • Параметр peer содержит значение asa_locator, возвращённое функцией discover(). При пустом peer сначала автоматически выполняется обнаружение GRASP для поиска подходящего партнёра (любого узла, поддерживающего данную задачу).
  • Параметр timeout описан в параграфе 2.3.2.3.
  • Этот вызов следует повторяит всякий раз, когда требуется последнее значение.
  • Асинхронные механизмы

    Потоковая реализация

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

    Реализация цикла событий

    Используется дополнительный входной/выходной параметр session_handle как для request_negotiate(). Значение errorcode = 2 (noReply) говорит, что отклик ещё не получен. При последующих вызовах должен указываться параметр session_handle.
  • При отказе перед повтором следует использовать экспоненциально увеличиваемый интервал (раздел 3).

listen_synchronize()

Эту функцию агент ASA использует для начала работы в качестве ответчика (слушающего) при синхронизации для данной задачи GRASP.
  • Входные параметры:
    asa_handle (целое число без знака);
    objective (structure).
  • Возвращаемое значение:
    errorcode (целое число без знака).
  • Эта функция указывает GRASP прослушивать запросы синхронизации для данной задачи и отвечать значением, заданным в параметре objective, а также включает отклики для задачи, как указано в описании register_objective() (параграф 2.3.3).
  • Этот вызов является неблокирующим и может повторяться при изменении значения.

stop_listen_synchronize()

Эту функцию агент ASA использует для прекращения работы в качестве ответчика (слушающего) при синхронизации для данной задачи GRASP.
  • Входные параметры:
    asa_handle (целое число без знака);
    objective (structure).
  • Возвращаемое значение:
    errorcode (целое число без знака).
  • Эта функция указывает GRASP прекратить прослушивание запросов синхронизации для данной задачи objective, т. е. отменить предыдущий вызов listen_synchronize().

flood()

Эту функцию агент ASA применяет для лавинной рассылки одной или нескольких задач GRASP через автономную сеть. Отметим, что каждый узел GRASP кэширует все лавинно рассылаемые задачи, которые он получает, пока сроки их действия не завершится. Кэшированные задачи указываются с их источником и сроком действия, поэтому одновременно может кэшироваться несколько копий одной задачи. Подробности приведены в параграфе 2.8.11 «Сообщение Flood Synchronization» [RFC8990].
  • Входные параметры:
    asa_handle (целое число без знака);
    ttl (целое число без знака);
    tagged_objective_list (structure).
  • Возвращаемое значение:
    errorcode (целое число без знака).
  • Этот вызов указывает GRASP выполнить лавинную рассылку указанных целей для синхронизации, из значений и связанных локаторов всем узлам GRASP.
  • Параметр ttl указывает срок действия рассылаемых лавинно данных в миллисекундах (0 указывает неограниченное действие).
  • Параметр tagged_objective_list содержит 1 или несколько пар tagged_objective. Параметр locator для каждой задачи обычно пуст, но может быть действительным asa_locator. Инфраструктурные ASA, которым нужно лавинно разослать триблет {address, protocol, port} с задачей, создают для этого объект asa_locator. Если в качестве IP-адреса в таком локаторе применяется незаданный адрес (::), он заменяется адресом link-local передающего узла в каждой копии группового лавинного сообщения с принудительно заданным счётчиком цикла 1. Это предназначено для задач, ограниченных локальным каналом.
  • Функция проверяет, что агент ASA зарегистрировал каждую задачу.
  • Вызов может повторяться при изменении любого значения.

get_flood()

Эту функцию агент ASA применяет для получения текущего значения лавинно разосланной задачи GRASP.
  • Входные параметры:
    asa_handle (целое число без знака);
    objective (structure).
  • Возвращаемые значения:
    errorcode (целое число без знака);
    tagged_objective_list (structure) (не определена до успешного завершения).
  • Этот вызов указывает GRASP возвратить данную задачу для синхронизации, если она разослана лавинно и срок её действия не истёк.
  • Параметр tagged_objective_list содержит список пар tagged_objective, каждая из которых является копией разосланной лавинно задачи и соответствующего локатора. Такие образом, если одну задачу лавинно рассылали несколько ASA, получатель может различить копии.
  • Этот вызов предназначен для смежных ASA. В простом случае ASA может просто вызвать synchronize() для получения действительной лавинно разосланной задачи.

expire_flood()

Эту функцию агент ASA может применять для завершения срока действия конкретных записей в локальном кэше лавинной рассылки GRASP.
  • Входные параметры:
    asa_handle (целое число без знака);
    tagged_objective (structure).
  • Возвращаемое значение:
    errorcode (целое число без знака).
  • Вызов можно применять лишь после предшествующего get_flood() агентом ASA способным понять, что рассылаемое лавинно значение устарело или недействительно. Функцию следует применять осторожно.
  • Параметр tagged_objective указывает устаревший элемент.

2.3.7. Функция для недействительных сообщений

send_invalid()

Эту функцию может использовать любой агент ASA для остановки продолжающейся сессии GRASP.
  • Входные параметры:
    asa_handle (целое число без знака);
    session_handle (structure);
    info (байты).
  • Возвращаемое значение:
    errorcode (целое число без знака).
  • Функция передаёт сообщение GRASP Invalid (M_INVALID), как описано в [RFC8990]. Её не следует применять, если достаточно будет вызова end_negotiate(). Отметим, что сообщение может использоваться в ответ на любое индивидуальное сообщение GRASP, которое получатель не может корректно интерпретировать. В большинстве случаев сообщение будет создаваться внутри реализации GRASP. Параметр info может содержать необязательные диагностические сведения от ASA. Это могут быть необработанные байты из непонятного сообщения.

3. Вопросы безопасности

Вопросы безопасности для протокола GRASP рассмотрены в [RFC8990], включая атаки с отказом в обслуживании, хотя для ACP они не считаются сильно опасными. В различных местах протокола GRASP рекомендуется применять экспоненциальное повышение интервалов (backoff). Агенту ASA, применяющему API, следует использовать экспоненциальное увеличение интервала после неудачных вызовов discover(), req_negotiate(), synchronize(). Масштаб интервалов для таких операций зависит от семантики соответствующей задачи GRASP. Вызов flood() не следует повторять через более короткие интервалы, чем это будет полезно (в зависимости от семантики соответствующей задачи GRASP). Эти предостережения призваны помочь при обнаружении атак на службы.

В качестве общей предосторожности все ASA, способные обрабатывать параллельно несколько запросов согласования или регистрации, могут защититься от атак на службы, ограничивая число обрабатываемых одновременно запросов и отбрасывая без уведомления избыточные запросы. Для ядра GRASP может быть полезно ограничивать число задач, регистрируемых данным агентом ASA, общее числе регистрируемых всеми ASA задач и общее число одновременных сессий для защиты ресурсов системы. При высокой автономной активности, например, во время восстановления после обширных повреждений агенты ASA могут сталкиваться с частыми отказами сессий GRASP. Рекомендации по обеспечению устойчивости ASA приведены в [ASA-GUIDE].

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

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

Параметр asa_handle применяется в API в качестве первой линии защиты от вредоносных программ, пытающихся имитировать корректно зарегистрированный агент ASA. Параметр session_handle служит в API первой линией защиты от враждебных процессов, пытающихся перехватить сессии GRASP. Оба эти дескриптора будут, скорей всего, создаваться с использованием 32-битового псевдослучайного GRASP Session ID. По своему устройству GRASP предотвращает риск конфликтов Session ID (см. параграф 2.7 «Идентификатор сессии (Session ID)» в [RFC8990]). Однако остаётся вероятность угадывания злоумышленником значения Session ID, session_handle или asa_handle, но это будет полезно лишь для атакующего, уже проникшего в ACP, которому доступны более простые формы атак, нежели перехват сессий GRASP.

4. Взаимодействие с IANA

Этот документ не требует действий IANA.

5. Литература

5.1. Нормативные документы

[RFC8610] Birkholz, H., Vigano, C., and C. Bormann, «Concise Data Definition Language (CDDL): A Notational Convention to Express Concise Binary Object Representation (CBOR) and JSON Data Structures», RFC 8610, DOI 10.17487/RFC8610, June 2019, <https://www.rfc-editor.org/info/rfc8610>.

[RFC8949] Bormann, C. and P. Hoffman, «Concise Binary Object Representation (CBOR)», STD 94, RFC 8949, DOI 10.17487/RFC8949, December 2020, <https://www.rfc-editor.org/info/rfc8949>.

[RFC8990] Bormann, C., Carpenter, B., Ed., and B. Liu, Ed., «GeneRic Autonomic Signaling Protocol (GRASP)», RFC 8990, DOI 10.17487/RFC8990, May 2021, <https://www.rfc-editor.org/info/rfc8990>.

5.2. Дополнительная литература

[ANIMA-COORD] Ciavaglia, L. and P. Peloso, «Autonomic Functions Coordination», Work in Progress, Internet-Draft, draft-ciavaglia-anima-coordination-01, 21 March 2016, <https://tools.ietf.org/html/draft-ciavaglia-anima-coordination-01>.

[ASA-GUIDE] Carpenter, B., Ciavaglia, L., Jiang, S., and P. Peloso, «Guidelines for Autonomic Service Agents», Work in Progress4, Internet-Draft, draft-ietf-anima-asa-guidelines-00, 14 November 2020, <https://tools.ietf.org/html/draft-ietf-anima-asa-guidelines-00>.

[GRASP-DISTRIB] Liu, B., Xiao, X., Hecker, A., Jiang, S., Despotovic, Z., and B. Carpenter, «Information Distribution over GRASP», Work in Progress, Internet-Draft, draft-ietf-anima-grasp-distribution-02, 8 March 2021, <https://tools.ietf.org/html/draft-ietf-anima-grasp-distribution-02>.

[libcbor] Kalvoda, P., «libcbor — libcbor 0.8.0 documentation», April 2021, <https://libcbor.readthedocs.io/>.

[RFC8993] Behringer, M., Ed., Carpenter, B., Eckert, T., Ciavaglia, L., and J. Nobre, «A Reference Model for Autonomic Networking», RFC 8993, DOI 10.17487/RFC8993, May 2021, <https://www.rfc-editor.org/info/rfc8993>.

[RFC8994] Eckert, T., Ed., Behringer, M., Ed., and S. Bjarnason, «ACK Autonomic Control Plane (ACP)», RFC 8994, DOI 10.17487/RFC8994, May 2021, <https://www.rfc-editor.org/info/rfc8994>.

[RFC8995] Pritikin, M., Richardson, M., Eckert, T., Behringer, M., and K. Watsen, «Bootstrapping Remote Secure Key Infrastructure (BRSKI)», RFC 8995, DOI 10.17487/RFC8995, May 2021, <https://www.rfc-editor.org/info/rfc8995>.

Приложение A. Коды ошибок

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

Коды ошибок, которые могут возвращать лишь одна или две функции, помечены именами этих функций в строке описания. Код noSecurity может возвращать большинство вызовов, если GRASP работает без защиты (например, нет защитной подложки, такой как ACP), за исключением специфического режима DULL, описанного в параграфе 2.5.2 «DULL GRASP» [RFC8990].

Таблица . Коды ошибок.

 

Имя

Код

Описание

ok

0

Все хорошо

declined

1

Отклонено (req_negotiate, negotiate_step)

noReply

2

Нет отклика (indicates waiting state in event loop calls)

unspec

3

Неуказанная ошибка

ASAfull

4

Реестр ASA заполнен (register_asa)

dupASA

5

Дублирование имени ASA (register_asa)

noASA

6

Агент ASA не зарегистрирован

notYourASA

7

Агент ASA зарегистрирован другим (deregister_asa)

notBoth

8

Задача не может поддерживать согласование и синхронизацию (register_obj)

notDry

9

Пробный прогон разрешён лишь при синхронизации (register_obj)

notOverlap

10

Реализация не поддерживает наложение (register_obj)

objFull

11

Реестр задач заполнен (register_obj)

objReg

12

Задача уже зарегистрирована (register_obj)

notYourObj

13

Задача не зарегистрирована этим ASA

notObj

14

Задача не найдена

notNeg

15

Задача не согласуется (req_negotiate, listen_negotiate)

noSecurity

16

Нет защиты

noDiscReply

17

Нет отклика при обнаружении (req_negotiate)

sockErrNegRq

18

Ошибка сокета, передающего запрос согласования (req_negotiate)

noSession

19

Нет сессии

noSocket

20

Нет сокета

loopExhausted

21

Завершился счётчик цикла (negotiate_step)

sockErrNegStep

22

Ошибка сокета, передающего этап согласования (negotiate_step)

noPeer

23

Нет партнёра для согласования (req_negotiate, negotiate_step)

CBORfail

24

Отказ при декодировании CBOR (req_negotiate, negotiate_step, synchronize)

invalidNeg

25

Непригодное сообщение Negotiate (req_negotiate, negotiate_step)

invalidEnd

26

Непригодное сообщение о завершении (req_negotiate, negotiate_step)

noNegReply

27

Нет отклика на этап согласования (req_negotiate, negotiate_step)

noValidStep

28

Нет пригодного отклика на этап согласования (req_negotiate, negotiate_step)

sockErrWait

29

Ошибка сокета, передающего сообщение об ожидании (negotiate_wait)

sockErrEnd

30

Ошибка сокета, передающего сообщение о завершении (end_negotiate, send_invalid)

IDclash

31

Конфликт Session ID во входящем запросе (listen_negotiate)

notSynch

32

Нет задачи для синхронизации (synchronize, get_flood)

notFloodDisc

33

Нет лавинной рассылки и отклика на обнаружение (synchronize)

sockErrSynRq

34

Ошибка сокета, передающего запрос синхронизации (synchronize)

noListener

35

Нет прослушивающей стороны для синхронизации (synchronize)

noSynchReply

36

Нет ответа на запрос синхронизации (synchronize)

noValidSynch

37

Нет пригодного ответа на запрос синхронизации (synchronize)

invalidLoc

38

Недействительный локатор (flood)

 

Благодарности

Существенные предложения внесли Ignas Bagdonas, Carsten Bormann, Laurent Ciavaglia, Roman Danyliw, Toerless Eckert, Benjamin Kaduk, Erik Kline, Murray Kucherawy, Paul Kyzivat, Guangpeng Li, Michael Richardson, Joseph Salowey, Éric Vyncke, Magnus Westerlund, Rob Wilton и другие члены рабочей группы IESG ANIMA.

Адреса авторов

Brian E. Carpenter
School of Computer Science
University of Auckland
PB 92019
Auckland 1142
New Zealand
Email: brian.e.carpenter@gmail.com
 
Bing Liu (editor)
Huawei Technologies
Q14, Huawei Campus
No.156 Beiqing Road
Hai-Dian District, Beijing
100095
China
Email: leo.liubing@huawei.com
 
Wendong Wang
BUPT University
Beijing University of Posts & Telecom.
No.10 Xitucheng Road
Hai-Dian District, Beijing 100876
China
Email: wdwang@bupt.edu.cn
 
Xiangyang Gong
BUPT University
Beijing University of Posts & Telecom.
No.10 Xitucheng Road
Hai-Dian District, Beijing 100876
China
Email: xygong@bupt.edu.cn

Перевод на русский язык

nmalykh@protokols.ru


1Internet Engineering Task Force — комиссия по решению инженерных задач Internet.

2Internet Engineering Steering Group — комиссия по инженерным разработкам Internet.

3Interprocess communication — взаимодействия между процессами.

4Опубликовано в RFC 9222. Прим. перев.

Рубрика: RFC | Оставить комментарий

RFC 8995 Bootstrapping Remote Secure Key Infrastructure (BRSKI)

Internet Engineering Task Force (IETF)                       M. Pritikin
Request for Comments: 8995                                         Cisco
Category: Standards Track                                  M. Richardson
ISSN: 2070-1721                                 Sandelman Software Works
                                                               T. Eckert
                                                           Futurewei USA
                                                            M. Behringer
                                                                        
                                                               K. Watsen
                                                         Watsen Networks
                                                                May 2021

Bootstrapping Remote Secure Key Infrastructure (BRSKI)

Инфраструктура ключей защищённой начальной загрузки

PDF

Аннотация

Этот документ определяет автоматизированную начальную загрузку автономной плоскости управления (Autonomic Control Plane или ACP), для чего запускается защищённая инфраструктура ключей (Secure Key Infrastructure). Это выполняется с использованием установленных изготовителем сертификатов X.509 в сочетании со службой предоставления полномочий (authorizing service) изготовителя через сеть (online) или автономно (offline). Это называется протоколом инфраструктуры защищённых удалённых ключей для начальной загрузки (Bootstrapping Remote Secure Key Infrastructure или BRSKI). Начальная загрузка нового устройства может происходить при использовании маршрутизируемого адреса и облачного сервиса, при наличии лишь локальной связности (link-local) или в изолированной (ограниченной) сети. Поддерживаются модели развёртывания с менее строгими требованиями безопасности. Начальная загрузка завершается, когда криптографическое отождествление (идентификатор) новой инфраструктуры ключей успешно на устройстве. Организованное защищённое соединение можно также использовать для развёртывания локально выпущенного сертификата на устройстве.

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

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

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

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

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

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

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

1. Введение

Протокол BRSKI предоставляет решение для защищённой автоматической (zero-touch) начальной загрузки новых (ненастроенных) устройств, называемых заявителями (pledge). У заявителей имеется исходный идентификатор устройства (Initial Device Identifier или IDevID), установленный на заводе.

BRSKI произносится как brewski — это разговорное название пива в Канаде и некоторых частях Среднего запада США [brewski].

В этом документе представлены в первую очередбь потребности провайдеров (ISP) и автономной плоскости управления (Autonomic Control Plane или ACP) ориентированной на предприятия интегрированной модели автономных сетей (Autonomic Networking Integrated Model and Approach или ANIMA) [RFC8994]. Этот процесс начальной загрузки соответствует требованиям обеспечения по умолчанию защиты всех операций из параграфа 3.3 в [RFC7575]. Другим пользователям протокола BRSKI потребуется предоставить свои заявления о применимости, включающие свои соображения безопасности и приватности для развёртывания. В разделе 9 подробно описана применимость такого использования ACP.

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

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

  1. Регистратор проверяет подлинность заявителя — что это? что его отождествляет?

  2. Регистратор проверяет полномочия заявителя — это моё? нужно ли мне это? каковы шансы, что это скомпрометировано?

  3. Заявитель проверяет подлинность регистратора — что отождествляет регистратор?

  4. Заявитель проверяет полномочия регистратора — нужно ли присоединяться к этой сети?

Этот документ детализирует протоколы и сообщения для ответов на поставленные выше вопросы. Используется соединение TLS и сертификат заявителя в форме PKIX (X.509v3, IEEE 802.1AR IDevID [IDevID]) для ответа на вопросы 1 и 2. Применяется новый артефакт «ваучер (voucher), который регистратор получает от уполномоченного изготовителем агентства подписей (Manufacturer Authorized Signing Authority или MASA) и передаёт заявителю для ответа на вопросы 3 и 4.

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

Детали синтаксиса ваучеров подробно описаны в [RFC8366]. Этот документ подробно рассматривает механизмы автоматизированного протокола получения ваучеров, включая определение сообщения voucher-request, задающего незначительное расширение формата ваучеров (3. Артефакт запроса ваучера), заданного в [RFC8366].

BRSKI делает хранящийся у заявителя корневой сертификат X.509 достаточным для проверки отождествления регистратора. В процессе организуется соединение TLS, которое можно напрямую использовать для регистрации через защищённый транспорт (Enrollment over Secure Transport или EST). Фактически BRSKI обеспечивает автоматизированный механизм для распределения сертификатовр при начальной загрузке (Bootstrap Distribution of CA Certificates), описанный в параграфе 4.1.1 [RFC7030], где заявитель «должен […] привлекать человека для проверки полномочий сертификата CA с использованием внешних (out-of-band) данных». С помощью BRSKI заявитель может автоматизировать процесс применения ваучеров. Интеграция с полным механизмом EST необязательна и тривиальна.

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

1.1. Прежние подходы к начальной загрузке

Буквально «подтянуть себя за шнурки» (pull yourself up by the bootstraps) нереально. Точно так же невозможно создать защищённую инфраструктуру ключей без привлечения внешних сил. Сегодня общепризнано, что исходные соединения между узлами не защищены, пока не завершено распространение ключей или не подготовлен зависящий от домена ключевой материал (зачастую это заранее распространённые ключи, включая SIM3-карты). Имеющиеся автоматизированные механизмы, известные как незащищённое доверие при первом использовании (Trust on First Use или TOFU) [RFC7435], «воскрешение утёнка» (resurrecting duckling) [Stajano99theresurrecting] или предварительная подготовка (pre-staging).

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

  • Использование базы неявных привязок доверияе (Trust Anchor или TA) [RFC7030] для аутентификации связанной с владельцем службы (неавтономное решение, поскольку требует защищённого распространение URL).

  • Привлечение пользователя (человека) для проверки полномочий сертификата CA с использованием внешних (out-of-band) данных (неавтономное решение, поскольку требует участия человека),

  • Использование настроенной базы явных TA (неавтономное решение, поскольку распространение базы явных TA не является автономным).

  • Использование метода взаимной аутентификации TLS без сертификатов (неавтономное решение, поскольку распространение симметричных ключей не является автономным).

Эти методы не соответствуют требованиям автоматизации (zero-touch).

Существуют технологии «звонка домой» (call home), когда заявитель сначала организует соединение с общеизвестной службой производителя, используя базовую модель аутентификации «клиент-сервер». После взаимной проверки подлинности заявителю передаются соответствующие свидетельства для аутентификации целевого домена. С этим связано несколько проблем и ограничений:

  • заявителю требуется соединение со службой производителя в реальном масштабе времени;

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

  • производитель отвечает за принятие решений о предоставлении полномочий (проблема ответственности).

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

1.2. Терминология

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

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

ANI

Автономная сетевая инфраструктура (Autonomic Networking Infrastructure), определённая в [RFC8993]. В разделе 9 указаны конкретные требования к зачвителям, посредникам и регистраторам, являющимся частью ANI.

Circuit Proxy

Реализация Join Proxy с поддержкой состояний. Это предполагаемый тип посредников.

drop-ship

Физическое распределение оборудования с принятыми по умолчанию заводскими настройками (factory default) в конечный пункт назначения. В автоматизированных (zero-touch) сценариях при прямой поставке не применяется предварительная настройка или подготовка.

Domain — домен

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

Domain CA — удостоверяющий центр домена

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

domainID

IDentity с уникальным значением, основанным на сертификате CA для регистратора. Расчёт значений идентификаторов описан в параграфе 5.8.2. Расчёт domainID.

Enrollment — зачисление

Процесс, в котором устройство представляет в сеть ключевой материал и получает связанное с сетью отождествление. Например, отправка запроса сертификата агентству CA и получение сертификата в ответ.

IDevID

Сертификат X.509 исходного идентификатора устройства (Initial Device Identifier), устанавливаемый производителем в новом оборудовании. Термин заимствован из 802.1AR [IDevID].

imprint — принятие отпечатка (впечатывание)

Процесс, где устройство получает криптографический ключевой материал для отождествления и доверия к будущим взаимодействиям с сетью. Этот термин взят из работы Конрада Лоренца (Konrad Lorenz) по биологии утят: «в критический период утёнок будет предполагать, что все, похожее на утку-мать, фактически является его матерью». Эквивалентом для устройства является получение отпечатка (fingerprint) сертификата корневого удостоверяющего центра сети. Устройство, принявшее отпечаток от злоумышленника, постигнет судьба, похожая на судьбу утёнка, принявшего волка за мать. Защищённое впечатывание является основным вопросом этого документа [imprinting]. Аналогия с работой Лоренца впервые была отмечена в [Stajano99theresurrecting].

IPIP Proxy

Вариант прокси без учёта состояния.

Join Proxy — посредник присоединения

Элемент домена, помогающий заявителю присоединиться к домену. Join Proxy упрощает взаимодействие для устройств, обнаруживающих себя в среде, где они не имеют связности, пока не будут проверены в качестве членов домена. Для простоты в этом документе Join Proxy иногда называется просто посредником или прокси. Заявитель не знает, что он взаимодействует с посредником, а не напрямую с регистратором.

Join Registrar (and Coordinator) — регистратор (и координатор) присоединения

Представитель домена, настроенный (возможно, автоматически) для решения вопроса о присоединении к домену нового устройства. Администратор домена взаимодействует с регистратором (и координатором) присоединения для управления этим процессом. Обычно Join Registrar находится «внутри» домена. Для простоты в этом документе используется просто термин «регистратор». В [RFC8993] применяется термин «агент автономной службы регистратора присоединения» (Autonomic Service Agent или ASA). Применяется также сокращение JRC.

LDevID

Сертификат X.509 локального идентификатора устройства (Local Device Identifier), устанавливаемый владельцем оборудования. Термин заимствован из 802.1AR [IDevID].

Manufacturer — производитель

Производителем в этом документе называется организация, создавшая устройство. Обычно это исходный производитель оборудования (original equipment manufacturer или OEM), но в более сложных ситуациях может обозначать реселлера (value added retailer или VAR) и даже системного интегратора. Целью BRSKI в общем случае является исключение небольших различий между каналами продажи. Это делается для того, чтобы обеспечить возможность поставки всем заказчикам одинаковых устройств с унифицированной загрузкой микрокода (firmware). Это сокращает расходы производителя, а также номенклатуру продукции с «полевой» поддержкой и повышает шансы того, что микрокод будет актуальным (up to date).

MASA Audit-Log — журнал аудита MASA

Анонимизированный список прежних владельцев, поддерживаемый агентом MASA по устройствам (заявителям), как описано в параграфе 5.8.1. Отклик MASA Audit-Log.

MASA Service — служба MASA

Сторонняя служба MASA в общедоступной сети Internet. Агент MASA подписывает ваучеры, а также поддерживает репозиторий сведений журнала аудита событий начальной загрузки с защитой приватности. Служба не отслеживает владение.

nonced

Ваучер (или запрос), содержащий одноразовое значение nonce (обычный случай).

nonceless

Ваучер (или запрос), не содержащий nonce или основанный на точности часов для проверки срока действия.

offline

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

Ownership Tracker — трекер владения

Служба слежения за владением в общедоступной сети Internet. Ownership Tracker использует бизнес-процессы для точного отслеживания владения всеми устройствами доменами, которые приобрели устройства. Эта служба не обязательна, но позволяет производителям предоставлять дополнительные услуги в случаях, когда их каналы продаж и распространения позволяют точно отслеживать владение. Данные отслеживания владения указываются в ваучерах, как описано в [RFC8366].

Pledge — заявитель

Предполагаемое (ненастроенное) устройства, имеющее заводское отождествление.

(Public) Key Infrastructure — инфраструктура (открытых) ключей

Набор систем и процессов, которые поддерживают работу системы открытых ключей. Регистратор выступает агентством регистрации (Registration Authority), см. [RFC5280] и раздел 7 в [RFC5272].

TOFU

Доверие при первом использовании (Trust on First Use), применяемое аналогично описанному в [RFC7435]. Заявитель не принимает рещений о защите, а просто доверяет первому регистратору, с которым он связался. Это также называется моделью «воскресающего утёнка» (resurrecting duckling).

Voucher — ваучер

Подписанный артефакт от агента MASA, указывающий криптографическое отождествление регистратора, которому заявителю следует доверять. Имеются разные типы ваучеров в зависимости от организации доверия. Разные типы ваучеров определены в [RFC8366].

1.3. Область действия

1.3.1. Среда поддержки

BRSKI может поддерживать большие платформы маршрутизации с мультимегабитными соединениями, установленные в центрах обработки данных (ЦОД) с контролируемым доступом. Кроме того, оно способно работать с тысячами устройств, размещённых в небезопасных средах, таких как предоставляемые провайдерами (ISP) оконечные устройства клиентов (Customer Premises Equipment или CPE), отгружаемые напрямую конечным пользователям. Явно поддерживаются ситуации, когда оборудование поставляется с распределенного склада напрямую в целевое место по запросу владельца домена. Такой запас устройств (SKU) может поддерживаться для множества возможных владельцев доменов, которые заранее не знают, какое из устройств будет поставлено в конкретное место.

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

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

1.3.2. Среды с ограничениями

Возникают вопросы о пригодности этого решения в общем случае для сетей «Интернета вещей» (Internet of Things или IoT). Это зависит от возможностей рассматриваемых устройств. Для описания границ лучше всего подходит терминология [RFC7228].

Описанное здесь решение нацелено, прежде всего, на устройства без ограничений (Class 2+ [RFC7228]), работающие в сетях без ограничений, и в целом не предназначено для устройств с ограничениями, работающих в сетях с ограничениями, таких как сети 802.15.4 со слабым питанием и потерями (Low-Power and Lossy Network или LLN).

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

Протокол впечатывания (imprint), описанный здесь, может применяться устройствами без ограничений по энергопотреблению, присоединяемых к сети без ограничений (например, «умные» лампочки обычно подключаются к электросети и используют беспроводную технологию 802.11). Протокол может также применяться устройствами без ограничений в сетях, где нет ограничений по питанию, но имеются иные ограничения (например, сети 802.15.4). Содержимое сертификата и процесс, с помощью которого решаются 4 отмеченных выше вопроса, применимы к устройствам с ограничениями. Это просто протокол передачи отпечатков по кабелям (on-the-wire imprint), который может быть неприемлемым.

1.3.3. Управление доступом в сеть

В этом документе предполагается, что контроль доступа в сеть уже выполнен, не требуется или интегрирован посредником и регистратором так, что самому устройству не нужно заботиться о деталях. Хотя применение X.509 IDevID совместимо с IEEE 802.1AR [IDevID] и может быть согласовано с методами контроля доступа в сеть 802.1X, здесь это используется для проверки подлинности заявителя, а не для контроля доступа в сеть. Сочетание этого протокола с контролем доступа в сеть, возможно на основе расширяемого протокола аутентификации (Extensible Authentication Protocol или EAP) [RFC3748] выходит за рамки этого документа.

1.3.4. Bootstrapping — это не Booting

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

1.4. Применение новой инфраструктуры ключей и следующие шаги

В результате применения описанного здесь протокола изначально загружаемые (bootstrap) устройства имеют общую привязку доверия (CA домена). Сертификаты конечных элементов (end-entity или EE) может выпускать CA домена. Это позволяет реализовать в домене защищённые функции, например,

  • управление устройствами;
  • аутентификация маршрутизации;
  • обнаружение служб.

Основным ожидаемым преимуществом является возможность использовать свидетельства, предоставляемые протоколом для защиты автономной плоскости управления (Autonomic Control Plane или ACP) [RFC8994].

1.5. Требования к устройствам автономной сетевой инфраструктуры

Протокол BRSKI может применяться во множестве сред. Некоторые из описанных в документе опций выходят за рамки ANI. В этом параграфе рассмотрены базовые требования к устройствам ANI.

Для устройств, намеревающихся стать частью инфраструктуры ANI [RFC8993], включающей ACP [RFC8994], протокол BRSKI должен быть реализован. Заявитель должен выполнять обнаружение посредников, как описано в параграфе 4.1, с использованием анонсов DULL M_FLOOD (Discovery Unsolicited Link-Local) [RFC8990] базового протокола автономной сигнализации (GeneRic Autonomic Signaling Protocol или GRASP).

После успешной проверки артефакта ваучера должна возвращаться телеметрия состояния (5.7. Телеметрия статуса заявителя BRSKI). Заявитель ANIMA ANI должен реализовать расширения автоматизации EST, описанные в параграфе 5.9. Интеграция EST с начальной загрузкой, дополняющие EST [RFC7030] для лучшей поддержки автоматизированных устройств без конечного пользователя. Агент ANI Join Registrar ASA должен поддерживать все операции BRSKI и указанные выше операции EST. Всем устройствам ANI следует поддерживать функции посредника BRSKI с использованием прокси-устройств через ACP (см. 4.3. Обнаружение посредника и связь с регистратором).

2. Обзор архитектуры

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

                                           +------------------------+
   +--------------Поставка-----------------| Служба производителя   |
   |                                       +------------------------+
   |                                       | M anufacturer|         |
   |                                       | A uthorized  |Отслежив.|
   |                                       | S igning     |владения |
   |                                       | A uthority   |         |
   |                                       +--------------+---------+
   |                                                      ^  BRSKI-
   V                                                      |   MASA
+-------+     ............................................|...
|       |     .                                           |  .
|       |     .  +------------+       +-----------+       |  .
|       |     .  | Посредник  |       |Регистратор<-------+  .
|IDevID |     .  |присоединен.|       |  домена   |          .
|заявит.<-------->............<-------> (PKI RA)  |          .
|       |        |        BRSKI-EST   |           |          .
|       |     .  |            |       +-----+-----+          .
|       |     .  +------------+             |напр., RFC 7030 .
|       |     .           +-----------------+----------+     .
|       |     .           | Инфраструктура ключей      |     .
|       |     .           | (например, PKI CA)         |     .
+-------+     .           +----------------------------+     .
              ................................................
                            Компоненты «домена»

Рисунок 1. Обзор архитектуры.


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

Домен — это управляемая сетевая инфраструктура с инфраструктурой ключей, к которой присоединяется заявитель. Домен обеспечивает начальное подключение устройства, достаточное для начальной загрузки через прокси. Регистратор домена аутентифицирует заявителя, принимает решения о предоставлении полномочий и распространяет ваучеры, полученные от службы производителя, а также может выступать как PKI CA.

2.1. Поведение заявителя

               ------------
              /  Заводские \
              \  настройки /
               -----+------
                    |
             +------v-------+
+------------> (1) Discover |
|            +------+-------+
|                   |
|            +------v-------+
^------------+ (2) Identify |
| Отвергнут  +------+-------+
|                   |
|            +------v-------+
|            | (3) Request  |
|            |     Join     |
|            +------+-------+
|                   |
|            +------v-------+
^------------+ (4) Imprint  |
| «Плохой»   +------+-------+
| отклик MASA       |  Передача Voucher Status Telemetry
|            +------v-------+
^------------+ (5) Enroll   |<---+ (код HTTP, не связанный с ошибкой)
| Отказ в    +------+-------+\___/ (например, 202 "Retry-After")
| зачислении        |
|             /-----v------\
^------------+   Зачислен  |
 Сброс к      \------------/
 заводским настройкам

Рисунок 2. Состояния заявителя.


Заявитель выполняет шаги, описанные ниже на высоком уровне.

  1. Обнаружение (Discover) канала связи с маршрутизатором.

  2. Отождествление (Identify) самого себя, выполняемое представлением отождествления X.509 IDevID обнаруженному регистратору (через прокси) в согласовании TLS. Свидетельства регистратора в этот момент принимаются лишь временно.

  3. Запрос на присоединение (Request join) к обнаруженному регистратору. Включается уникальное одноразовое значение (nonce), гарантирующее связывание любых откликов с конкретной попыткой начальной загрузки.

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

  5. Зачисление (Enroll). После впечатывания между регистратором и заявителем будет аутентифицированное соединение TLS (HTTPS). Можно использовать EST [RFC7030] для получения сертификата домена от регистратора.

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

Эта спецификация подробно описывает интеграцию с зачислением EST, чтобы заявители могли получать локально выпущенные сертификаты, хотя в будущем возможна интеграция с любой службой представления состояний (Representational State Transfer или REST) [REST].

2.2. Защищённое впечатывание с использованием ваучеров

Ваучер — это криптографически защищённый артефакт (использующий цифровую подпись) для заявителя, позволяющий автоматическое (zero-touch) впечатывание его в домен регистратора. Формат и криптографические механизмы для ваучеров подробно описаны в [RFC8366].

Ваучеры обеспечивают гибкий механизм защиты впечатывания на основе проверки ваучера. На нижних уровнях защиты агент MASA может без разбора выдавать ваучеры и регистрировать (log) заявки на владение от доменов. На высших уровнях защиты выпус ваучеров может быть интегрирован с комплексными каналами продаж, но это выходит за рамки документа. Интеграция с каналом продаж будет подтверждать фактическое (правовое) владение заявителем со стороны домена. Это обеспечивает гибкость для множества вариантов применения на основе одного базового протокольного механизма для заявителя и регистратора, который будет развернут в «полевых» условиях. Службы MASA обладают гибкостью, позволяющей применять имеющиеся механизмы заявления прав и экспериментировать с разными уровнями защиты.

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

2.3. Исходный идентификатор устройства

Аутентификация заявителя и подписание запроса ваучера выполняются с использованием сертификата в форме PKIX, установленного в процессе производства. Это идентификатор 802.1AR IDevID, обеспечивающий основу для аутентификации заявителя в протокольном обмене, описываемом здесь. Иерархия PKI с общим корнем не требуется, каждый производитель устройств имеет свой корневой сертификат. IDevID позволяет, в частности, указанное ниже.

  • Однозначная идентификация заявителя по отличительному имени (Distinguished Name или DN) и subjectAltName (SAN) в IDevID. Однозначная идентификация заявителя в объектах ваучеров выводится из этих параметров, как описано ниже. В параграфе 10.3 рассматривается влияние идентификатора на приватность.

  • Обеспечение регистратору криптографической аутентификации заявителя (параграф 5.3).

  • Защита автоматического обнаружения MASA заявителя регистратором (параграф 2.8).

  • Подписание запроса ваучера с помощью IDevID заявителя (раздел 3).

  • Обеспечение агенту MASA криптографической аутентификации заявителя (параграф 5.5.5).

В параграфе 7.2.13 (редакция 2009 г.) и 8.10.3 (редакция 2018 г.) [IDevID] обсуждаются расширения keyUsage и extendedKeyUsage для сертификата IDevID. В [IDevID] указано, что добавление ограничений в сертификат сужает его применимость для долгосрочных сертификатов. Эта спецификация подчёркивает данное обстоятельство и рекомендует не задавать ограничений на использование ключей. Это согласуется с параграфом 4.2.1.3 в [RFC5280], где не требуется ограничивать использование ключей для сертификатов конечных объектов.

2.3.1. Идентификация заявителя

В контексте BRSKI с заявителем однозначно связан серийный номер (serial-number). Этот номер используется в поле ваучера serial-number или voucher-request (3. Артефакт запроса ваучера) и локальных правилах регистратора или MASA (5. Детали протокола (заявитель — регистратор — MASA)).

Поле (сертификата) serialNumber определено в параграфе 4.1.2.2 [RFC5280]. В ASN.1 это называется CertificateSerialNumber. К данной спецификации это поле не имеет отношения. Не следует путать это поле с serial-number, определенным в этом документе или [IDevID] и параграфе 2.31 в [RFC4519].

Серийный номер определён в Приложении A.1 к [RFC5280] как X520SerialNumber с тегом OID id-at-serialNumber.

Серийный номер устройства (X520SerialNumber) используется заявителем для создания поля serial-number, помещаемого в voucher-request. Для этого значение преобразуется в тип type string.

Пример печатного представления поля serialNumber представлен в параграфе 2.31 (WI-3005) [RFC4519]. В этом параграфе дополнительно представлены атрибуты равенства и синтаксиса.

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

Как указано в параграфе 5.5, регистратор должен заново извлечь serialNumber из сертификата TLS заявителя. Он может обратиться к serial-number в запросе заявителя при возникновении возможности путаницы с номерами.

2.3.2. Расширение MASA URI

Этот документ определяет новое некритическое расширение сертификата PKIX для передачи MASA URI, предназначенное для применения в сертификате IDevID. Представление URI дано в параграфе 7.4 [RFC5280]. URI обеспечивает сведения о полномочиях. дерево BRSKI /.well-known [RFC8615] описано в разделе 5.

В этом расширении может быть полное значение URI, включая scheme, authority и path. Полное значение URI обычно применяется для диагностики или экспериментов. Как правило (и с учётом систем с ограничениями) идентификатор следует сокращать до authority в предположении схемы https:// (параграф 2.7.3 в [RFC7230]) и пути /.well-known/brski.

Регистратор может предположить наличие в расширении лишь элемента authority, если в расширении нет символов /.

В параграфе 7.4 [RFC5280] названы различные схемы, которые должны поддерживаться, включая облегченный протокол доступа к каталогам (Lightweight Directory Access Protocol или LDAP), HTTP, FTP. Однако регистратор должен использовать HTTPS для соединения BRSKI-MASA. Идентификация нового расширения показана ниже.

   <CODE BEGINS>
   MASAURLExtnModule-2016 { iso(1) identified-organization(3) dod(6)
   internet(1) security(5) mechanisms(5) pkix(7)
   id-mod(0) id-mod-MASAURLExtn2016(96) }

   DEFINITIONS IMPLICIT TAGS ::= BEGIN

   -- EXPORTS ALL --

   IMPORTS
   EXTENSION
   FROM PKIX-CommonTypes-2009
     { iso(1) identified-organization(3) dod(6) internet(1)
       security(5) mechanisms(5) pkix(7) id-mod(0)
       id-mod-pkixCommon-02(57) }

   id-pe FROM PKIX1Explicit-2009
     { iso(1) identified-organization(3) dod(6) internet(1)
        security(5) mechanisms(5) pkix(7) id-mod(0)
        id-mod-pkix1-explicit-02(51) } ;

   MASACertExtensions EXTENSION ::= { ext-MASAURL, ... }
   ext-MASAURL EXTENSION ::= { SYNTAX MASAURLSyntax
   IDENTIFIED BY id-pe-masa-url }

   id-pe-masa-url OBJECT IDENTIFIER ::= { id-pe 32 }

   MASAURLSyntax ::= IA5String

   END
   <CODE ENDS>

Рисунок 3. Модуль MASAURL ASN.1.

Выбор id-pe основывается на рекомендациях параграфа 4.2.2 в [RFC5280]: «Эти расширения могут служить для направления приложений к online-сведениям об эмитенте субъекта.» MASA URL содержит именно online-сведения о конкретном субъекте.

2.4. Поток протокола

Представление потока показано на рисунке 4. При первой начальной загрузке новое устройство (заявитель) использует автоматическое обнаружение локальной службы (GeneRic Autonomic Signaling Protocol — GRASP или Multicast DNS — mDNS) для нахождения посредника в присоединении (Join Proxy). Посредник соединяет заявителя с локальным регистратором (JRC).

Найдя кандидата в регистраторы, новый заявитель передаёт регистратору некоторые сведения о себе, включая серийный номер, в форме voucher-request и свой сертификат IDevID как часть сессии TLS.

Регистратор может определить, ожидал ли он появления такого устройства, и найти MASA. Местоположение MASA обычно указывается в расширении IDevID. После определения приемлемости MASA вся информация из начального voucher-request (включая серийный номер устройства) передаётся через Internet по защищённому TLS каналу изготовителю устройства вместе по сведениями о регистраторе и владельце.

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

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

+--------+         +---------+    +------------+     +------------+
| Pledge |         | Circuit |    | Domain     |     | Vendor     |
|        |         | Join    |    | Registrar  |     | Service    |
|        |         | Proxy   |    |  (JRC)     |     | (MASA)     |
+--------+         +---------+    +------------+     +------------+
  |                     |                   |           Internet |
[discover]              |                   |                    |
  |<-RFC 4862 адрес IPv6|                   |                    |
  |<-RFC 3927 адрес IPv4| Приложение A      | Обозначения        |
  |-++++++++++++++++++->|                   | C - посредник в    |
  | необяз.: mDNS query | Приложение B      | присоединении      |
  | RFCs 6763/6762 (+)  |                   | P - соединение TLS |
  |<-++++++++++++++++++-|                   | для взаимодействия |
  | GRASP M_FLOOD       |                   |                    |
  | период. широковещат.|                   |                    |
[identity]              |                   |                    |
  |<------------------->C<----------------->|                    |
  |          TLS через Join Proxy           |                    |
  |<-Аутентифик. TLS-сервера регистратора---|                    |
[PROVISIONAL accept of server cert]         |                    |
  P---Аутентификация клиента X.509--------->|                    |
[запрос присоединения]                      |                    |
  P---Voucher-Request(w/nonce for voucher)->|                    |
  P                  /-------------------   |                    |
  P                  |                 [accept device?]          |
  P                  |                 [contact vendor]          |
  P                  |                      |--Pledge ID-------->|
  P                  |                      |--Domain ID-------->|
  P                  |                      |--optional:nonce--->|
  P            необязательно:               |     [extract DomainID]
  P        может выполняться заранее,       |     [update audit-log]
  P        если nonce не применяется        |                    |
  P                  |                      |<- voucher ---------|
  P                  \-------------------   | с nonce при наличии|
  P<------voucher---------------------------|                    |
[imprint]                                   |                    |
  |-------voucher status telemetry--------->|                    |
  |                                         |<-device audit-log--|
  |                             [проверка audit-log и ваучера]   |
  |<--------------------------------------->|                    |
[enroll]                                    |                    |
  | Продолжение зачисления с использованием |                    |
  | аутентифицированной в обоих направлениях|                    |
  | сессией TLS в соответствии с RFC 7030.  |                    |
[enrolled]                                  |                    |

Рисунок 4. Временная диаграмма протокола.


В подписанном ваучере фильтрация сведений невозможна, поскольку это двоичное решение — «да-нет». Регистратор применяет к ваучеру локальную политику и в случае восприятия ваучера возвращает его заявителю для впечатывания.

Ваучер также включает привязку доверия, которую заявитель использует для представления владельца. Это используется для начальной загрузки из среды, где устройство имеет «встроенное» доверие лишь к изготовителю, в среду, где владелец имеет PKI-отпечаток на устройстве.

Когда BRSKI следует за EST, этот единственный отпечаток дополнительно используется в PKI владельца и LDevID для устройства. Последующие этапы отчётности предоставляют потоки сведений, указывающих результат процесса — успех или неудача.

2.5. Компоненты архитектуры

2.5.1. Заявитель

Заявитель является устройством, которое пытается присоединиться. Предполагается, что заявитель взаимодействует с Join Proxy используя локальное соединение (link-local). В большинстве случаев у заявителя нет других соединений, пока тот не завершит процесс зачисления и не получит то или иное свидетельство (credential) от сети.

2.5.2. Посредник присоединения

Join Proxy обеспечивает соединение HTTPS между заявителем и регистратором. механизм Circuit Proxy описан в разделе 4. Дополнительные механизмы, включая протокол приложений с ограничениями (Constrained Application Protocol или CoAP) и механизм IP in IP (IPIP) без поддержки состояний требуют дополнительной работы.

2.5.3. Регистратор домена

Регистратор домена выступает как клиент BRSKI-MASA при запросе ваучеров у MASA (5.4. Организация BRSKI-MASA TLS). Регистратор служит сервером BRSKI-EST, когда заявители запрашивают ваучеры (5.1. Организация BRSKI-EST TLS). Регистратор служит сервером BRSKI-EST агентства регистрации (Registration Authority) при запросе заявителем сертификата конечного объекта через соединение BRSKI-EST (5.9. Интеграция EST с начальной загрузкой).

Регистратор использует базу неявных привязок доверия (Implicit Trust Anchor) для аутентификации сертификата сервера MASA TLS соединения BRSKI-MASA. Настройка и распространение привязок доверия выходят за рамки этой спецификации.

Регистратор использует другую базу Implicit TA для аутентификации клиентского сертификата TLS заявителя в соединении BRSKI-EST. Настройка и распространение точек доверия клиента BRSKI-EST выходят за рамки этой спецификации. Отметим, что привязки доверия в корне (/), исключённые из базы данных, будут влиять на выбор устройств изготовителя, воспринимаемых в качестве заявителей, а также будут служит для ограничения набора MASA, которые являются доверенными для зачисления.

2.5.4. Служба изготовителя

Служба изготовителя обеспечивает две логически разделённых функции — MASA, как описано в параграфах 5.5 и 5.6, а также отслеживание и аудит владения, как описано в параграфах 5.7 и 5.8.

2.5.5. Инфраструктура открытых ключей

Инфраструктура открытых ключей (Public Key Infrastructure или PKI) управляет сертификатами соответствующего домена, обеспечивая привязки доверия для него и позволяя зачислять заявителей с сертификатами домена.

Ваучеры обеспечивают метод распространения одной точки доверия PKI (как pinned-domain-cert). Распространение полного набора привязок доверия возможно через необязательную интеграцию с EST.

Регистратор домена выступает в качестве Registration Authority [RFC5272], запрашивая сертификаты заявителей в PKI.

Ожидания от PKI не изменились по сравнению с EST [RFC7030] и этот документ не вносит дополнительных архитектурных требований к PKI.

2.6. Проверка времени в сертификате

2.6.1. Отсутствие часов

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

Заявитель раскрывается со значениями даты в 5 элементах: notBefore и notAfter в сертификате регистратора, created-on и expires-on в ваучере, а также подписи в CMS4, содержащие signingTime. Заявитель с часами, которым он доверяет, должен проверить указанные значения времени во всех обрабатываемых сертификатах и подписях.

Если ваучер содержит nonce, заявитель должен подтвердить соответствие исходному voucher-request от заявителя. Это подтверждает свежесть ваучера (5.2. Запрос заявителем ваучера у регистратора).

2.6.2. Неограниченный срок действия IDevID

В сертификатах с длительным сроком действия «следует устанавливать значение GeneralizedTime = 99991231235959Z» в поле notAfter, как описано в [RFC5280].

Некоторые развёрнутые системы управления IDevID не соответствуют требованиям 802.1AR к неограниченному сроку действия и имеют обычно срок действия сертификата не более 3 лет. Регистраторам следует быть настраиваемыми по производителям, чтобы они игнорировали сроки действия заявителей, когда те не соответствуют рекомендациям [RFC5280].

2.7. Облачный регистратор

Имеются операционно открытые сети, где устройства получают доступ в Internet без проверки полномочий (unauthenticated). В таких случаях домен управления для устройств должен быть открыт из сети Internet. Случаи, когда устройство может загрузиться и получить доступ Internet, менее вероятны в сфере действия ANIMA ACP, но могут стать более важными в будущем. В области действия ANIMA ACP новые устройства будут помещаться в карантин за посредником присоединения (Join Proxy).

Кроме того, имеются ситуации с совершенно новыми инсталляциями, где устройства могут иметь тот или иной тип восходящего канала (uplink) управления, пригодного для использования, например, сеть 3G. В таких будущих ситуациях устройство может использовать интерфейс управления, чтобы узнать, что оно должно настроить себя для работы в качестве локального регистратора. Для поддержки таких случаев заявитель может обратиться по общеизвестному URI облачного регистратора, если не удаётся обнаружить локальный регистратор или цель использования регистратора не включает локальный регистратор. Если заявитель использует общеизвестный идентификатор URI для обращения к облачному регистратору, должна использоваться заданная изготовителем база Implicit TA [RFC7030] для аутентификации этой службы в соответствии с [RFC6125]. Приемлемо использования DNS-ID для проверки и это может включать шаблонные компоненты в левой части. Это согласуется с настройкой URI сервера EST человеком [RFC7030], которая тоже зависит от [RFC6125].

2.8. Определение MASA для контактов

Регистратор должен иметь возможность контакта с агентом MASA, которому доверяет заявитель, для получения ваучеров. Идентификатор устройства IDevID обычно содержит MASA URL, как указано в параграфе 2.3. Рекомендуется применять этот механизм.

В некоторых случаях может быть сложно обеспечить требуемые расширения X.509 в IDevID заявителя из-за сложности согласования производства заявителя с разработкой и выпуском программного обеспечения. Поэтому в качестве финальной меры регистратор можно настроить вручную или распространять с MASA URL для каждого изготовителя. Отметим, что регистратор может выбирать настроенный MASA URL лишь на основе привязки доверия, поэтому изготовители могут применять такой подход лишь при наличии гарантии работы одного MASA URL для всех заявителей, связанных с каждой привязкой доверия.

3. Артефакт запроса ваучера

Для запроса ваучеров применяется voucher-request. Семантика описана ниже в модуле YANG. Заявитель формирует voucher-request, подписывает его с помощью IDevID и представляет регистратору. Регистратор формирует свой voucher-request, подписывает его с использованием своих ключей и представляет MASA.

В voucher-request заявителя используется лист proximity-registrar-cert, позволяющий заявителю подтвердить близость регистратора. Эта сетевая близость (network proximity) является следствием свойств в контексте ACP — заявитель подключается к Join Proxy (раздел 4) с использованием соединения IPv6 по локальному каналу (link-local). Хотя Join Proxy не участвует значимо в криптографии соединения TLS (например, через Channel Binding), регистратор может видеть, что соединение выполняется через приватный адрес ACP (ULA) посредника присоединения и не может приходить извне ACP. Поэтому заявитель должен находиться не далее одного интервала пересылки (hop) IPv6 link-local от имеющегося узла ACP.

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

Лист prior-signed-voucher-request используется в voucher-request регистратора. При наличии листа он является подписанным артефактом voucher-request от заявителя. Это обеспечивает регистратору способ пересылки подписанного заявителем запроса агенту MASA, завершающей передачу подписанного листа proximity-registrar-cert.

Если не указано иное (вне артефакта voucher-request), структура подписи соответствует заданной для ваучеров [RFC8366].

3.1. Ваучеры без Nonce

Регистратор может извлекать ваучеры без nonce, передавая voucher-request без nonce агенту MASA для получения ваучеров, применяемых при отсутствии у регистратора связности с MASA. Лист prior-signed-voucher-request в этом случае не включается. Регистратору также нужно знать серийный номер заявителя. Этот документ не задаёт механизма автоматического получения этих сведений. Обычно это делается путём сканирования штрихкода или QR-кода на упаковке или через интеграцию с каналами продаж.

3.2. Диаграмма дерева

На рисунке 5 приведено дерево высокоуровневого представления документа voucher-request, созданного на основе артефакта ваучера, описанного в [RFC8366]. Дерево использует нотацию и синтаксис [RFC8340]. Каждый узел полностью описан в параграфе 3.4. Модуль YANG.

   module: ietf-voucher-request
    grouping voucher-request-grouping
     +-- voucher
        +-- created-on?                      yang:date-and-time
        +-- expires-on?                      yang:date-and-time
        +-- assertion?                       enumeration
        +-- serial-number                    string
        +-- idevid-issuer?                   binary
        +-- pinned-domain-cert?              binary
        +-- domain-cert-revocation-checks?   boolean
        +-- nonce?                           binary
        +-- last-renewal-date?               yang:date-and-time
        +-- prior-signed-voucher-request?    binary
        +-- proximity-registrar-cert?        binary

Рисунок 5. Дерево YANG для Voucher-Request.

3.3. Примеры

В этом параграфе приведены примеры, иллюстрирующие voucher-request в форме JSON до упаковки в CMS. Правила кодирования JSON задают представление двоичных объектов в формате base64 (раздел 4 в [RFC4648]). Содержимое кодированных (base64) сертификатов опущено для краткости, детальные примеры приведены в приложении C.2. Примеры следуют правилам кодирования, заданным в [RFC7951].

Пример 1

Ниже показан запрос voucher-request от заявителя. Лист assertion указан как proximity, а сертификат TLS регистратора включён в лист proximity-registrar-cert (5.2. Запрос заявителем ваучера у регистратора).
   {
       "ietf-voucher-request:voucher": {
           "assertion": "proximity",
           "nonce": "62a2e7693d82fcda2624de58fb6722e5",
           "serial-number" : "JADA123456789",
           "created-on": "2017-01-01T00:00:00.000Z",
           "proximity-registrar-cert": "base64encodedvalue=="
       }
   }

Рисунок 6. Представление JSON для примера Voucher-Request.

Пример 2

Ниже показан запрос voucher-request от регистратора. Лист prior-signed-voucher-request содержит voucher-request от заявителя (как в первом примере), который является двоичным объектом с подписью CMS. В используемой форме JSON он должен кодироваться в формате base64. Листья nonce и assertion из запроса заявителя перенесены в запрос регистратора. Значение serial-number извлечено из клиентского сертификата заявителя в соединении TLS (5.5. Запрос регистратором ваучера у MASA).
   {
       "ietf-voucher-request:voucher": {
           "assertion" : "proximity",
           "nonce": "62a2e7693d82fcda2624de58fb6722e5",
           "created-on": "2017-01-01T00:00:02.000Z",
           "idevid-issuer": "base64encodedvalue==",
           "serial-number": "JADA123456789",
           "prior-signed-voucher-request": "base64encodedvalue=="
       }
   }

Рисунок 7. Представление JSON для Prior-Signed Voucher-Request.

Пример 3

Ниже показан запрос voucher-request от регистратора. Лист prior-signed-voucher-request не содержит ни voucher-request от заявителя, ни листа nonce. Эта форма может применяться регистратором, запрашивающим ваучер, когда заявитель не может взаимодействовать с регистратором (например, выключен или ещё не распакован) и поэтому не может представить nonce. Этот вариант наиболее полезен в случаях, когда регистратору известно, что он не может получить доступ к MASA в процессе развёртывания (5.5. Запрос регистратором ваучера у MASA).
   {
       "ietf-voucher-request:voucher": {
           "created-on":    "2017-01-01T00:00:02.000Z",
           "idevid-issuer": "base64encodedvalue==",
           "serial-number": "JADA123456789"
       }
   }

Рисунок 8. Представление JSON для Offline Voucher-Request.

3.4. Модуль YANG

Ниже представлен модуль YANG [RFC7950] формально преобразующий ваучер [RFC8366] в voucher-request. Этот модуль YANG ссылается на [ITU.X690].

   <CODE BEGINS> file "ietf-voucher-request@2021-05-20.yang"
   module ietf-voucher-request {
     yang-version 1.1;
     namespace "urn:ietf:params:xml:ns:yang:ietf-voucher-request";
     prefix vcr;

     import ietf-restconf {
       prefix rc;
       description
         "Этот оператор импорта предназначен лишь для доступа к 
          расширению yang-data из RFC 8040.";
       reference
         "RFC 8040: RESTCONF Protocol";
     }
     import ietf-voucher {
       prefix vch;
       description
         "Этот модуль задаёт формат для ваучера, который изготовитель
          заявителя создаёт или делегирует (MASA) для защищённого 
          назначения заявителя владельцем, чтобы тот мог организовать
          защищённое соединение с сетевой инфраструктурой владельца.";
       reference
         "RFC 8366: A Voucher Artifact for
          Bootstrapping Protocols";
     }

     organization
       "IETF ANIMA Working Group";
     contact
       "WG Web:   <https://datatracker.ietf.org/wg/anima/> 
        WG List:  <mailto:anima@ietf.org> 
        Author:   Kent Watsen
                  <mailto:kent+ietf@watsen.net> 
        Author:   Michael H. Behringer
                  <mailto:Michael.H.Behringer@gmail.com> 
        Author:   Toerless Eckert
                  <mailto:tte+ietf@cs.fau.de> 
        Author:   Max Pritikin
                  <mailto:pritikin@cisco.com> 
        Author:   Michael Richardson
                  <mailto:mcr+ietf@sandelman.ca>"; 
     description
       "Этот модуль задаёт формат voucher-request, являющегося
        надмножеством voucher. Модуль обеспечивает агенту
        сведения для рассмотрения voucher-request.

        Ключевые слова ДОЛЖНО, НЕДОПУСТИМО, ТРЕБУЕТСЯ, НУЖНО, НЕ НУЖНО, 
        СЛЕДУЕТ, НЕ СЛЕДУЕТ, РЕКОМЕНДУЕТСЯ, НЕ РЕКОМЕНДУЕТСЯ, МОЖНО,
        НЕОБЯЗАТЕЛЬНО в этом документе трактуются в соответствии с 
        BCP 14 (RFC 2119) (RFC 8174) тогда и только тогда, когда они
        указаны заглавными буквами, как показано здесь.

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

        Распространение и применение модуля в исходной или двоичной 
        форме с изменениями или без таковых разрешено в соответствии с
        лицензией Simplified BSD License, изложенной в параграфе 4.c
        IETF Trust's Legal Provisions Relating to IETF Documents
        (https://trustee.ietf.org/license-info). 

        Эта версия модуля YANG является частью RFC 8995, где правовые
        аспекты приведены более полно.";

     revision 2021-05-20 {
       description
         "Исходный выпуск";
       reference
         "RFC 8995: Bootstrapping Remote Secure Key Infrastructure
          (BRSKI)";
     }

     // Оператор верхнего уровня
     rc:yang-data voucher-request-artifact {
       uses voucher-request-grouping;
     }

     // Группировка для будущего использования

     grouping voucher-request-grouping {
       description
         "Группировка для использования и расширения в будущем.";
       uses vch:voucher-artifact-grouping {
         refine "voucher/created-on" {
           mandatory false;
         }
         refine "voucher/pinned-domain-cert" {
           mandatory false;
           description
             "Поле pinned-domain-cert недействительно в voucher-request 
              и ДОЛЖНО игнорироваться при наличии.";
         }
         refine "voucher/last-renewal-date" {
           description
             "Поле last-renewal-date недействительно в voucher-request 
              и ДОЛЖНО игнорироваться при наличии.";
         }
         refine "voucher/domain-cert-revocation-checks" {
           description
             "Поле domain-cert-revocation-checks недействительно в 
              voucher-request и ДОЛЖНО игнорироваться при наличии.";
         }
         refine "voucher/assertion" {
           mandatory false;
           description
             "Агенту MASA СЛЕДУЕТ игнорировать любые assertion в 
              voucher-request от регистратора.";
         }
         augment "voucher" {
           description
             "Добавляет листью, подходящие для запроса ваучеров.";
           leaf prior-signed-voucher-request {
             type binary;
             description
               "Если требуется сменить ваучер или заново подписать и
                переслать ваучер, который был представлен с протокольным
                путём, прежний ваучер СЛЕДУЕТ включить в это поле.

                Например, заявитель может подписать voucher-request с
                proximity-registrar-cer и регистратор включит его как 
                prior-signed-voucher-request. Это простой механизм для
                связывания доверенных сторон для смены voucher-request
                с сохранением сведений прежней подписи.

                Регистратор и MASA МОГУТ проверить сведения подписанного
                ранее ваучера в соответствии с правилами. Например, эти
                сведения могут быть полезны MASA для проверки согласия
                заявителя и регистратора с заявлением близости. MASA 
                СЛЕДУЕТ удалять сведения prior-signed-voucher-request
                при подписании ваучера для впечатывания с целью 
                сокращения окончательного размера вайчера.";
           }
           leaf proximity-registrar-cert {
             type binary;
             description
               "Структура сертификата X.509 v3, заданная в разделе 4
                RFC 5280, закодированная по правилам ASN.1 DER, как
                указано в ITU X.690.

                Первый сертификат в последовательности certificate_list 
                TLS-сервера регистратора (сертификат TLS конечного 
                элемента, см. RFC 8446), представленной регистратором
                заявителю. Лист ДОЛЖЕН заполняться в voucher-request
                заявителя при запросе заявления близости.";
             reference
               "ITU X.690: Information Technology - ASN.1 encoding
                rules: Specification of Basic Encoding Rules (BER),
                Canonical Encoding Rules (CER) and Distinguished
                Encoding Rules (DER)
                RFC 5280: Internet X.509 Public Key Infrastructure
                Certificate and Certificate Revocation List (CRL)
                Profile
                RFC 8446: The Transport Layer Security (TLS)
                Protocol Version 1.3";
           }
         }
       }
     }
   }
   <CODE ENDS>

Рисунок 9. Модуль YANG для Voucher-Request.

4. Детали посредничества (заявитель — прокси — регистратор)

Этот раздел является нормативным для использования с ANIMA ACP, применение механизма GRASP является частью ACP. Другим пользователям BRSKI нужно определить эквивалентный механизм посредничества для настройки прокси. Роль прокси состоит в облегчении взаимодействия путём пересылки между заявителем и регистратором пакетов, предоставленных посреднику через полное обнаружение GRASP ACP.

В этом разделе определён механизм посредничества в учётом состояния, называемый circuit proxy, который является формой шлюза прикладного уровня (Application Level Gateway, см. параграф 2.9 в [RFC2663]). Посредник не прерывает согласование TLS, он просто передаёт потоки данных без проверки. Посреднику недопустимо предполагать какую-либо конкретную версию TLS. Детали инвариантов TLS описаны в параграфе 9.3 [RFC8446].

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

В результате процесса обнаружения прокси, описанного в параграфе 4.1.1, раскрываемому посредником номеру порта не требуется быть общеизвестным или выделенным IANA.

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

Чтобы позволить реализацию функциональности посредника для максимально широкого класса устройств следует применять механизм с минимальным числом состояний ну устройстве-посреднике. Хотя многие устройства в целевом пространства ANIMA будут скорее большими маршрутизаторами, функции посредника вероятно будут реализованы в CPU плоскости управления такого устройства с возможностями proxy-функции близкими к устройствам IoT класса 2.

В [ANIMA-STATE] приведён более детальный анализ и основы других методов посредничества.

4.1. Обнаружение посредника заявителем

Результатом обнаружения является логическое соединение с регистратором через посредника, который прозрачен для заявителя. Связь между заявителем и Join Proxy происходит по адресам IPv6 link-local. Для обнаружения посредника заявитель выполняет указанные ниже действия.

  1. Требуется получить локальный адрес с использованием методов IPv6, описанных в IPv6 Stateless Address Autoconfiguration [RFC4862]. Рекомендуется применять временные адреса [RFC8981]. Для ограничения всеобъемлющего отслеживания [RFC7258] новые временный адрес может применяться кратковременно (малое значение TEMP_PREFERRED_LIFETIME). Заявители обычно будут предпочитать адреса IPv6 link-local и искать посредника с помощью механизмов локального канала. Методы для IPv4 описаны в Приложении A.

  2. Должны прослушиваться анонсы GRASP M_FLOOD [RFC8990] для цели AN_Proxy, более подробно описанной в параграфе 4.1.1. Анонсирование Proxy GRASP. Заявитель может одновременно прослушивать другие источники информации (Приложение B. Варианты mDNS и DNS-SD Proxy Discovery).

После обнаружения посредника заявитель взаимодействует с регистратором через прокси, используя протокол начальной загрузки, заданный в разделе 5. Детали протокола (заявитель — регистратор — MASA).

Хотя механизм GRASP M_FLOOD является пассивным для заявителя, другие ненормативные методы (mDNS и IPv4), описанные в Приложении B, являются активными. Заявителю следует запускать эти методы вместе с прослушиванием M_FLOOD. Активным методам следует удваивать время отсрочки (вплоть до 1 часа) для предотвращения перегрузки сети попытками обнаружения. При обнаружении смены состояния физического канала (например, несущей Ethernet) следует сбрасывать таймеры отсрочки.

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

Интервалы между попытками соединения через один прокси следует экспоненциально увеличивать вплоть до 1 часа для предотвращения перегрузки сетевой инфраструктуры. Таймеры отсрочки для каждого соединения должны быть независимыми. Попытки соединения следует предпринимать в параллель для предотвращения проблем в голове очереди, когда атакующий с фиктивным посредником или регистратором может преднамеренно замедлять операции протокола. Попытки соединения с разными прокси следует предпринимать с интервалом от 3 до 5 секунд. Заявителю следует продолжать прослушивание дополнительных сообщений GRASP M_FLOOD при попытках соединения. Для каждой попытки соединения через свой Join Proxy должно применяться уникальное значение nonce в voucher-request.

Когда соединение с регистратором установлено (например, создан сеансовый ключ TLS), ожидается более скорый отклик (5.2. Запрос заявителем ваучера у регистратора).

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

4.1.1. Анонсирование Proxy GRASP

Посредник использует для анонсирования себя механизм DULL GRASP M_FLOOD. Этот анонс может находиться в одном сообщении с анонсом ACP, описанным в [RFC8994]. Формальное определение CDDL5 [RFC8610] имеет вид

   <CODE BEGINS> file "proxygrasp.cddl"
   flood-message = [M_FLOOD, session-id, initiator, ttl,
                    +[objective, (locator-option / [])]]

   objective = ["AN_Proxy", objective-flags, loop-count,
                                          objective-value]

   ttl             = 180000     ; 180000 мсек (3 минуты)
   initiator = адрес ACP для контакта с регистратором
   objective-flags   = sync-only  ; как в спецификации GRASP
   sync-only         =  4         ; M_FLOOD требует лишь синхронизации
   loop-count        =  1         ; только один интервал пересылки (hop)
   objective-value   =  any       ; нет

   locator-option    = [ O_IPv6_LOCATOR, ipv6-address,
                       transport-proto, port-number ]
   ipv6-address      = адрес IPv6 LL для Proxy
   $transport-proto /= IPPROTO_TCP  ; Это может быть любое значение из 
                                    ; реестра протоколов IANA, как в
                                    ; параграфе 2.9.5.1 RFC 8990
                                    ; (примечание 3).
   port-number      = выбирается Proxy
   <CODE ENDS>

Рисунок 10. Определение CDDL для сообщения Proxy Discovery.

Ниже приведён пример анонса M_FLOOD для посредника с адресом fe80::1 на порту TCP 4443.

 [M_FLOOD, 12340815, h'fe800000000000000000000000000001', 180000,
             [["AN_Proxy", 4, 1, ""],
              [O_IPv6_LOCATOR,
               h'fe800000000000000000000000000001', IPPROTO_TCP, 4443]]]

Рисунок 11. Пример сообщения Proxy Discovery.

В небольшой сети регистратор может включать анонсы GRASP M_FLOOD в локально подключённые сети. Поле $transport-proto выше указывает метод, который будет использовать pledge-proxy-registrar. Описанный здесь метод TCP является обязательным, а другие прокси-методы, такие как методы CoAP, не определённые в этом документе, не являются обязательными. Другие методы недопустимо включать, пока Join Registrar ASA не указывает их поддержку в своих анонсах.

4.2. Соединение CoAP с регистратором

Использование CoAP для соединения заявителя с регистратором выходит за рамки этого документа и рассматривается в [ANIMA-CONSTRAINED-VOUCHER].

4.3. Обнаружение посредника и связь с регистратором

Регистратору следует анонсировать себя, чтобы посредники могли найти его и определить, какой тип соединения может быть завершён. Регистратор анонсирует себя в сообщениях GRASP M_FLOOD с целью AN_join_registrar в экземпляре ACP. Регистратор может анонсировать любой подходящий номер порта, включая стандартный порт 443. Посредники ANI должны поддерживать обнаружение регистраторов GRASP. Формат M_FLOOD показан ниже.

 [M_FLOOD, 51804321, h'fda379a6f6ee00000200000064000001', 180000,
             [["AN_join_registrar", 4, 255, "EST-TLS"],
              [O_IPv6_LOCATOR,
               h'fda379a6f6ee00000200000064000001', IPPROTO_TCP, 8443]]]

Рисунок 12. Пример сообщения Registrar Announcement.

Формальное определение CDDL приведено ниже.

   <CODE BEGINS> file "jrcgrasp.cddl"
   flood-message = [M_FLOOD, session-id, initiator, ttl,
                    +[objective, (locator-option / [])]]

   objective = ["AN_join_registrar", objective-flags, loop-count,
                                          objective-value]

   initiator = адрес ACP для контактов с регистратором
   objective-flags = sync-only  ; как в спецификации GRASP
   sync-only         =  4       ; M_FLOOD требует лишь синхронизации
   loop-count      = 255        ; обязательный максимум
   objective-value = text       ; имя (или список имен) поддерживаемого
                                ; протокола (EST-TLS для RFC 7030).
   <CODE ENDS>

Рисунок 13. Определение CDDL для сообщения Registrar Announcement.

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

Ниже приведены некоторые примеры локаторов для иллюстрации, из которых лишь первый ($transport-protocol = 6, TCP) определён в этом документе и обязателен для регистрации.

   locator1  = [O_IPv6_LOCATOR, fd45:1345::6789, 6,  443]
   locator2  = [O_IPv6_LOCATOR, fd45:1345::6789, 17, 5683]
   locator3  = [O_IPv6_LOCATOR, fe80::1234, 41, nil]

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

Регистраторы должны анонсировать набор поддерживаемых протоколов и должны поддерживать трафик TCP.

Регистраторы должны воспринимать трафик HTTPS/EST на указанном порту TCP.

Регистраторы должны поддерживать ANI TLS Circuit Proxy и, следовательно, BRSKI через HTTPS/TLS в ACP.

В ANI должен использоваться защищённый ACP экземпляр GRASP [RFC8990] для обнаружения адресов ANI регистратора ACP и портов посредников ANI. Поэтому ветвь TCP прокси-соединения между посредником ANI и регистратором ANI также работает через ACP.

5. Детали протокола (заявитель — регистратор — MASA)

Заявитель должен инициировать BRSKI после загрузки, если это ещё не настроено. заявителю недопустимо автоматически инициировать BRSKI, если инфраструктура уже настроена или настраивается сейчас.

Инфраструктура BRSKI описана как расширение EST [RFC7030]. Цель этих расширений заключается в сокращении числа соединений TLS и криптоопераций, требуемых для заявителя. Регистратор реализует интерфейс BRSKI REST в дереве URI /.well-known/brski и реализует имеющиеся EST URI, как указано в параграфе 2.2.2 EST [RFC7030]. Канал связи между заявителем и регистратором обозначается как BRSKI-EST (Рисунок 1).

Каналом связи между регистратором и MASA является новый коммуникационный канал, аналогичный EST, внутри вновь зарегистрированного дерева /.well-known/brski. Для ясности этот канал обозначен как BRSKI-MASA (Рисунок 1).

MASA URI имеет вид https://» authority «/.well-known/brski.

BRSKI использует имеющиеся форматы сообщений CMS для существующих операций EST и JSON [RFC8259] для всех новых операций, определённых здесь для форматов ваучеров. Во всех случаях, когда двоичное значение должно быть передано в строке JSON, применяется формат base64 (раздел 4 в [RFC4648]) в соответствии с параграфом 6.6 [RFC7951].

Хотя EST (параграф 3.2 в [RFC7030]) не настаивает на использовании постоянных соединений HTTP (параграф 6.3 в [RFC7230]), соединениям BRSKI-EST следует применять их. Цель этого руководства состоит в том, чтобы гарантировать возникновение состояния готовности TLS лишь один раз и предотвратить MITM6-атаки на последующее распознавание состояния готовности во время критической фазы.

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

Обобщённые расширения автоматизации для потока BRSKI-EST перечислены ниже.

  • Заявитель пытается установить одновременные соединения через все обнаруженные прокси или быстро наступает тайм-аут и соединения организуются последовательно, как указано в параграфе 5.1.

  • Заявитель воспринимает сертификат регистратора при согласовании TLS, как указано в параграфе 5.1.

  • Заявитель запрашивает ваучер, используя новые вызовы REST, описанные ниже. Ваучер затем проверяется.

  • Заявитель завершает аутентификацию сертификата сервера, как указано в параграфе 5.6.1. Это выводит соединения BRSKI-EST TLS из условного (provisional) состояния.

  • Обязательные этапы начальной загрузки завершаются телеметрией статуса ваучера (параграф 5.7).

Соединение BRSKI-EST TLS теперь может служить для зачисления EST. Расширения для регистратора (эквивалент сервера EST) указаны ниже.

  • Аутентификация клиента автоматизируется использованием IDevID как при аутентификации клиента EST по на основе сертификатов. Кодирование DN поля субъекта должно включать атрибут serialNumber с уникальным серийным номером устройства, как описано в параграфе 2.3.1. Идентификация заявителя.

  • Регистратор запрашивает ваучер у MASA и проверяет его.

  • Регистратор пересылает ваучер заявителю по запросу.

  • Регистратор проверяет журнал (log), как указано в параграфе 5.8.3, в дополнение к локальным проверкам полномочий, прежде чем воспринимать необязательные запросы заявителя на зачисление его устройства.

5.1. Организация BRSKI-EST TLS

Заявитель организует соединение TLS с регистратором через Circuit Proxy (см. раздел 4), но согласование TLS происходит с регистратором. Заявитель BRSKI-EST является клиентом TLS, а регистратор BRSKI-EST — сервером TLS. Все защищённые связи существуют между заявителем и регистратором независимо от операций посредника.

Рекомендуется применять TLS 1.3 (или новее), на стороне заявителя требуется TLS 1.2 или новее. На интерфейсе сервера и клиента у регистратора следует поддерживать TLS 1.3 (или новее), но можно применять TLS 1.2.7 При использовании TLS 1.3 применять индикатор имени сервера (Server Name Indicator или SNI, [RFC6066]) не требуется в соответствии с параграфом 9.2 в RFC8446 и эта спецификация задаёт профиль приложения. Заявитель соединяется с регистратором, используя лишь адрес IP, и не имеет представления о корректном значении SNI. Это также предполагает, что интерфейс регистратора не может быть виртуальным, поддерживаемым с использованием SNI.

Организация соединения BRSKI-EST TLS происходит в соответствии с параграфом 4.1.1 Bootstrap Distribution of CA Certificates в [RFC7030], при этом клиент аутентифицируется по сертификату IDevID, а сервер EST (регистратор) аутентифицирован ранее по непроверенному сертификату сервера. Настройка и распространение базы данных о привязках доверия, служащей для проверки сертификата IDevID, выходит за рамки этой спецификации. Отметим, что привязки доверия в корне (/), исключённые из базы данных, будут влиять на выбор устройств изготовителя, воспринимаемых регистратором как заявители, и могут также служить для ограничения набора MASA, которым доверяют при зачислении.

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

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

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

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

Заявителю, способному одновременно соединиться с несколькими регистраторами, следует делать это. Некоторые устройства могут быть неспособны на это из-за нехватки потоков или проблем с ресурсами. Параллельные соединения препятствуют попыткам вредоносных посредников вызвать атаки, подобные TCP Slowloris [slowloris].

Заявитель, не способный поддерживать число соединений по числу подходящих посредников, должен будет чередовать варианты, прерывая «заторможенные» соединения. Если в течение 5 секунд соединение «не продвинулось», заявителю следует отбросить наиболее старое соединение и перейти к другому посреднику (тому, с которым связывались в последний раз). Если не было найдено других посредников, заявитель может продолжить ожидание, одновременно прослушивая анонсы новых посредников.

5.2. Запрос заявителем ваучера у регистратора

При начальной загрузке заявитель запрашивает ваучер у регистратора с использованием HTTPS POST с путём к операции /.well-known/brski/requestvoucher. Тип носителя (Content-Type) в voucher-request показан ниже.

application/voucher-cms+json

[RFC8366] задаёт «определённый с использованием YANG документ JSON, подписанный структурой CMS», а voucher-request, описанный в разделе 3, создаётся таким же способом. Тип носителя совпадает с заданным в [RFC8366]. Это же применяется для voucher-request от заявителя. Заявитель должен подписать запрос, используя свидетельства, указанные в параграфе 2.3. Исходный идентификатор устройства.

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

Заявителю следует включать поле заголовка Accept (см. параграф 5.3.2 в [RFC7231]), указывающее приемлемый для отклика с ваучером тип носителя. Тип application/voucher-cms+json определён в [RFC8366], но в будущем ожидаются ограниченные форматы ваучеров. Предполагается гибкость регистраторов и MASA при их восприятии.

Заявитель заполняет поля voucher-request, указанные ниже.

created-on

Заявителю, у которого есть часы, рекомендуется указывать в этом поле текущую дату и время в формате yang:date-and-time, дающие дополнительные сведения агенту MASA. Заявители без часов могут опускать это поле.

nonce

Запрос ваучера от заявителя должен содержать криптографически строгое случайное или псевдослучайное значение nonce (параграф 6.2 в [RFC4086]). Поскольку nonce обычно создаётся в самом начале загрузки, имеются опасения, что одно значение nonce может создаваться при нескольких загрузках или после сброса к заводским установкам. Для каждой попытки начальной загрузки должно создаваться своё значение nonce при параллельных или последовательных загрузках. Свежесть nonce смягчает отсутствие часов, как указано в параграфе 2.6.1.

assertion

Заявитель указывает поддержку описанного в этом документе механизма, помещая значение proximity в voucher-request, и должен включать поле proximity-registrar-cert (см. ниже).

proximity-registrar-cert

В voucher-request заявителя это первый сертификат в последовательности сервера TLS certificate_list (параграф 4.4.2 в [RFC8446]), представленной регистратором заявителю. Это сертификат конечного элемента (end-entity), который должен указываться в voucher-request заявителя.

serial-number

Серийный номер заявителя включается в voucher-request от заявителя. Это значение включается лишь для проверки пригодности и не пересылается регистратором, как указано в параграфе 5.5.

Остальные поля могут быть опущены в voucher-request заявителя.

Пример JSON для voucher-request заявителя представлен в параграфе 3.3 (пример 1).

Регистратор подтверждает, что заявление является proximity и прикрепленный proximity-registrar-cert является сертификатом регистратора. Если эта проверка завершается отказом, это говорит о наличии злоумышленника в пути (MITM) и соединение должно быть закрыто после возврата кода HTTP 401.

5.3. Проверка полномочий заявителя регистратором

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

Регистратор воспринимает или отклоняет запрос на присоединение к домену на основе представленного аутентифицированного отождествления. Для разных сетей примеры автоматизированного принятия запросов могут включать:

  • любое устройство заданного типа (как указано X.509 IDevID);

  • любое устройство определённого производителя (как указано X.509 IDevID);

  • конкретное устройство производителя (как указано X.509 IDevID) из принятого в домене списка (механизм проверки по этому списку для нескольких регистраторов выходит за рамки документа).

Если проверка не проходит, регистратору следует отвечать кодом HTTP 404. Если voucher-request имеет неизвестный формат, лучше подходит код HTTP 406. В ситуациях, которые можно разрешить административными мерами (например, добавлением производителя в список принимаемых) может возвращаться отклик HTTP 403.

При успешной проверке полномочий регистратор получает ваучер от службы MASA (5.5. Запрос регистратором ваучера у MASA) и возвращает заявителю подписанный MASA ваучер, как указано в параграфе 5.6.

5.4. Организация BRSKI-MASA TLS

Соединение BRSKI-MASA TLS является «обычным» соединением TLS, подходящим для интерфейсов HTTPS REST. Регистратор инициирует соединения и использует идентификатор MASA URL, полученный, как указано в параграфе 2.8. Механизмы [RFC6125] следует применять при аутентификации MASA с использованием DNS-ID, соответствующего найденному в IDevID. Регистраторы могут включать механизм переопределения MASA URL для каждого изготовителя и при таком переопределении целесообразно предоставлять альтернативные привязки. Обычно это применяется некоторыми производителями для создания явных (или приватных) привязок доверия для проверки их MASA, которые являются частью интеграции с каналами продаж.

При недоступности TLS 1.3 требуется TLS 1.2 [RFC5246] с поддержкой SNI [RFC6066]. Индикатор имени сервера (SNI) требуется, когда регистратор взаимодействует с MASA, чтобы разместить агент MASA в инфраструктуре TLS с множеством арендаторов.8

Как описано в [RFC7030], MASA и регистраторам следует быть готовыми к поддержке аутентификации клиентского сертификата TLS и/или использованию механизмов HTTP Basic, Digest или Salted Challenge Response Authentication Mechanism. В соединении аутентификация клиента может не использоваться.

Регистраторам следует разрешать предварительную настройку привязок доверия по производителям (MASA). Регистраторам следует иметь возможность настройки TLS Client Certificate по MASA или не использовать сертификаты клиентов, а также следует поддерживать настройку аутентификации HTTP Basic и Digest.

Аутентификация соединения BRSKI-MASA не меняет процесс запроса ваучера, поскольку voucher-request уже подписан регистратором. Аутентификация обеспечивает контроль доступа к журналу аудита, как описано в параграфе 5.8. Запрос журнала аудита у регистратора.

Разработчикам рекомендуется обеспечивать возможность при обращении к MASA создавать защищённое API-соединение с web-службой и учитывать, что в отрасли поддерживается несколько моделей аутентификации. Регистраторам рекомендуется корректно завершать работу и создавать полезные административные уведомления или записи в журнале (log) при получении неожиданных откликов HTTP 401 (Unauthorized) от MASA.

5.4.1. Аутентификация агентом MASA регистратора клиента

Предоставление опций по клиентам требует однозначной идентификации клиентских регистраторов. Это можно сделать любым методом без сохранения состояний, который поддерживает HTTPS (например, аутентификация HTTP Basic или Digest, т. е. использование паролей), но рекомендуется применять TLS Client Certificate.

Методы с поддержкой состояний, включающие маркеры API или HTTP Cookie, не рекомендуются.

Предполагается, что установка и настройка Client Certificate выполняется как часть процесса продажи.

Использование сертификатов конечных объектов из общедоступных PKI (т. е. WebPKI) для идентификации регистратора является разумным и при повсеместном применении это позволит MASA идентифицировать клиентские регистраторы просто по полным доменным именами (Fully Qualified Domain Name или FQDN).

Использование записей DANE в подписанных DNSSEC зонах также позволяет применять FQDN для идентификации клиентских регистраторов.

Третьим (самым простым, но наименее гибким) механизмом является просто хранение в MASA сертификатов регистраторов, закреплённых в базе данных.

MASA без интеграции с цепочкой поставок может просто воспринимать регистраторы без аутентификации или вслепую на основе TOFU, как описано в параграфе 7.4.2. Доверие при первом использовании.

Этот документ не даёт конкретных рекомендаций по способу аутентификации регистраторов агентом MASA, поскольку возможны различные компромиссы в разных средах для различной продукции. Даже в сфере применимости ANIMA ACP имеются существенные различия между логистикой цепочек поставок простых устройств CPE за $100 и маршрутизаторов ядра стоимостью $100000 core.


5.5. Запрос регистратором ваучера у MASA

При получении регистратором voucher-request от заявителя он представляет свой voucher-request службе MASA через интерфейс HTTPS [RFC7231] с помощью HTTP POST с путём к операции /.well-known/brski/requestvoucher. Тип носителя для ваучера application/voucher-cms+json определён в [RFC8366] и применяется также в запросе ваучера регистратором. Это документ JSON, подписанный с использованием структуры CMS. Регистратор должен подписывать свой voucher-request.

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

Объект CMS в voucher-request включает некоторое число сертификатов, которые служат вводом для MASA, поскольку агент заполняет pinned-domain-cert. [RFC8366] обеспечивает достаточную гибкость в части содержимого pinned-domain-cert, поэтому агенту MASA требуется некий сигнал о типе сертификата, подходящем для заполнения поля. Это может варьироваться от сертификата конечного объекта, используемого регистратором, до всего частного сертификата Enterprise CA. Более конкретные сертификаты усиливают привязку ваучера к домену, а менее конкретные повышают гибкость представления домена сертификатами.

Регистратор, ищущий ваучер без nonce для последующего автономного (offline) применения, выигрывает от менее конкретного сертификата, поскольку он позволяет прикреплённому CA определить фактическую пару ключей, применяемую будущим регистратором.

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

Регистратору следует запрашивать наиболее конкретный ваучер, соответствующий режиму работы. Для этого при подготовке структуры CMS для подписанного voucher-request регистратору следует включать лишь сертификаты, являющиеся частью цепочки, желаемой для закрепления агентом MASA. Это может оказаться лишь одним сертификатом конечного объекта (с id-kp-cmcRA), используемым как сертификат сервера TLS, или целой цепочкой, включающей CA домена.

Регистратору следует включать поле заголовка Accept (параграф 5.3.2 в [RFC7231]) указывающее приемлемые типы носителя. Этому списку следует быть полным списком, представленным регистратору в исходном запросе заявителя (5.2. Запрос заявителем ваучера у регистратора), но может указываться лишь часть. Предполагается, что агент MASA достаточно гибок при восприятии.

Регистратор заполняет поля voucher-request, как указано ниже.

created-on

Регистратору следует указывать в этом поле дату и время формирования voucher-request. Поле обеспечивает дополнительные сведения для MASA.

nonce

Это значение копируется из voucher-request заявителя (при наличии) и может быть опущено в voucher-request регистратора (см. 3.1. Ваучеры без Nonce).

serial-number

Серийный номер заявителя, для которого регистратор хочет получить ваучер. Регистратор определяет это значение путём анализа аутентифицированного сертификата IDevID от заявителя (см. 2.3. Исходный идентификатор устройства). Регистратор должен убедиться, что найденное поле serial-number соответствует полю serial-number, представленному заявителем в его voucher-request. Это обеспечивает проверку пригодности, полезную для обнаружения ошибок и ведения журнала. Регистратору недопустимо просто копировать поле serial-number из voucher-request заявителя, поскольку оно не заверяется.

idevid-issuer

Значение Issuer из сертификата заявителя IDevID включается для однозначной интерпретации serial-number. В случае voucher-request без nonce требуется задать подходящее значения из того внешнего (out-of-band) же источника, что и serial-number.

prior-signed-voucher-request

Следует включать подписанный запрос voucher-request от заявителя в voucher-request регистратора. Подписанная CMS структура с кодированием base64 включается целиком для передачи в структуре JSON.

Агенту MASA можно представлять запрос voucher-request от регистратора без nonce. Это позволяет регистратору запросить ваучер отключённого (offline) заявителя или в предположении отсутствия связи с MASA во время развёртывания заявителя. В некоторых случаях регистратора должен знать соответствующие IDevID serialNumber и поле заголовка Accept из маркировки физического устройства или канала продаж (выходит за рамки документа).

Остальные поля voucher-request от регистратора могут быть опущены.

Поле proximity-registrar-cert недопустимо включать в voucher-request регистратора.

Примеры JSON для voucher-request от регистратора приведены в параграфе 3.3 (примеры 2 — 4).

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

5.5.1. Обновление агентом MASA просроченных ваучеров

Как описано в [RFC8366], ваучеры обычно имеют короткий срок действия, чтобы избежать проблем с отзывом. Если запрос для прежнего (просроченного) ваучера передан тем же регистратором (регистратором с тем же CA домена), запросу обновлённого ваучера следует предоставлять полномочия автоматически. Агент MASA имеет достаточно сведений для определения этого путём проверки запроса на предмет аутентификации регистратора и имеющегося журнала аудита (audit-log). Выпуск обновлённого ваучера записывается в журнал (5.6. MASA и отклик с ваучером регистратора).

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

5.5.2. Закрепление регистратора агентом MASA

Цепочка сертификатов извлекается из подписанного CMS контейнера регистратора. Эта цепочка может содержать от одного сертификата конечного объекта до всей цепочки сертификатов регистратора, включая сертификат доменного CA, как указано в параграфе 5.5. Запрос регистратором ваучера у MASA.

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

MASA может использовать сертификат из цепочки, наиболее удалённый от сертификата конечного объекта для регистратора, в соответствии с политикой MASA. Для MASA может быть задана локальная политика, в которой закрепляются только сертификаты конечных элементов. Это согласуется с [RFC8366]. Детали политики обычно зависят от уровня интеграции с цепочкой поставок и механизма, используемого регистратором для аутентификации. Политика будет также определять реакцию MASA на запросы ваучеров без nonce.

5.5.3. Проверка агентом MASA подписи в Voucher-Request

Как указано в параграфе 5.5.2, MASA определяет CA домена регистратора, используемый для проверки подписи CMS [RFC5652] в voucher-request.

При проверке подписи voucher-request предполагается обычная проверка отзывов PKIX. Сертификат CA может иметь точки распространения списков отозванных сертификатов (Certificate Revocation List или CRL) или сведения протокола состояния сертификатов (Online Certificate Status Protocol или OCSP) [RFC6960]. При наличии таких данных агент MASA должен иметь доступ к соответствующим серверам, относящимся к CA домена регистратора для проверки отзыва.

Предпочтительно использовать OCSP Stapling.

5.5.4. Проверка агентом MASA регистратора домена

Агент MASA должен проверить, что voucher-request от регистратора подписан тем. Это подтверждается проверкой наличия поля расширенного использования ключа id-kp-cmcRA (см. параграф 3.6.1 в EST [RFC7030]) в сертификате объекта, подписавшего voucher-request от регистратора. Это проверяет лишь то, что неаутентифицированный CA домена для стороны, подписавшей voucher-request, является регистратором. Выполнение такой проверки повышает ценность PKI домена, гарантируя администратору домена, что служба MASA будет учитывать лишь требования уполномоченных органов регистрации в домене.

Даже при аутентификации CA домена агентом MASA и надёжной интеграции с каналом продаж для понимания, кто является законным владельцем, указанная выше проверка id-kp-cmcRA предотвращает наличие ваучеров, выпущенных с произвольными сертификатами конечных элементов (такими как LDevID).

Значение id-kp-cmcRA является атрибутом расширенного использования ключа (Extended Key Usage или EKU). При установке какого-либо атрибута EKU сертификат должен иметь все связанные с этим атрибуты. Это значит, что сертификат регистратора должен иметь id-kp-clientAuth (для MASA) и id-kp-serverAuth (для заявителя).9

Другие случаи неправомерного выпуска ваучеров обнаруживает проверка журнала аудита (audit-log).

При представлении voucher-request без сертификата агент MASA должен аутентифицировать регистратор, как описано в EST (параграфы 3.2.3 и 3.3.2 в [RFC7030]), или путём проверки сертификата регистратора, использованного для подписи voucher-request, с применением настроенной привязки доверия. Любой из этих методов снижает риск атак DDoS и представляет аутентифицированное отождествление на вход интеграции с каналом продаж и проверки полномочий (детали этого выходят за рамки документа).

При использовании nonce проверку отождествления регистратора (через TLS Client Certificate или аутентификацию HTTP) можно опустить, если MASA знает, что политика устройства задаёт восприятие ваучеров лишь для аудита.

5.5.5. Проверка агентом MASA prior-signed-voucher-request от заявителя

MASA может проверить, что voucher-request от регистратора включает поле prior-signed-voucher-request. При наличии этого поля оно должно включать сертификат proximity-registrar-cert, соответствующий сертификату, использованному для voucher-request от регистратора. Кроме того, лист serial-number в voucher-request должен соответствовать serial-number от заявителя, который MASA извлекает из подписанного сертификата в prior-signed-voucher-request. Описанная выше проверка соответствия включает проверку наличия в proximity-registrar-cert отпечатка открытого ключа субъекта (Subject Public Key Info или SPKI) в цепочке сертификатов подписи CMS для voucher-request от регистратора. Это практически совпадает с проверкой закрепления (pin), описанной в параграфе 2.6 [RFC7469].

После успешной проверки MASA обновляет листья ваучера и утверждения audit-log утверждением proximity, как указано в параграфе 5.3 [RFC8366].

5.5.6. Обработка MASA Nonce

MASA не проверяет значение nonce. Если voucher-request от регистратора включает nonce и имеется prior-signed-voucher-request, агент MASA должен проверить согласованность nonce (напомним, что voucher-request может не включать nonce, см. 5.5. Запрос регистратором ваучера у MASA и 5.5.4. Проверка агентом MASA регистратора домена).

MASA помещает в audit-log проверенное значение nonce. Если ваучер не включает nonce, в audit-log помещается JSON-значение null.

5.6. MASA и отклик с ваучером регистратора

Отклик MASA с ваучером для регистратора пересылается без изменений заявителю, поэтому данный параграф применим для MASA и регистратора. Описанная сигнализация HTTP применима к откликам MASA и регистратора.

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

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

При успехе запроса voucher-request отклик сервера (агент MASA, отвечающий регистратору, или регистратор, отвечающий заявителю) должен содержать код HTTP 200. Сервер должен отвечать подходящим кодом HTTP 4xx или 5xx [RFC7230] при возникновении проблем. В этом случае данные отклика от MASA должны быть понятным человеку текстом (UTF-8) сообщения об ошибке, разъясняющим причины отклонения запроса.

Регистратор может отвечать кодом HTTP 202 (запрос принят для обработки, но она ещё не завершена), как описано в параграфе 4.2.3 EST [RFC7030], а клиент «должен ждать в течение по меньшей мере retry-after перед повторением запроса» (см. параграф 6.6.4 в [RFC7231]). Заявителю рекомендуется предоставлять локальный отклик (мигание светодиода и т. п.) в процессе ожидания, если для этого имеется механизм. Чтобы злонамеренный регистратор не мог существенно задержать начальную загрузку, заявитель должен ограничивать Retry-After значением 60 секунд. В идеале заявитель будет отслеживать значения поля Retry-After для любого числа остающихся регистраторов, но это требует наличия у него таблицы состояний. Вместо этого заявитель может игнорировать точные значения Retry-After в пользу одного жёстко заданного значения (регистратор, не способный завершить транзакцию за первые 60 секунд, получает другой шанс через 1 минуту). Заявителю следует быть готовым поддерживать состояние отклика 202 до 4 дней, что превышает длинные выходные, после чего передаётся отказ в попытке зачисления и заявитель возвращается в состояние Discovery. Это даёт время на передачу отклика оператору (человеку), который может принять решение о продолжении попыток или отказе от зачисления. Заявитель, повторяющий запрос после получения кода 202, должен передать тот же voucher-request. Недопустимо каждый раз подписывать новый voucher-request, в частности, недопустимо менять значение nonce.

Для предотвращения бесконечных циклов перенаправления, которые орнанизует вредоносный регистратор с целью помешать заявителю найти корректного регистратора, заявителю недопустимо следовать более, чем одному перенаправлею (код 3xx) на другой web-источник. EST поддерживает перенаправление, но требует ввода от пользователя, это изменение позволяет заявитель использовать 1 перенаправление без участия пользователя.

Отклик 403 (Forbidden — запрещено) подходит при некорректной подписи voucher-request, его устаревании или наличия у заявителя другого ваучера, который не может быть переопределён. Отклик 404 (Not Found — не найдено) подходит при запросе для устройства, неизвестного MASA. Отклик 406 (Not Acceptable — неприемлемо) подходит, если ваучер желаемого типа или использующий желаемый алгоритм (как указано в поле заголовка Accept и алгоритме, примененном в подписи) не может быть выдан, поскольку MASA знает, что заявитель не может обработать этот тип. Регистратору следует применять такой отклик, если он видит, что заявитель не приемлем для контроля учёта, MASA audit-log или по иным причина. Отклик 415 (Unsupported Media Type — неподдерживаемый тип носителя) подходит для запроса с непонятным voucher-request или значением Accept.

Формат отклика с ваучером указан в полях представленного заголовка Accept или основывается на предварительном знании агентом MASA подходящего для этого заявителя формата. В настоящее время определён лишь носитель application/voucher-cms+json [RFC8366]. Синтаксис ваучера подробно описан в [RFC8366]. Пример содержимого ваучера представлен на рисунке 14.

   {
     "ietf-voucher:voucher": {
       "nonce": "62a2e7693d82fcda2624de58fb6722e5",
       "assertion": "logged",
       "pinned-domain-cert": "base64encodedvalue==",
       "serial-number": "JADA123456789"
     }
   }

Рисунок 14. Пример ваучера.

Агент MASA заполняет поля ваучера, указанные ниже.

nonce

Значение nonce от заявителя при его доступности (см. 5.5.6. Обработка MASA Nonce).

assertion

Метод проверки взаимоотношений заявителя и регистратора (см. 5.5.5. Проверка агентом MASA prior-signed-voucher-request от заявителя).

pinned-domain-cert

Сертификат (см. 5.5.2. Закрепление регистратора агентом MASA). Пример приведён в Приложении C.2. Примеры процессов, где применяется сертификат конечного объекта.

serial-number

Серийный номер, представленный в voucher-request (см. также 5.5.5. Проверка агентом MASA prior-signed-voucher-request от заявителя).

domain-cert-revocation-checks

Устанавливается в соответствии с возможностями заявителя и [RFC8366]. MASA может установить в этом поле значение false, поскольку установка true потребует доступности сведений об отзыве заявителю, а этот документ не задаёт нормативных требования для интеграции с [RFC6961], параграфом 4.4.2.1 в [RFC8446] или эквивалентами.

expires-on

Устанавливается для ваучеров без nonce. MASA гарантирует, что срок действия ваучера согласуется с отзывом и проверками согласованности pinned-domain-cert, которые заявитель может выполнять (см. параграф 2.6.1). Нужно учитывать три момента: (a) настроенный срок действия ваучера в MASA, (b) срок завершения сертификата регистратора, (c) срок действия CRL. Значению поля expires-on следует быть раньше каждого из этих значений. Обычно (b) указывает достаточно далеко в будущее, но значение (c) обычно невелико (неделя или меньше). Рекомендуемый период для (a) составляет около 20 минут, поэтому он обычно определяет срок действия полученного ваучера. 20 минут достаточно для достижения заявителем состояния post-provisional, когда между ним и регистратором уже установлены отношения доверия. Последующие операции могут продолжать столько, сколько им требуется. Срок действия ваучера не влияет на срок действия отношений владения.

При каждой выдаче ваучера агент MASA должен обновлять журнал аудита, чтобы можно было создать отклик, как описано в параграфе 5.8.1. Требования к внутреннему состоянию для поддержки audit-log выходят за рамки документа.

5.6.1. Проверка ваучера заявителем

Заявитель должен проверять подпись ваучера, используя заданные изготовителем привязки доверия, связанные с MASA изготовителя (вероятно, они включены в прошивку заявителя). Управления заданными изготовителем привязками доверия выходит за рамки этого документа, а протокол не обновляет такие привязки.

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

Заявитель должен проверить данные nonce в ваучере. При наличии nonce в ваучере значение должно совпадать с nonce, представленным регистратору. Приемлемы ваучеры без nonce (в зависимости от локальной политики, см. 7.2. Снижение защиты заявителем).

Заявитель должен быть готов к синтаксическому анализу и отказу от отклика с ваучером, не содержащим поля pinned-domain-cert. Это указывает отказ при зачислении в домен и заявитель должен попытаться присоединиться через другой доступный Join Proxy.

Заявитель должен быть готов игнорировать непонятные ему дополнительные поля.

5.6.2. Аутентификация заявителем представленного соединения TLS

В соответствии с процессом из [RFC8366] заявителю следует считать открытый ключ из pinned-domain-cert единственной временной привязкой доверия. Затем заявитель оченивает цепочку сертификатов сервера TLS, полученную при организации соединения TLS с использованием этой привязки доверия. Возможно совпадение открытого ключа из pinned-domain-cert с открытым ключом в сертификате конечного объекта, представленном сервером TLS.

Если свидетельства регистратора не удаётся проверить с использованием привязки доверия pinned-domain-cert из ваучера, соединение TLS отбрасывается и заявитель отказывается от попыток начальной загрузки с найденным регистратором. Заявителю следует передать телеметрию статуса ваучера (см. ниже) до закрытия соединения TLS. Хаявитель должен попытаться зарегистрироваться с использованием других найденных посредников. Ему следует вернуться к тому же посреднику после неудачных попыток с другими proxy. Попытки следует предпринимать с использованием описанного выше таймера отсрочки. Попытки следует повторять, поскольку причиной отказа может быть временная несогласованность (несогласованный ключ регистратора или другая ошибка в конфигурации). Несогласованность может быть также результатом активной MITM-атаки на соединение EST.

Регистратор должен использовать сертификат, связанный с pinned-domain-cert, в качестве сертификата сервера TLS.

Проверка заявителем пути PKIX для срока действия сертификата регистратора описана в параграфе 2.6.1. После успешной проверки пути PKIX соединение TLS перестаёт быть временным.

Сертификат pinned-domain-cert может устанавливаться как привязка доверия для будущих операций, таких как зачисление (например, как рекомендовано в [RFC7030]), управление привязками доверия или raw-протоколы, которым не нужно полное управление ключами на основе PKI. Его можно применять для аутентификации любого динамически найденного сервера EST с расширением использования ключей id-kp-cmcRA, заданным в EST (параграф 3.6.1 в [RFC7030]), но для упрощения заявителю следует избегать дополнительных операций обнаружения. Взамен заявителю следует напрямую взаимодействовать с регистратором в качестве сервера EST. сертификат pinned-domain-cert не является откликом полного распространения сертификата CA, как описано в параграфе 4.1.3 [RFC7030], что служит дополнительным основанием продолжить операции управления ключами EST. После получения полного отклика с сертификатом CA этот сертификат будет более полномочным для домена, нежели ограниченный отклик pinned-domain-cert.

5.7. Телеметрия статуса заявителя BRSKI

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

Заявитель должен указывать свой статус в отношении ваучера, передавая регистратору сообщение о состоянии с использованием носителя типа application/json

Клиент передаёт серверу HTTP POST с URI .well-known/brski/voucher_status. Формат и семантика описаны ниже для версии 1. Поле версии включено для возможности внесения в будущем существенных изменений. Регистратору, получившему сообщение о состоянии с номером версии больше известного ему, следует сделать запись в журнале и подать сигнал человеку. Поле статуса указывает, приемлем ли ваучер. Допустимы логические значения, true указывает, что ваучер был воспринят.

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

Атрибут reason-context представляет собой произвольный объект JSON (буквальное значение или хэш) с дополнительными сведениями, относящимися к этому заявителю. Содержимое поля не стандартизуется.

Поля version и status должны присутствовать. Поле Reason следует включать, когда поле состояния имеет значение false. Поле Reason-Context является необязательным. При успехе (SUCCESS) поле Reason можно не включать.

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

   <CODE BEGINS> file "voucherstatus.cddl"
   voucherstatus-post = {
       "version": uint,
       "status": bool,
       ? "reason": text,
       ? "reason-context" : { $$arbitrary-map }
     }
   }
   <CODE ENDS>

Рисунок 15. CDDL для Voucher Status POST.

   {
       "version": 1,
       "status":false,
       "reason":"Informative human-readable message",
       "reason-context": { "additional" : "JSON" }
   }

Рисунок 16. Пример Status Telemetry.

Серверу следует отвечать с кодом HTTP 200, но можно просто отказать с кодом HTTP 404. Клиент игнорирует отклик. Серверу следует записывать данные телеметрии в системные журналы.

В запрос POST могут быть добавлены другие стандартные поля JSON (см. 8.5. Телеметрия состояния BRSKI у заявителя). Серверу, встретившему с неизвестное полем, следует записать это в журнал, игнорируя поле в остальном.

5.8. Запрос журнала аудита у регистратора

После получения телеметрии статуса заявителя (параграф 5.7) регистратору следует запросить MASA audit-log у сервера MASA с помощью HTTP POST с путём к операции /.well-known/brski/requestauditlog.

Регистратору следует включать в HTTP POST свой voucher-request, использованный при запросе ваучера (с тем же Content-Type) и передавать его с URI /requestauditlog. Поля idevid-issuer и serial-number указывают MASA запрашиваемый журнал, чтобы он мог быть подготовлен для отклика. Использование того же типа носителя и сообщения минимизирует операции с криптографией и сообщением, хотя создаёт дополнительный сетевой трафик. Надёжная реализация MASA может использовать внутреннее состояние для связывания этого запроса с исходным, который уже проверен, чтобы избежать дополнительной криптопроверки.

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

Агент MASA, получивший запрос для несуществующего устройства или для которого запрашивающий владелец никогда не был таковым, возвращает код HTTP 404 (Not found).

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

Вместо возврата журнала аудита в ответ на POST (с кодом 200) MASA может вернуть отклик 201 (Created — создано) ([RFC7231], параграф 6.3.2 и раздел 7.1) и URL для подготовленного (идемпотентного, поэтому кэшируемого) отклика с аудитом в поле заголовка Location.

Чтобы избежать перечисления журналов аудита устройств, агенту MASA, возвращающему URL, следует позаботиться о том, чтобы возвращаемый URL нельзя было угадать. В [W3C.capability-urls] приведены очень хорошие рекомендации для этого. Например, вместо возврата URL с номером базы данных, вроде https://example.com/auditlog/1234, или расширенным уникальным идентификатором (Extended Unique Identifier или EUI) устройства, таким как https://example.com/auditlog/10-00-00-11-22-33, MASA следует возвращать случайно сгенерированное значение (slug в терминологии web). Это значение сложит для нахождения соответствующей записи базы данных. Агент MASA, возвращающий код 200, может включать заголовок Location для дальнейшего использования регистратором.

5.8.1. Отклик MASA Audit-Log

Возвращается файл данных из журнала, состоящий из всех записей, связанных с устройством, заданным значением IDevID в запросе. Журнал аудита можно сократить путём удаления старых или повторяющихся записей, как указано ниже. Возвращаемые данные представлены в формате JSON [RFC8259], для Content-Type следует применять application/json.

Приведённый ниже код CDDL [RFC8610] показывает структуру формата JSON с откликом из журнала аудита.

   <CODE BEGINS> file "auditlog.cddl"
   audit-log-response = {
     "version": uint,
     "events": [ + event ]
     "truncation": {
       ? "nonced duplicates": uint,
       ? "nonceless duplicates": uint,
       ? "arbitrary": uint,
     }
   }

   event = {
     "date": text,
     "domainID": text,
     "nonce": text / null,
     "assertion": "verified" / "logged" / "proximity",
     ? "truncated": uint,
   }
   <CODE ENDS>

Рисунок 17. CDDL для отклика Audit-Log.

Ниже представлен пример отклика.

   {
     "version":"1",
     "events":[
       {
           "date":"2019-05-15T17:25:55.644-04:00",
           "domainID":"BduJhdHPpfhQLyponf48JzXSGZ8=",
           "nonce":"VOUFT-WwrEv0NuAQEHoV7Q",
           "assertion":"proximity",
           "truncated":"0"
       },
       {
           "date":"2017-05-15T17:25:55.644-04:00",
           "domainID":"BduJhdHPpfhQLyponf48JzXSGZ8=",
           "nonce":"f4G6Vi1t8nKo/FieCVgpBg==",
           "assertion":"proximity"
       }
     ],
       "truncation": {
           "nonced duplicates": "0",
           "nonceless duplicates": "1",
           "arbitrary": "2"
        }
   }

Рисунок 18. Пример отклика Audit-Log.

Поле domainID указывает двоичное значение SubjectKeyIdentifier, рассчитанное в соответствии с параграфом 5.8.2. Оно однократно кодируется в формате base64 для транспортировки в контейнере JSON. Значение даты (date) указывается в формате [RFC3339], соответствующем типичному использования JSON в JavaScript. Структуру отсечки можно не включать, если все значения равны 0. Предполагается, что все пропущенные значения счётчиков в этой структуре имеют значение 0. Значение nonce является строкой, представленной в voucher-request, и применяется в ваучере. Если в результирующем ваучере нет nonce, следует использовать значение null, а не пропускать строку. Хотя nonce часто создаётся как последовательность случайных байтов в кодировке base64, этого не следует предполагать.

Распространение большого журнала далеко не идеально. Структуру можно оптимизировать — записи с nonce или без nonce для одного domainID можно сократить, оставляя лишь самую свежую запись с nonce или без nonce для этого domainID. В случае отсечки значению event в ней следует указывать число пропущенных событий для данного domainID. Не следует дополнительно сокращать журнал, но могут быть рабочие ситуации, где поддержка полного журнала невозможна. В таких случаях размер журнала можно сократить произвольно, а для числа удалённых записей указать значение arbitrary (произвольное). Если счётчик отсечки превышает 1024, MASA может использовать это значение без дальнейшего инкрементирования.

Журнал, где дубликаты записей для одного домена были опущены (nonced duplicates и/или nonceless duplicates), может оставаться приемлемым для обоснованных решений. Журнал с произвольной (arbitrary) отсечкой менее приемлем, но лучше указать изготовителя, чем спрятать отсечки.

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

Этот документ задаёт простой формат журнала, предоставляемого службой MASA регистратору, который можно улучшить с помощью технологий распределенного согласования (consensus), объединяющих ваучеры с такими технологиями, как block-chain, хэш-деревья, оптимизированное ведение журналов. Это вопрос выходит за рамки документа, но остаётся желаемым для будущей работы. Поэтому регистраторам следует предвидеть новые типы откликов и следует давать операторам элементы управления для указания способов обработки неизвестных откликов.

5.8.2. Расчёт domainID

Поле domainID — это двоичное значение (BIT STRING), однозначно указывающие регистратор по pinned-domain-cert. Если сертификат pinned-domain-cert включает SubjectKeyIdentifier (параграф 4.2.1.2 в [RFC5280]), это значение используется в качестве domainID, в противном случае применяется SPKI Fingerprint, как указано в параграфе 2.4 [RFC7469]. Это значение должны рассчитывать как MASA (для audit-log), так и регистратор (для распознавания себя в audit-log). Параграф 4.2.1.2 [RFC5280] не требует присутствия расширения SubjectKeyIdentifier в сертификатах не от CA. В (самоподписанный) сертификат регистратора рекомендуется всегда включать SubjectKeyIdentifier для использования в качестве domainID.

Значение domainID определяется из цепочки сертификатов, связанной с pinned-domain-cert, и применяется для обновления audit-log.

5.8.3. Проверка журнала аудита у регистратора

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

Хотя audit-log предоставляет список выпущенных MASA ваучеров, они выдаются в ответ на voucher-requests и именно содержимое voucher-request определяет значимость записей в журнале аудита.

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

date

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

domainID

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

nonce

Записи без nonce говорят, что указанный в журнале domainID теоретически может инициировать сброс заявителя, а затем принять на себя управления, используя имеющийся ваучер без nonce.

assertion

Лист подтверждения в ваучере и журнале аудита указывает причину выдачи ваучера агентом MASA. Запись verified (подтверждено) указывает, что агент MASA выдал ваучер по положительному результату проверки владения. Однако эта запись не показывает, был ли заявитель развернут в прежнем домене. Запись logged (зарегистрировано) говорит регистратору, что прежние ваучеры были выданы с минимальной проверкой. Запись proximity (близость) гарантирует регистратору, что заявитель действительно взаимодействовал с прежним доменом, что подтверждает внедрение заявителя в прежнем домене.

Относительно простая политика состоит в том, чтобы принять список известных (внутренних или внешних) domainID и требовать наличия nonce во всех ваучерах. Другой вариант требует, чтобы все ваучеры без nonce относились в некому подмножеству domainID (например, только внутренние). При нарушении правил достаточно просто отозвать все локально выданные свидетельства для соответствующего заявителя или отклонить пересылку ваучера. После этого регистратор должен отклонять любые действия EST и следует также уведомить человека через журнал. Регистратор можно настроить на игнорирование (т. е. переопределение указанного выше правила) истории устройства, но рекомендуется делать это лишь при наличии аппаратной поддержки, т. е. модуля доверенной платформы (Trusted Platform Module10 или TPM) оценки конечных точек сети (Network Endpoint Assessment или NEA) [RFC5209].

5.9. Интеграция EST с начальной загрузкой

Заявителю следует выполнить операции BRSKI с операциями зачисления EST, включая запросы сертификата CA, атрибутов CSR, сертификата клиента, генерации ключей на сервере и т. п. Это сравнительно бесшовная интеграция, поскольку вызовы BRSKI API обеспечивают автоматизированный вариант начальной загрузки, описанной в [RFC7030]. Как отмечено выше, использование сохраняющегося соединения HTTP упрощает конечный автомат заявителя.

Хотя EST позволяет клиентам получать несколько сертификатов, отправляя запросы на подписание сертификата (Certificate Signing Request или CSR), BRSKI не поддерживает этот механизм напрямую. Это связано с тем, что заявители BRSKI должны использовать запрос атрибутов CSR (параграф 4.5 в [RFC7030]). Регистратор должен проверить CSR на соответствие ожидаемым атрибутам. Это означает, что запросы клиента «будут выглядеть одинаково» и, следовательно, приведут к выпуску одного логического сертификата даже при нескольких запросах от клиента. Регистраторы могут применять более сложную логику, но это выходит за рамки документа. BRSKI не указывает каких либо расширений или ограничений для этой возможности.

5.9.1. Распространение EST для сертификатов CA

Заявителю следует запрашивать полное распространение EST для сообщений с сертификатами CA, см. параграф 4.1 в [RFC7030]. Это обеспечивает наличие у заявителя полного набора текущих сертификатов CA в дополнение к pinned-domain-cert (ограничения, присущие использованию одного сертификата вместо полного отклика с сертификатами CA, рассмотрены в параграфе 5.6.2). Хотя эти ограничения допустимы при исходной начальной загрузке, они не подходят для текущей проверки сертификата конечного объекта PKIX.

5.9.2. Атрибуты CSR для EST

Автоматизированная начальная загрузка происходит без настройки заявителя локальным администратором. В некоторых развёртываниях вполне вероятно создание заявителем запроса, содержащего лишь известное ему отождествление (по сути, X.509 IDevID) и получение в конечном итоге сертификата со специфическими для домена сведениями об отождествлении. Концептуально CA имеет полный контроль над всеми полями, выдаваемыми в сертификате конечного объекта, но на деле это сложно с точки зрения текущего состояния внедрения PKI CA, где CSR представляется в CA через ряд нестандартных протоколов. Даже при использовании стандартизованных протоколов может быть проблематично ожидать, что зависящие от службы поля сертификата могут быть созданы CA, который вероятно управляется группой, не имеющей представления об используемых сетевых протоколах и службах. Например, CA может поддерживаться сторонней организацией.

Для снижения этих эксплуатационных трудностей заявитель должен запросить атрибуты CSR для EST у сервера EST, а тот должен иметь возможность ответить атрибутами, требуемыми для использования сертификата в предполагаемых протоколах (службах). Такой подход допускает минимальную интеграцию с CA, а локальная инфраструктура (сервер EST) сообщает заявителю нужные поля для включения в генерируемый запрос CSR (такие как rfc822Name). Это позволяет автоматизировать начальную загрузку в самых разных средах.

В средах, использующих зачисленный BRSKI сертификат для аутентификации ACP, атрибуты CSR для EST должны включать поля сведений о домена ACP, заданные в параграфе 6.2.2 [RFC8994].

Регистратор должен также подтвердить, что формат результирующего CSR соответствует указанному, до отправки запроса CA. Если регистратор взаимодействует с CA по протоколу, такому как управление сертификатами через CMS (Certificate Management over CMS или CMC), который предоставляет механизмы переопределения атрибутов CSR, эти механизмы могут использоваться, если клиент игнорирует рекомендации для атрибутов CSR.

5.9.3. Запрос сертификата клиента EST

Заявитель должен запрашивать новый сертификат клиента (см. параграф 4.2 в [RFC7030]).

5.9.4. Телеметрия статуса зачисления

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

Клиент должен передать регистратору сведения о статусе своего зачисления. Это делается с использованием в HTTP POST словаря JSON с атрибутами, описанными ниже для новой конечной точки EST, по ссылке /.well-known/brski/enrollstatus.

При индикации успешного зачисления клиенту следует сначала заново организовать сессию EST TLS, используя вновь полученные свидетельства. TLS 1.3 поддерживает это по основному каналы (in-band), а TLS 1.2 не поддерживает. Поэтому клиенту следует закрыть имеющееся соединение TLS и начать новое с тем же Join Proxy. При отказе в зачислении клиент должен передать сведения телеметрии через соединение TLS, которое применялось при попытке зачисления, со строкой Reason, указывающей причину отказа при последней попытке зачисления (для таких случаев соединение TLS является наиболее надёжным способом сопоставить сведения сервера с клиентскими).

Поля version и status должны присутствовать, поле Reason следует включать при значении false в поле status. При успехе (SUCCESS) поле Reason можно не включать.

Атрибут reason-context является произвольным объектом JSON (буквальное значение или хэш) с дополнительными сведениями об отказе при зачислении этого заявителя. Содержимое этого поля не стандартизуется. Это представлено групповым сокетом $$arbitrary-map в CDDL.

   <CODE BEGINS> file "enrollstatus.cddl"
   enrollstatus-post = {
       "version": uint,
       "status": bool,
       ? "reason": text,
       ? "reason-context" : { $$arbitrary-map }
     }
   }
   <CODE ENDS>

Рисунок 19. CDDL для Enrollment Status POST

An example status report can be seen below. It is sent with the media type: application/json

   {
       "version": 1,
       "status":true,
       "reason":"Informative human readable message",
       "reason-context": { "additional" : "JSON" }
   }

Рисунок 20. Пример Enrollment Status POST.

Серверу следует отвечать кодом HTTP 200, но можно просто отказать с кодом HTTP 404. В своих журналах сервер должен оставить запись, если это сообщение было получено в сессии TLS с соответствующим сертификатом клиента.

5.9.5. Множество сертификатов

Заявители, которым нужно несколько сертификатов, могут организовать прямые соединения EST с регистратором.

5.9.6. EST через CoAP

Этот документ описывает расширение EST для инфраструктуры удалённых ключей при начальной загрузке. Начальная загрузка актуальная также для обсуждения зачисления CoAP. Определение EST и BRSKI через CoAP не рассматривается в этом документе, кроме обеспечения proxy-поддержки для операций CoAP. Предполагается, что определение сопоставлений CoAP будет дано в последующих документах, таких как [ACE-COAP-EST], а отображения CoAP для BRSKI будут описана там же или в будущих работах.

6. Разъяснение по транспортному кодированию

[RFC7030] определяет конечные точки для включения заголовка Content-Transfer-Encoding, а для данных (payload) используется представление DER с кодированием base64 [RFC4648].

При использовании с BRSKI исходные конечные точки EST сохраняют кодирование base64 [RFC7030] (как разъяснено в [RFC8951]), но новые конечные точки BRSKI, передающие и принимающие двоичные артефакты (в частности, /.well-known/brski/requestvoucher), остаются бинарными, т. е. кодирование не применяется.

В контексте BRSKI поле заголовка EST Content-Transfer-Encoding следует игнорировать, если оно имеется. Включать это поле не требуется.

7. Режимы работы с пониженной защитой

Общим требованием начальной загрузки является поддержка менее защищённых режимов работы для конкретных случаев. В этом разделе предлагается ряд механизмов, меняющих гарантии защиты BRSKI для разных архитектур внедрения и смягчения проблем управления жизненным циклом, отмеченных в разделе 10. Они представлены здесь в качестве ненормативного руководства для будущей стандартизации. А разделе 9 приведены заявления о применимости стандартизации для ANIMA ACP. Другие пользователи могут ожидать, что подмножества этих механизмов могут быть профилированы в заявлениях о применимости, подобных приведённым в разделе 9.

Этот раздел считается ненормативным в рамках протокола. Использование предложенных здесь механизмов должно быть детализовано в конкретных профилях BRSKI, как в разделе 9. Применимость к ACP.

7.1. Модель доверия

+---------+       +----------+    +------------+     +------------+
|Заявитель|       |Посредник |    |Регистратор |     |Служба      |
|         |       |присоедин.|    |домена      |     |изготовителя|
|         |       |          |    |            |     |(Internet)  |
+---------+       +----------+    +------------+     +------------+

Рисунок 21. Элементы модели доверия BRSKI.


В этом параграфе объяснены отношения доверия, подробно описанные в параграфе 2.4. Поток протокола.

Pledge — заявитель

Заявитель может быть скомпрометрирован или на него может быть нацелена атака вредоносного ПО. Объект считается доверенным лишь для впечатывания (imprint) с использованием защищённых методов, описанных в этом документе. Рекомендуются дополнительные методы оценки конечных точек, но это выходит за рамки документа.

Join Proxy — посредник присоединения

Обеспечивает функции посредника, но не участвует в вопросах безопасности.

Registrar — регистратор

Регистратор принимает все решения при взаимодействии с MASA. Для ваучеров аудита владения (Ownership Audit Voucher, [RFC8366] регистратору предоставляется возможность воспринимать решения MASA.

Vendor Service, MASA — служба производителя, агент MASA

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

Vendor Service, Ownership Validation — служба изготовителя, проверка владения

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

7.2. Снижение защиты заявителем

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

  1. Заявитель должен воспринимать ваучеры без nonce. Это позволяет использовать вариант, где регистратор не может связаться с MASA во время развёртывания. Ведение журнала и сроки действия учитывают соображения безопасности, связанные с поддержкой этих вариантов.

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

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

  4. Последовательная консоль может включать такие команды, как est-enroll [2001:db8:0:1]:443, которые запускают процесс EST с момента после проверки ваучера. Этому процессу следует включать проверку сертификата сервера с использованием экранного отпечатка (on-screen fingerprint).

Рекомендуется разрешать доверие при первом использовании или иной метод пропуска проверки ваучера (включая использование последовательной консоли) лишь при поддержке аппаратной оценки конечных точек (NEA) [RFC5209]. Эта рекомендация гарантирует, что мониторинг сети домена сможет обнаружить использованием процедур автономного или аварийного развёртывания, когда основанная на ваучерах начальная загрузка не применяется.

7.3. Снижение защиты регистратором

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

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

  2. Регистратор может воспринимать устройства, которые заявили уникальный идентификатор без проверки подлинности заявленного отождествления. Это может происходить, когда у заявителя нет установленного на производстве свидетельства X.509 IDevID. Новые объекты без свидетельства X.509 IDevID могут формировать запрос в соответствии с параграфом 5.2, используя формат из параграфа 5.5, чтобы убедиться, что сведения о серийном номере представлены регистратору (включая значение IDevID AuthorityKeyIdentifier, которое статически настраивается у заявителя). Заявитель может отказаться от предъявления клиентского сертификата TLS (поскольку тот недоступен). Заявителю следует поддерживать аутентификацию на основе HTTP или TLS без сертификата, как описано в параграфе 3.3.2 EST [RFC7030]. Регистратору недопустимо воспринимать новые неаутентифицированные объекты, пока это на задал администратор, который подтвердил, что лишь ожидаемые проверенные объекты могут взаимодействовать с регистратором (предположительно через физически защищённый периметр).

  3. Регистратор может представить службе MASA voucher-request без nonce. Полученные ваучеры могут сохраняться регистратором, пока они нужны для операций начальной загрузке. Это применяется в случаях, когда целевая сеть защищена воздушным зазором (изолирована) и поэтому не может взаимодействовать со службой MASA в процессе развёртывания заявителя.

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

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

7.4. Снижение защиты MASA

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

7.4.1. Выпуск ваучеров без nonce

MASA может не включать nonce в ваучер и/или не требовать его наличия в voucher-request. Это ведёт к распространению ваучеров, которые могут иметь неограниченный срок действия, и по сути делает указанный домен доверенным объектом для заявителя при всех последующих попытках начальной загрузки. Журнальные записи фиксируют выпуск ваучеров без nonce, что позволяет регистратору принять соответствующее решение по защите при зачислении заявителя в домен. Ваучеры без nonce полезны для поддержки вариантов использования, где регистратор может быть недоступен в процессе фактической начальной загрузки.

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

Более типичным для ваучера без nonce является использование при автономном (offline) включении, когда невозможно передать новый voucher-request агенту MASA. Использование долгосрочного ваучера также избавляет от необходимости заботиться о доступности MASA на много дней в будущее. Поэтому ваучеры без nonce не имеют срока действия.

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

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

7.4.2. Доверие при первом использовании

MASA может не проверять владение перед отправкой отклика с ваучером. Предполагается, что это будет обычная рабочая модель, поскольку это позволяет изготовителям, предоставляющим услуги MASA, обойтись без отслеживания владения в процессе поставки и через цепочки поставок, а также обойтись очень малыми издержками, связанными с услугами MASA. Регистратор использует сведения из журнала аудита как стратегию всесторонней защиты, чтобы гарантировать, что это не произойдёт неожиданно (например, при покупке нового оборудования регистратор выдаст ошибку, если не будут получены сведения из журнала аудита). Агенту MASA следует проверять сведения prior-signed-voucher-request для заявителей, которые поддерживают такую функциональность. Это обеспечивает проверку подтверждения близости, которая снижает потребность в проверке владения. Подтверждение близости основано на допущении размещения заявителя и посредника присоединения на одном локальном канале.

Агент MASA, использующий TOFU для отождествления регистратора, может захотеть аннотировать источник соединения по адресу IP или сетевому блоку (netblock) и ограничить будущее использование этого отождествления из других мест. Агенту MASA, который делает это, следует позаботиться о том, чтобы не создавать для себя неприятные ситуации, когда клиент имеет несколько регистраторов или использует исходящие соединения IPv4-to-IPv4 NAT (NAT44), которые часто меняются.

7.4.3. Обновление или расширение точек доверия ваучера

В этом параграфе рассматриваются две проблемы — недоступность MASA из-за проблем в бизнесе и отказ MASA взаимодействовать со вторичной продажей.

Изготовитель может предложить механизм управления, позволяющий расширить список привязок доверия для проверки ваучеров. В [YANG-KEYSTORE] описан интерфейс, который можно реализовать с использованием YANG. Практически любой механизм настройки, используемый сегодня, можно расширить для обеспечения требуемого обновления. Производитель может даже установить привязки доверия доменного CA, полученные на этапе EST cacerts в качестве привязок для проверки сертификатов. Потребуются некоторые дополнительные сигналы для чёткой идентификации ключей с полномочиями проверки ваучеров среди подписанных доменным CA. Это дело будущего.

При таком изменении списка привязок доверия ваучеры может выпускать другой агент MASA, которым может быть предыдущий владелец (продавец) или иное доверенное лицо, посредничающее при продаже. Если это третья сторона, продавец должен предпринять действия по внедрению конфигурации этой стороны на устройство до отсоединения. Третья сторона (например, оптовый продавец использованного оборудования) может использовать механизм, описанный в параграфе 7.2, для получения контроля над устройством после его физического получения. Это позволит третьей стороне действовать как MASA при будущих подключениях (onboarding). Сертификат IDevID заменить нельзя, поэтому регистратор нового владельца должен будет поддерживать переопределение MASA URL.

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

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

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

8. Взаимодействие с IANA

В соответствии с этим документом агентство IANA выполнило указанные ниже действия.

8.1. Реестр IETF XML

Этот документ вносит URI в реестр IETF XML Registry [RFC3688].

   URI:  urn:ietf:params:xml:ns:yang:ietf-voucher-request
   Registrant Contact:  The ANIMA WG of the IETF.
   XML:  запрошенный URI является пространством имён XML.

8.2. Реестр YANG Module Names

Этот документ регистрирует модуль YANG в реестре YANG Module Names [RFC6020].

   Name:  ietf-voucher-request
   Namespace:  urn:ietf:params:xml:ns:yang:ietf-voucher-request
   Prefix:  vch
   Reference:  RFC 8995

8.3. Общеизвестные BRSKI

8.3.1. Регистрация BRSKI .well-known

Этот документ регистрирует в реестре Well-Known URIs (https://www.iana.org/assignments/well-known-uris/) имя brski с шаблоном из [RFC8615]

   URI Suffix:  brski
   Change Controller:  IETF

Агентство IANA изменило регистрацию est, которая сейчас включает лишь [RFC7030] и не указывает этот документ. В предшествующих черновых версиях этого документа использовалось /.well-known/est вместо /.well-known/brski.

8.3.2. Реестр BRSKI .well-known

Агентство IANA создало реестр BRSKI Well-Known URIs. Записи реестра состоят из 3 полей: URI, Description (описание), Reference (документ). Новые записи добавляются в реестр по процедуре Specification Required [RFC8126]. Исходное содержимое реестра представлено в таблице 1.

Таблица 1. Общеизвестные BRSKI URI.

 

URI

Описание

Документ

requestvoucher

От заявителя к регистратору и от регистратора к MASA

RFC 8995

voucher_status

От заявителя к регистратору

RFC 8995

requestauditlog

От регистратора к MASA

RFC 8995

enrollstatus

От заявителя к регистратору

RFC 8995

 

8.4. Реестр PKIX

Агентство IANA зарегистрировало значение id-mod-MASAURLExtn2016(96) из реестра pkix(7) id-mod(0).

Агентство IANA выделило реестра id-pe (Structure of Management Information (SMI) Security for PKIX Certificate Extension) значение 32 для id-pe-masa-url, приводящее к OID 1.3.6.1.5.5.7.1.32.

8.5. Телеметрия состояния BRSKI у заявителя

Агентство IANA создало реестр BRSKI Parameters с таблицей Pledge BRSKI Status Telemetry Attributes. Новые элементы добавляются в реестр по процедуре Specification Required. Исходная таблица в соответствии с этим документом (5.7. Телеметрия статуса заявителя BRSKI) содержит поля:

  • version;
  • status;
  • reason;
  • reason-context.

8.6. Имена DNS для служб

Агентство IANA зарегистрировало указанные ниже имена служб.

   Service Name:  brski-proxy
   Transport Protocol(s):  tcp
   Assignee:  IESG <iesg@ietf.org> 
   Contact:  IESG <iesg@ietf.org> 
   Description: The Bootstrapping Remote Secure Key Infrastructure Proxy
   Reference:  RFC 8995

   Service Name:  brski-registrar
   Transport Protocol(s):  tcp
   Assignee:  IESG <iesg@ietf.org> 
   Contact:  IESG <iesg@ietf.org> 
   Description: The Bootstrapping Remote Secure Key Infrastructure
      Registrar
   Reference:  RFC 8995

8.7. Имена целей GRASP

Агентство IANA зарегистрировало значение AN_Proxy в таблице GRASP Objective Names реестра GRASP Parameter. Спецификация для этого значения приведена в параграфе 4.1.1. Анонсирование Proxy GRASP. Зарегистрировано также значение AN_join_registrar в таблице GRASP Objective Names реестра GRASP Parameter. Спецификация значения приведена в параграфе 4.3. Обнаружение посредника и связь с регистратором.

9. Применимость к ACP

Этот документ предлагает решение для защищённой начальной загрузки как определено в Using an Autonomic Control Plane for Stable Connectivity of Network Operations, Administration, and Maintenance (OAM) [RFC8368], A Reference Model for Autonomic Networking [RFC8993], а также в параграфах 3.2 (Secure Bootstrap over an Unconfigured Network) и 6.2 (ACP Domain, Certificate, and Network) документа An Autonomic Control Plane (ACP) [RFC8994].

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

Плоскость управления ACP, загружаемая протоколом BRSKI, обычно применяется у средних и крупных провайдеров Internet. Аналогичные предприятия, имеющие значительные возможности связности L3, также получат существенные преимущества, особенно при наличии множества сайтов. Не исключаются и сети, построенные в основном на соединениях L2, но связи, создаваемые и поддерживаемые ACP в этом случае не будут отражать топологию, пока все устройства не участвуют в ACP. В ACP посредник присоединения (Join Proxy) является близким, поскольку взаимодействие между заявителем и Join Proxy осуществляется исключительно по адресам IPv6 link-local. Близость Join Proxy к регистратору последний проверяет с использованием адресов ANI ACP IPv6 ULA. Эти адреса не маршрутизируются через Internet, поэтому при корректной работе Join Proxy заявление о близости соблюдается. Для других применений BRSKI потребуется аналогичный анализ, если они применяют заявления о близости.

Как указано в уставе ANIMA, эта работа «сосредоточена на профессионально управляемых сетях». В таких сетях имеются операторы, которые могут устанавливать, настраивать и применять функции регистратора. Оператор принимает решения о покупке и знает о изготовителях, чьё оборудования он ожидает увидеть в сети. Такой оператор также может выполнять начальную загрузку устройств с использованием последовательной консоли. Автоматический (zero-touch) механизм, описанный здесь и в документе ACP [RFC8994] обеспечивает высокую эффективность, в частности снижает необходимость отправки квалифицированных специалистов для настройки оборудования.

По мере развития технологии становилось ясно, что не всегда удаётся выполнить действия автоматически и иной раз требуется привлекать человека, для чего в параграфе 7.2 представлены некоторые механизмы. Изготовитель должен предоставить хотя бы один из механизмов настройки «в одно касание» (one-touch), позволяющих выполнить зачисление при недоступности какого-либо сервера изготовителя (такого как MASA).

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

9.1. Эксплуатационные требования

В этом параграфе собраны рабочие требования на основе трёх ролей в BRSKI — MASA, владелец (домена) и устройство. Следует отметить, что изготовитель может играть две роли, он создаёт программы/микрокод для устройства, а также может быть оператором MASA.

Требования в этом разделе представлены с использованием уровней BCP 14 [RFC2119] [RFC8174]. Здесь нет новых нормативных требований, просто приведён обзор некоторых аспектов с учётом ролей. Это применимо также к варианту применения ANIMA ACP. Для иных применения могут быть похожие, но отличающиеся требования.

9.1.1. Операционные требования к MASA

Изготовитель должен обеспечить доступность сетевой (online) службы, называемой MASA. Служба должна быть доступна по URL, закодированному в расширении сертификата IDevID, описанного в параграфе 2.3.2. Расширение MASA URI. Эта служба должна иметь доступ к секретному ключу, которым подписаны артефакты ваучеров [RFC8366]. Открытый ключ, сертификат или цепочка сертификатов должны встраиваться в устройство как часть прошивки (микрокода). Изготовителю рекомендуется организовать депонирование ключей подписи в соответствии обычной практикой депонирования исходного кода программ [softwareescrow].

MASA воспринимает voucher-request от владельцев доменов в соответствии с операционной практикой, подходящей для устройства. Это может варьироваться от восприятия запросов от любого владельца домена (обслуживание в порядке поступления запросов в стиле TOFU) до полной интеграции с каналами продаж, когда владелец домена должен быть точно идентифицирован закреплённым сертификатом TLS или процессом аутентификации HTTP. MASA создаёт артефакты подписанных ваучеров в соответствии со своими внутренними правилами.

Агент MASA должен вести журнал аудита для доступных устройств. Журнал позволяет простое кэширование и MASA может счесть полезным поместить его содержимое в сеть CDN11.

9.1.2. Операционные требования к владельцу домена

Владелец домена должен поддерживать сервер EST [RFC7030] с описанными в этом документе расширениями (JRC или регистратор). Этот сервер JRC/EST должен анонсировать себя, используя GRASP в ACP. Сервер EST обычно размещается в сетевом операционном центре (Network Operations Center) организации. Владелец домена может поддерживать внутренний CA отдельно от EST или может объединить все действия в одном устройстве. Выбор архитектуры зависит от масштаба организации и требований к отказоустойчивости. Можно анонсировать в ACP несколько экземпляров JRC из разных мест для обеспечения требуемого резервирования.

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

Владельцу домена следует использовать полученную в результате наложенную сеть ACP для управления устройствами взамен унаследованных автономных (out-of-band) механизмов.

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

Организация должна принять подходящие меры предосторожности против потери доступа к секретному ключу CA. Для этого подходят аппаратные модули защиты и/или разделение секретов.

9.1.3. Операционные требования к устройству

Устройства должны поставляться со встроенными привязками доверия, позволяющими проверить ваучеры от MASA. Устройства должны поставляться с (уникальными) сертификатами IDevID, включающими серийный номер и расширение MASA URL.

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

Предполагается, что после проверки владельца домена по ваучеру устройства будут зачисляться в домен с использованием EST. Ожидается, что после этого устройства сформируют ACP, используя IPsec с адресами IPv6 link-local,как описано в [RFC8994]. После зачисления устройства ему следует прослушивать адрес JRC, применяя GRASP, а также следует включить себя как Join Proxy и анонсировать это на всех каналах (интерфейсах) через GRASP DULL. Предполагается, что устройства обновят свои сертификаты до завершения срока их действия.

10. Вопросы приватности

10.1. Журнал аудита MASA

Журнал аудита MASA включает domainID каждого домена, для для которого был выдан ваучер. Эти сведения тесно связаны с фактическим отождествлением домена. MASA может потребоваться дополнительная защита от атак на службы (Denial-of-Service, параграф 11.1), которая может включать сбор не указанных здесь сведений. Это может дать службе MASA сведения для подробного представления о имеющихся в домене устройствах.

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

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

10.2. Что раскрывает BRSKI-EST

На предварительном этапе соединения BRSKI-EST между заявителем и регистратором каждая сторона раскрывает другой свои сертификаты. Для заявителя это включает атрибут serialNumber, MASA URL, и отождествление, подписанное сертификатом IDevID.

TLS 1.2 раскрывает отождествления сертификатов находящимся в пути наблюдателям, включая Join Proxy. TLS 1.3 раскрывает отождествления сертификатов лишь конечным элементам, но соединение является предварительным и злоумышленник на пути (MITM) может видеть сертификаты. Это видят также регистраторы, которые видны заявителю, но не входят в предполагаемый домен.

Сертификат регистратора достаточно условен с точки зрения протокола BRSKI. Поскольку проверка [RFC6125] не предполагается, для содержимого легко организовать псевдоминимизацию. Любое устройство, способное видеть Join Proxy, способно соединиться с регистратором и получить отождествление соответствующей сети. Даже при псевдоминимизации сертификата можно сопоставить различные соединения в разных местах, относящиеся к одному объекту. Возникновение существенных проблем с приватностью маловероятно в ANIMA ACP с BRSKI, но может вызывать беспокойство у других пользователей BRSKI.

Сертификат заявителя может раскрываться враждебному Join Proxy, организовавшему MITM-атаку на предварительное соединение TLS. Такой злоумышленник может раскрыть отождествление заявителя третьей стороне.

Было бы полезно исследовать механизм многоэтапного согласования ключей с многосторонней аутентификацией, включающий какое-либо нераскрываемое (zero-knowledge) подтверждение. В идеале такой механизм позволит избежать раскрытия отождествлений, пока заявитель, регистратор и MASA не согласуют транзакцию. Такой механизм должен обнаруживать местоположение MASA, не имея отождествления заявителя и MASA. Эта часть проблемы может оказаться неразрешимой.

10.3. Что BRSKI-MASA раскрывает изготовителю

В устройствах, ориентированных на потребителя механизм «звонков домой» (call-home) для IoT вызывает серьёзные проблемы приватности (см. примеры в [livingwithIoT] и [IoTstrangeThings]). Применение BRSKI ACP нацелено не на индивидуальное использование устройств IoT, а на создание сетей предприятий и ISP, работающих без участия человека (zero-touch), где call-home создаёт новый класс вопросов приватности и управления жизненным циклом.

Нужно повторить, что механизм BRSKI-MASA срабатывает лишь 1 раз в процессе ввода устройства в эксплуатацию. Механизм чётко определён и, хотя и применяет шифрование TLS, теоретически может быть доступен для аудита. Соединения не создаётся при включении устройства или при обычном перезапуске (возможен, но крайне маловероятен, сброс устройства к заводским установкам при исключительной ситуации в процессе обновления прошивки, после которого потребуется заново выполнять зачисление устройства с организацией нового соединения).

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

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

Обмен BRSKI-MASA раскрывает изготовителю указанные ниже сведения.

  • Отождествление зачисляемого устройства раскрывается передачей подписанного voucher-request с серийным номером. Изготовитель обычно может связать серийный номер с моделью устройства.

  • Отождествление владельца домена через привязки доверия. Однако это не глобальное имя, связанное с PKI в WebPKI, и может быть псевдонимом. При интеграции с каналами продаж MASA аутентифицируется владельцем домена через прикрепленный сертификат или иной метод аутентификации HTTP (параграф 5.5.4).

  • Время активации устройства.

  • IP-адрес регистратора владельца домена. Для ISP и предприятий адрес IP чётко указывает геолокацию владельца. Никакие расширения приватности адресов IP [RFC8981] не могут решить эту проблему, ведь поиск с помощью whois чётко указывает ISP или предприятие по старшим битам адреса. Пассивный атакующий, наблюдающий за соединением, может понять, что данное предприятие или ISP является клиентом конкретного производителя оборудования. Модели зачисляемых в домен устройств не раскрываются.

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

Изготовитель знает IP-адрес регистратора, но не может видеть IP-адрес самого устройства. Изготовитель не может отследить для устройства конкретное физическое или сетевое местоположение и знает лишь размещение регистратора (вероятно в центральном офисе предприятия или ISP).

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

Ситуация не улучшается, если предприятие или /ISP использует службу анонимизации, такую как Tor [Dingledine], поскольку соединение TLS 1.2 раскроет применяемый ClientCertificate, чётко указывающий предприятие или ISP. TLS 1.3 в этом отношении лучше, но активный атакующий всё-таки может раскрыть участников, организовав MITM-атаку на первую попытку (прерывание путём сброса TCP — RST), а затем пропустив последующее соединение через себя.

Изготовитель может смешивать трафик BRSKI-MASA с остальным трафиком на своём сайте, разместив MASA за тем же балансировщиком нагрузки (или их набором), что и обычный маркетинговый сайт. Это имеет смысл с точки зрения прямого планирования пропускной способности, поскольку может применяться общий набор услуг (и средств смягчения DDoS-атак). Поскольку соединения BRSKI-MASA включают обмен TLS ClientCertificate, это легко отслеживается в TLS 1.2, а анализ трафика позволяет раскрыть сведения даже в TLS 1.3. Однако это не делает такой подход неактуальным. Могут быть и другие организационные причины отделять маркетинговый сайт (который обычно часто обновляется, отдаётся сторонним организациям и т. п.) от службы MASA, которая должна безотказно работать десятилетиями.

10.4. Изготовители и использованное или украденное оборудование

Как указано выше, изготовитель получает сведения всякий раз, когда устройство с заводскими настройками по умолчанию выполняет автоматическую (zero-touch) начальную загрузку и пытается зачислиться у регистратора владельца домена. Поэтому изготовитель может отказать в выдаче сертификата, если он видит, что новый владелец отличается от прежнего.

  1. Это можно рассматривать как признак кражи устройства. Если законный владелец сообщил изготовителю о краже, при включении новым владельцем устройства с механизмом zero-touch будет раскрыто отождествление и местоположение этого владельца.

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

  3. Изготовитель может отказаться выдавать новый ваучер при смена владельца (как в случае кражи).

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

  5. Если изготовитель решил прекратить поддержку устройств (end-of-line) или владелец не оплатил поддержку, производитель может отклонить выдачу новых ваучеров. Это не является новым в отрасли и развёрнуто уже много систем лицензирования со значительно более жёсткими последствиями.

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

10.5. Изготовители и «серое» оборудование

Изготовители устройств часто продают разную продукцию на рынках разных регионов. Доступность конкретной продукции на определённом рынке может зависеть от разницы в ценах, вопросов поддержки (некоторые рынки требуют документацию и поддержку на местных языках) и государственного регулирования экспорта (например, возможность поставки строгой криптографии на конкретный рынок). При получении владельцем домена устройства (возможно, нового) для другого рынка это называется приобретением на «сером рынке» (Grey Market).

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

Указанные выше действия не являются новыми или незаконными. Многие изготовители поставляли (экспортные) варианты устройств со слабой криптографией в прошивке в течение десятилетий. Первой задачей предприятия или ISP всегда был вход (login) в систему изготовителя, подтверждение своих «прав» (сведения о стране и оплате поддержки) и получение обновлённой прошивки или лицензионного ключа для активации нужной прошивки.

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

10.6. Некоторые способы защиты от вмешательства изготовителей

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

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

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

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

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

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

10.7. Прекращение деятельности изготовителя

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

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

11. Вопросы безопасности

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

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

Для содействия работе клиентов EST с ограничениями клиент должен поддерживать модель аутентификации (параграф 3.3.2 в [RFC7030]). В разделе 7 эти требования изменены указанием, что регистратор может воспринимать устройства при отказе криптографической аутентификации. Это отражает текущую (слабую) практику поставки устройств без криптографического отождествления, которая не рекомендуется.

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

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

11.1. DoS-атаки на MASA

В некоторых случаях агент MASA может быть недоступен или откажется сотрудничать с регистратором. Это включает активные DoS-атаки, разделение сети (partition), смену правил MASA или иные ситуации, когда правила MASA отклоняют заявку. Это создаёт риск для владельца регистратора, поскольку поведение MASA может ограничивать возможность начальной загрузки устройства заявителя. Регистратор может снизить риск, запрашивая и сохраняя долгосрочные копии ваучеров без nonce. Таким способом они гарантируют начальную загрузку своих устройств.

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

Агент MASA открыт для DoS-атак, в которых злоумышленник заявляет неограниченное число устройств. Проблему смягчает возможность регистратора представлять действительного клиента изготовителя даже без проверки владения конкретными устройствами заявителя. Подпись заявителя в его voucher-request, пересылаемая регистратором в поле prior-signed-voucher-request его voucher-request, существенно снижает риск, гарантируя MASA возможность подтвердить близость между заявителем и подающим запрос регистратором. Интеграция с цепочкой продаж (знай своих клиентов) является дополнительным средством снижения рисков для провайдеров MASA и производителей.

11.2. Устойчивость DomainID к атакам Second-Preimage

Идентификатор domainID служит ссылкой на домен в журнале аудита. Ожидается, что domainID рассчитывается с помощью хэш-функции, устойчивой к атакам second-preimage, позволяющим регистратору создавать ложные записи.

11.3. Доступность качественных случайных значений

Значения nonce, применяемые заявителем в voucher-request, следует генерировать строгой криптографической последовательностью (параграф 6.2 в [RFC4086]). Аналогичное требование применяется к TLS. В частности, реализациям следует принимать в внимание усовершенствования из раздела 3 и параграфа 3.4 в [RFC4086]. Случайная затравка (seed), используемая при загрузке, должна быть уникальной у каждого устройства при каждой начальной загрузке. Сброс устройства к заводским установкам не отменяет это требование.

11.4. Свежесть Voucher-Request

Высказывались предложения по включению в voucher-request заявителя некого содержимого (a nonce), предоставляемого регистратором и/или MASA, чтобы те могли проверить свежесть запроса ваучера заявителем. Есть ряд операционных проблем с получением от MASA nonce для заявителя. Несколько проще получить случайное значение от регистратора, но тот ещё не подтверждён, поэтому nonce от него имеет мало смысла. При решении этих оперативных вопросов возникают проблемы с приватностью и логистикой, поэтому для рассмотрения вопроса нужно разобраться с ценностью такого подхода. В этом параграфе рассматриваются последствия отсутствия свежего voucher-request от заявителя.

Поскольку регистратор аутентифицирует заявителя, полная MITM-атака невозможна, несмотря на предварительную аутентификацию TLS (см. раздел ). Вместо этого рассматривается случай с фальшивым регистратором (Rm), который взаимодействует с заявителем параллельно или в непосредственной близости от предусмотренного регистратора (этот вариант поддерживается намеренно, как описано в параграфе 4.1). Фальшивый регистратор Rm может получить подписанный MASA ваучер напрямую или через произвольных посредников. Предположим, что MASA воспринимает voucher-request от регистратора (поскольку Rm взаимодействует с легитимным регистратором в соответствии с данными цепочки поставок или MASA лишь ведёт журнал аудита), тогда выдаётся ваучер, связывающий заявителя с Rm. Такой ваучер при его передаче заявителю будет связывать того с Rm и позволит заявителю завершить временное состояние. Заявитель будет доверять Rm и при наличии уязвимостей, которыми может воспользоваться Rm для получения полного административного контроля, можно предположить угрозу для предусмотренного регистратора.

Это смягчается проверкой предусмотренным регистратором журналов аудита, доступных у MASA, как описано в параграфе 5.8. Rm может принять voucher-request и подождать, пока предусмотренный регистратор завершит процесс предоставления полномочий, а затем передать voucher-request. Этот запрос ваучера от заявителя будет «устаревшим» в том смысле, что он больше не соответствует внутреннему состоянию заявителя. Для использования полученного ваучера Rm потребуется удалить устаревшее значение nonce или угадать будущее значение nonce от заявителя. Для снижения вероятности этого требуется генерировать строгие случайные или псевдослучайные значения nonce.

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

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

  • Извлечение и проверка сведений из журнала MASA при возникновении непредвиденных событий. Rm будет указан в журналах вместе с nonce.

11.5. Доверие к изготовителю

Расширения BRSKI для EST позволяет полностью настроить привязки доверия для домена у заявителя. Связь заданных на производстве привязок доверия с привязками в домене задаётся подписанным артефактом ваучера.

При отсутствии должной проверки ключа подписи IDevID изготовителя возникает риск восприятия сетью заявителей, которым не следует входить в сеть. Поскольку адрес MASA изготовителя включается в IDevID с использованием расширения из параграфа 2.3, заявитель-злоумышленник не будет иметь проблем при взаимодействии с MASA для создания действительного ваучера. Однако BRSKI не меняет основ модели доверия владельца домена изготовителю. Предполагая, что заявитель использует свой IDevID с EST [RFC7030] и BRSKI, домен (регистратор) должен доверять изготовителю. Организация такого доверия между доменом и изготовителем выходит за рамки BRSKI. Имеется ряд механизмов, которые подходят для этого, включая указанные ниже.

  • Настройка привязок доверия для каждого изготовителя вручную.

  • Механизм TOFU. При первом появлении привязки доверия выдаётся запрос человеку, а затем привязка помещается в доверенное хранилище. При этом возникает риск, связанный с похожими именами (например, dem0.example и demO.example) даже при проверке сопоставления ключа с именем, такой как WebPKI.

  • Сканирование привязки доверия по QR-коду на упаковке (на деле это ручной вариант механизма TOFU).

  • Работа с каналом продаже, где привязки доверия предоставляются как часть процесса продажи и возможно включаются в упаковочную накладную или счёт-фактуру.

  • Участие в консорциуме со всеми изготовителями данной категории оборудования (например, кабельных модемов), все члены которой специально для этого подписаны CA. Сегодня так делает CableLabs, выполняя аутентификацию и проверку полномочий как часть [docsisroot] и [TR069].

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

11.6. Поддержка привязок доверия изготовителем

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

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

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

Набор стандартный рабочих процедур для поддержки долгосрочных секретных ключей хорошо документирован. Например, WebPKI обеспечивает ряд вариантов аудита [cabforumaudit], а корневые операции DNSSEC хорошо описаны в [dnssecroot].

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

В следующем параграфе оцениваются риски, связанные с компрометацией ключа подписи IDevID у изготовителя, а затем рассматриваются риски при компрометации ключа MASA. Заключительный параграф рассматривает ситуацию, когда сам web-сервер MASA находится под контролем злоумышленника, но ключ подписи MASA безопасно хранится в аппаратном модуле, не подключённом напрямую.

11.6.1. Компрометация ключей подписи IDevID у изготовителя

Злоумышленник с доступом к ключу, который изготовитель применяет для подписи сертификатов IDevID, пожет создавать контрафактные устройства, которые могут представляться продукцией конкретного изготовителя, на деле отличаясь от таковой и являясь, по сути, троянскими конями. Поскольку злоумышленник контролирует MASA URL в сертификате, регистратора можно убедить обратиться к MASA злоумышленника. Регистратору при этом не нужно быть в каком-либо неразборчивом режиме. Помимо создания поддельных устройств злоумышленник может отзывать выпущенные сертификаты, если процесс сертификации IDevID полагается на распространяемые списки отзыва (CRL).

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

11.6.2. Компрометация ключей подписи MASA

Здесь нужно учитывать два момента времени — попадание ключа к злоумышленнику и признание взлома агент MASA.

11.6.2.1. Возможности атакующего при компрометации ключей MASA

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

Если злоумышленник контролирует видимый устройству регистратор, проблем с доставкой фиктивного ваучера не возникает. Практическим примером может служить атака на ЦОД в точке обмена трафиком (peering) ISP (приватной или общедоступной — IX). В такой ситуации к оборудованию уже подключены кабели, ведущие к другим устройствам (партнёрам по IX), через которые можно доставить фальшивый ваучер. Сложнее будет сбросить устройство к заводским настройкам, но это можно сделать путём обмана (социальная психология) инженерного персонала ЦОД. В большинстве закрытых ячеек имеются вентиляционные отверстия и с помощью длинной «скрепки» можно дотянуться до кнопки сброса устройства. Как только нужная часть оборудования ISP скомпрометирована, его можно использовать для компрометации соединённых с ним устройств (даже через длинные соединения — long haul), при условии их сброса к заводским настройкам.

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

Сказанное выше относится к использованию BRSKI с ANI. В случае применения IEEE 802.11 или 802.15.4 не возникает необходимости подключаться к устройству напрямую, но сброс к заводским настройкам все равно нужен. Физическое владение устройством не требуется, как отмечено выше, при наличии способа удалённого сброса к заводским настройкам. Для некоторых потребительских устройствах со слабой реализацией конечные пользователи могут знать о необходимости регулярного сброса настроек.

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

11.6.2.2. Риски после компрометации ключей

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

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

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

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

Необходимость использования краткосрочных ваучеров разъяснена в параграфе 6.1 [RFC8366]. Применение nonce обеспечивает свежесть, а краткосрочность ваучеров означает, что временные рамки доставки фиктивного ваучера очень малы. Злоумышленнику останутся лишь хранящиеся на складе устройства с долгоживущими ваучерами без nonce, поскольку их уязвимость сохранится.

Основной операционной рекомендацией для изготовителя является подписывание долгосрочных ваучеров без nonce не тем ключом, который применяется для подписи краткосрочных ваучеров. Если оба ключа приходят из одной привязки доверия (CA изготовителя), компрометация ключа этого CA приведёт к компрометации обоих ключей и, вероятно, других ключей, упомянутых в этом разделе.

11.6.3. Компрометация Web-службы MASA

Злоумышленник, захвативший web-службу MASA может организовать ряд атак. Самым очевидным путём является извлечение из базы данных списка клиентов и устройств для продажи этих сведений другим злоумышленникам, которые знают, как найти потенциально уязвимые устройства. Другим распространенным вариантом является установка (kill) службы или нарушение её работы с целью разочаровать клиентов. Это может серьёзно повлиять на возможность развёртывания клиентами новых услуг и станет большой проблемой при аварийном восстановлении.

Хотя компрометация web-службы MASA может вести к компрометации ключа подписи ваучеров у MASA, если подпись создаётся вовне (offboard), например в аппаратном модуле подписей (hardware signing module или HSM), ключи сохраняются в безопасности, но контроль над ними остаётся у злоумышленника. Такой злоумышленник может выпускать ваучеры для любого эксплуатируемого устройства, хотя это устройство ещё потребуется убедить в необходимости сброса к заводским настройкам перед атакой.

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

11.7. Вопросы безопасности для модуля YANG

Как указано в параграфе 7.4 (Вопросы безопасности) [RFC8366], заданный в этом документе модуль YANG определяет схему для данных, которые затем инкапсулируются в тип носителя с подписью CMS, как описано в разделе 5 [RFC5652]. Поэтому все данные модели YANG защищены от изменения.

Применение YANG для задания структур данных оператором yang-data является сравнительно новым и отличается от традиционного использования YANG для определения API с доступом по протоколам сетевого управления, таким как NETCONF [RFC6241] и RESTCONF [RFC8040]. Поэтому эти рекомендации не соответствуют шаблону, приведённому в параграфе 3.7 [RFC8407].

12. Литература

12.1. Нормативные документы

[IDevID] IEEE, «IEEE Standard for Local and metropolitan area networks — Secure Device Identity», IEEE 802.1AR, <https://1.ieee802.org/security/802-1ar>.

[ITU.X690] ITU-T, «Information Technology — ASN.1 encoding rules: Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER)», ITU-T Recommendation X.690, ISO/IEC 8825-1:2015, August 2015, <https://www.itu.int/rec/T-REC-X.690>.

[REST] Fielding, R.F., «Architectural Styles and the Design of Network-based Software Architectures», 2000, <http://www.ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation.pdf>.

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>.

[RFC3339] Klyne, G. and C. Newman, «Date and Time on the Internet: Timestamps», RFC 3339, DOI 10.17487/RFC3339, July 2002, <https://www.rfc-editor.org/info/rfc3339>.

[RFC3688] Mealling, M., «The IETF XML Registry», BCP 81, RFC 3688, DOI 10.17487/RFC3688, January 2004, <https://www.rfc-editor.org/info/rfc3688>.

[RFC3748] Aboba, B., Blunk, L., Vollbrecht, J., Carlson, J., and H. Levkowetz, Ed., «Extensible Authentication Protocol (EAP)», RFC 3748, DOI 10.17487/RFC3748, June 2004, <https://www.rfc-editor.org/info/rfc3748>.

[RFC3927] Cheshire, S., Aboba, B., and E. Guttman, «Dynamic Configuration of IPv4 Link-Local Addresses», RFC 3927, DOI 10.17487/RFC3927, May 2005, <https://www.rfc-editor.org/info/rfc3927>.

[RFC4086] Eastlake 3rd, D., Schiller, J., and S. Crocker, «Randomness Requirements for Security», BCP 106, RFC 4086, DOI 10.17487/RFC4086, June 2005, <https://www.rfc-editor.org/info/rfc4086>.

[RFC4519] Sciberras, A., Ed., «Lightweight Directory Access Protocol (LDAP): Schema for User Applications», RFC 4519, DOI 10.17487/RFC4519, June 2006, <https://www.rfc-editor.org/info/rfc4519>.

[RFC4648] Josefsson, S., «The Base16, Base32, and Base64 Data Encodings», RFC 4648, DOI 10.17487/RFC4648, October 2006, <https://www.rfc-editor.org/info/rfc4648>.

[RFC4862] Thomson, S., Narten, T., and T. Jinmei, «IPv6 Stateless Address Autoconfiguration», RFC 4862, DOI 10.17487/RFC4862, September 2007, <https://www.rfc-editor.org/info/rfc4862>.

[RFC5272] Schaad, J. and M. Myers, «Certificate Management over CMS (CMC)», RFC 5272, DOI 10.17487/RFC5272, June 2008, <https://www.rfc-editor.org/info/rfc5272>.

[RFC5280] Cooper, D., Santesson, S., Farrell, S., Boeyen, S., Housley, R., and W. Polk, «Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile», RFC 5280, DOI 10.17487/RFC5280, May 2008, <https://www.rfc-editor.org/info/rfc5280>.

[RFC5652] Housley, R., «Cryptographic Message Syntax (CMS)», STD 70, RFC 5652, DOI 10.17487/RFC5652, September 2009, <https://www.rfc-editor.org/info/rfc5652>.

[RFC6020] Bjorklund, M., Ed., «YANG — A Data Modeling Language for the Network Configuration Protocol (NETCONF)», RFC 6020, DOI 10.17487/RFC6020, October 2010, <https://www.rfc-editor.org/info/rfc6020>.

[RFC6125] Saint-Andre, P. and J. Hodges, «Representation and Verification of Domain-Based Application Service Identity within Internet Public Key Infrastructure Using X.509 (PKIX) Certificates in the Context of Transport Layer Security (TLS)», RFC 6125, DOI 10.17487/RFC6125, March 2011, <https://www.rfc-editor.org/info/rfc6125>.

[RFC6241] Enns, R., Ed., Bjorklund, M., Ed., Schoenwaelder, J., Ed., and A. Bierman, Ed., «Network Configuration Protocol (NETCONF)», RFC 6241, DOI 10.17487/RFC6241, June 2011, <https://www.rfc-editor.org/info/rfc6241>.

[RFC6762] Cheshire, S. and M. Krochmal, «Multicast DNS», RFC 6762, DOI 10.17487/RFC6762, February 2013, <https://www.rfc-editor.org/info/rfc6762>.

[RFC6763] Cheshire, S. and M. Krochmal, «DNS-Based Service Discovery», RFC 6763, DOI 10.17487/RFC6763, February 2013, <https://www.rfc-editor.org/info/rfc6763>.

[RFC7030] Pritikin, M., Ed., Yee, P., Ed., and D. Harkins, Ed., «Enrollment over Secure Transport», RFC 7030, DOI 10.17487/RFC7030, October 2013, <https://www.rfc-editor.org/info/rfc7030>.

[RFC7230] Fielding, R., Ed. and J. Reschke, Ed., «Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing», RFC 7230, DOI 10.17487/RFC7230, June 2014, <https://www.rfc-editor.org/info/rfc7230>.

[RFC7231] Fielding, R., Ed. and J. Reschke, Ed., «Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content», RFC 7231, DOI 10.17487/RFC7231, June 2014, <https://www.rfc-editor.org/info/rfc7231>.

[RFC7469] Evans, C., Palmer, C., and R. Sleevi, «Public Key Pinning Extension for HTTP», RFC 7469, DOI 10.17487/RFC7469, April 2015, <https://www.rfc-editor.org/info/rfc7469>.

[RFC7950] Bjorklund, M., Ed., «The YANG 1.1 Data Modeling Language», RFC 7950, DOI 10.17487/RFC7950, August 2016, <https://www.rfc-editor.org/info/rfc7950>.

[RFC7951] Lhotka, L., «JSON Encoding of Data Modeled with YANG», RFC 7951, DOI 10.17487/RFC7951, August 2016, <https://www.rfc-editor.org/info/rfc7951>.

[RFC8040] Bierman, A., Bjorklund, M., and K. Watsen, «RESTCONF Protocol», RFC 8040, DOI 10.17487/RFC8040, January 2017, <https://www.rfc-editor.org/info/rfc8040>.

[RFC8174] Leiba, B., «Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words», BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[RFC8259] Bray, T., Ed., «The JavaScript Object Notation (JSON) Data Interchange Format», STD 90, RFC 8259, DOI 10.17487/RFC8259, December 2017, <https://www.rfc-editor.org/info/rfc8259>.

[RFC8366] Watsen, K., Richardson, M., Pritikin, M., and T. Eckert, «A Voucher Artifact for Bootstrapping Protocols», RFC 8366, DOI 10.17487/RFC8366, May 2018, <https://www.rfc-editor.org/info/rfc8366>.

[RFC8368] Eckert, T., Ed. and M. Behringer, «Using an Autonomic Control Plane for Stable Connectivity of Network Operations, Administration, and Maintenance (OAM)», RFC 8368, DOI 10.17487/RFC8368, May 2018, <https://www.rfc-editor.org/info/rfc8368>.

[RFC8407] Bierman, A., «Guidelines for Authors and Reviewers of Documents Containing YANG Data Models», BCP 216, RFC 8407, DOI 10.17487/RFC8407, October 2018, <https://www.rfc-editor.org/info/rfc8407>.

[RFC8446] Rescorla, E., «The Transport Layer Security (TLS) Protocol Version 1.3», RFC 8446, DOI 10.17487/RFC8446, August 2018, <https://www.rfc-editor.org/info/rfc8446>.

[RFC8610] Birkholz, H., Vigano, C., and C. Bormann, «Concise Data Definition Language (CDDL): A Notational Convention to Express Concise Binary Object Representation (CBOR) and JSON Data Structures», RFC 8610, DOI 10.17487/RFC8610, June 2019, <https://www.rfc-editor.org/info/rfc8610>.

[RFC8951] Richardson, M., Werner, T., and W. Pan, «Clarification of Enrollment over Secure Transport (EST): Transfer Encodings and ASN.1», RFC 8951, DOI 10.17487/RFC8951, November 2020, <https://www.rfc-editor.org/info/rfc8951>.

[RFC8981] Gont, F., Krishnan, S., Narten, T., and R. Draves, «Temporary Address Extensions for Stateless Address Autoconfiguration in IPv6», RFC 8981, DOI 10.17487/RFC8981, February 2021, <https://www.rfc-editor.org/info/rfc8981>.

[RFC8990] Bormann, C., Carpenter, B., Ed., and B. Liu, Ed., «GeneRic Autonomic Signaling Protocol (GRASP)», RFC 8990, DOI 10.17487/RFC8990, May 2021, <https://www.rfc-editor.org/rfc/rfc8990>.

[RFC8994] Eckert, T., Ed., Behringer, M., Ed., and S. Bjarnason, «An Autonomic Control Plane (ACP)», RFC 8994, DOI 10.17487/RFC8994, May 2021, <https://www.rfc-editor.org/rfc/rfc8994>.

12.2. Дополнительная литература

[ACE-COAP-EST] van der Stok, P., Kampanakis, P., Richardson, M., and S. Raza, «EST over secure CoAP (EST-coaps)», Work in Progress12, Internet-Draft, draft-ietf-ace-coap-est-18, 6 January 2020, <https://tools.ietf.org/html/draft-ietf-ace-coap-est-18>.

[ANIMA-CONSTRAINED-VOUCHER] Richardson, M., van der Stok, P., Kampanakis, P., and E. Dijk, «Constrained Voucher Artifacts for Bootstrapping Protocols», Work in Progress, Internet-Draft, draft-ietf-anima-constrained-voucher-10, 21 February 2021, <https://tools.ietf.org/html/draft-ietf-anima-constrained-voucher-10>.

[ANIMA-STATE] Richardson, M., «Considerations for stateful vs stateless join router in ANIMA bootstrap», Work in Progress, Internet-Draft, draft-richardson-anima-state-for-joinrouter-03, 22 September 2020, <https://tools.ietf.org/html/draft-richardson-anima-state-for-joinrouter-03>.

[brewski] Urban Dictionary, «brewski», March 2003, <https://www.urbandictionary.com/define.php?term=brewski>.

[cabforumaudit] CA/Browser Forum, «Information for Auditors and Assessors», August 2019, <https://cabforum.org/information-for-auditors-and-assessors/>.

[Dingledine] Dingledine, R., Mathewson, N., and P. Syverson, «Tor: The Second-Generation Onion Router», August 2004, <https://svn-archive.torproject.org/svn/projects/design-paper/tor-design.pdf>.

[dnssecroot] «DNSSEC Practice Statement for the Root Zone ZSK Operator», December 2017, <https://www.iana.org/dnssec/procedures/zsk-operator/dps-zsk-operator-v2.1.pdf>.

[docsisroot] «CableLabs Digital Certificate Issuance Service», February 2018, <https://www.cablelabs.com/resources/digital-certificate-issuance-service/>.

[imprinting] Wikipedia, «Imprinting (psychology)», January 2021, <https://en.wikipedia.org/w/index.php?title=Imprinting_(psychology)&=999211441>.

[IoTstrangeThings] ESET, «IoT of toys stranger than fiction: Cybersecurity and data privacy update», March 2017, <https://www.welivesecurity.com/2017/03/03/internet-of-things-security-privacy-iot-update/>.

[livingwithIoT] Silicon Republic, «What is it actually like to live in a house filled with IoT devices?», February 2018, <https://www.siliconrepublic.com/machines/iot-smart-devices-reality>.

[minerva] Richardson, M., «Minerva reference implementation for BRSKI», 2020, <https://minerva.sandelman.ca/>.

[minervagithub] «ANIMA Minerva toolkit», <https://github.com/ANIMAgus-minerva>.

[openssl] OpenSSL, «OpenSSL X509 Utility», September 2019, <https://www.openssl.org/docs/man1.1.1/man1/openssl-x509.html/>.

[RFC2131] Droms, R., «Dynamic Host Configuration Protocol», RFC 2131, DOI 10.17487/RFC2131, March 1997, <https://www.rfc-editor.org/info/rfc2131>.

[RFC2663] Srisuresh, P. and M. Holdrege, «IP Network Address Translator (NAT) Terminology and Considerations», RFC 2663, DOI 10.17487/RFC2663, August 1999, <https://www.rfc-editor.org/info/rfc2663>.

[RFC5209] Sangster, P., Khosravi, H., Mani, M., Narayan, K., and J. Tardo, «Network Endpoint Assessment (NEA): Overview and Requirements», RFC 5209, DOI 10.17487/RFC5209, June 2008, <https://www.rfc-editor.org/info/rfc5209>.

[RFC6960] Santesson, S., Myers, M., Ankney, R., Malpani, A., Galperin, S., and C. Adams, «X.509 Internet Public Key Infrastructure Online Certificate Status Protocol — OCSP», RFC 6960, DOI 10.17487/RFC6960, June 2013, <https://www.rfc-editor.org/info/rfc6960>.

[RFC6961] Pettersen, Y., «The Transport Layer Security (TLS) Multiple Certificate Status Request Extension», RFC 6961, DOI 10.17487/RFC6961, June 2013, <https://www.rfc-editor.org/info/rfc6961>.

[RFC7228] Bormann, C., Ersue, M., and A. Keranen, «Terminology for Constrained-Node Networks», RFC 7228, DOI 10.17487/RFC7228, May 2014, <https://www.rfc-editor.org/info/rfc7228>.

[RFC7258] Farrell, S. and H. Tschofenig, «Pervasive Monitoring Is an Attack», BCP 188, RFC 7258, DOI 10.17487/RFC7258, May 2014, <https://www.rfc-editor.org/info/rfc7258>.

[RFC7435] Dukhovni, V., «Opportunistic Security: Some Protection Most of the Time», RFC 7435, DOI 10.17487/RFC7435, December 2014, <https://www.rfc-editor.org/info/rfc7435>.

[RFC7575] Behringer, M., Pritikin, M., Bjarnason, S., Clemm, A., Carpenter, B., Jiang, S., and L. Ciavaglia, «Autonomic Networking: Definitions and Design Goals», RFC 7575, DOI 10.17487/RFC7575, June 2015, <https://www.rfc-editor.org/info/rfc7575>.

[RFC8126] Cotton, M., Leiba, B., and T. Narten, «Guidelines for Writing an IANA Considerations Section in RFCs», BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017, <https://www.rfc-editor.org/info/rfc8126>.

[RFC8340] Bjorklund, M. and L. Berger, Ed., «YANG Tree Diagrams», BCP 215, RFC 8340, DOI 10.17487/RFC8340, March 2018, <https://www.rfc-editor.org/info/rfc8340>.

[RFC8615] Nottingham, M., «Well-Known Uniform Resource Identifiers (URIs)», RFC 8615, DOI 10.17487/RFC8615, May 2019, <https://www.rfc-editor.org/info/rfc8615>.

[RFC8993] Behringer, M., Ed., Carpenter, B., Eckert, T., Ciavaglia, L., and J. Nobre, «A Reference Model for Autonomic Networking», RFC 8993, DOI 10.17487/RFC8993, May 2021, <https://www.rfc-editor.org/info/rfc8993>.

[slowloris] Wikipedia, «Slowloris (computer security)», January 2021, <https://en.wikipedia.org/w/index.php?title=Slowloris_(computer_security)&oldid=1001473290/>.

[softwareescrow] Wikipedia, «Source code escrow», March 2020, <https://en.wikipedia.org/w/index.php?title=Source_code_escrow&oldid=948073074>.

[Stajano99theresurrecting] Stajano, F. and R. Anderson, «The Resurrecting Duckling: Security Issues for Ad-hoc Wireless Networks», 1999, <https://www.cl.cam.ac.uk/~fms27/papers/1999-StajanoAnd-duckling.pdf>.

[TR069] Broadband Forum, «CPE WAN Management Protocol», TR-069, Issue 1, Amendment 6, March 2018, <https://www.broadband-forum.org/download/TR-069_Amendment-6.pdf>.

[W3C.capability-urls] Tennison, J., «Good Practices for Capability URLs», W3C First Public Working Draft, World Wide Web Consortium WD WD-capability-urls-20140218, February 2014, <https://www.w3.org/TR/2014/WD-capability-urls>.

[YANG-KEYSTORE] Watsen, K., «A YANG Data Model for a Keystore», Work in Progress, Internet-Draft, draft-ietf-netconf-keystore-22, 18 May 2021, <https://tools.ietf.org/html/draft-ietf-netconf-keystore-22>.

Приложение A. IPv4 и операции без ANI

Спецификация BRSKI в разделе 4 намеренно рассматривает лишь механизмы для заявителей с адресами IPv6 link-local. В этом приложении даны ненормативные расширения, которые могут быть применены в других средах.

A.1. Адреса IPv4 Link-Local

Вместо адреса IPv6 link-local можно создать адрес IPv4 в соответствии с Dynamic Configuration of IPv4 Link-Local Addresses [RFC3927]. В случае формирования адреса IPv4 link-local начальная загрузка будет продолжаться как для IPv6 с поиском посредника.

A.2. Использование DHCPv4

Заявитель может получить IP-адрес по протоколу DHCP ([RFC2131]. Предоставленные DHCP параметры для системы доменных имён (DNS) можно использовать для операций DNS при отказе попыток локального обнаружения.

Приложение B. Варианты mDNS и DNS-SD Proxy Discovery

Обнаружение посредника заявителем (параграф 4.1) может выполняться через DNS-based Service Discovery [RFC6763] по протоколу Multicast DNS [RFC6762] для поиска посредника в _brski-proxy._tcp.local. Обнаружение посредником регистратора (параграф 4.3) может выполняться поиском служб через по протоколу Multicast DNS для обнаружения _brski-registrar._tcp.local.

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

Обнаружить регистратор можно также с помощью поиска служб через DNS по _brski-registrar._tcp.example.com. В этом случае домен example.com обнаруживается, как указано в разделе 11 [RFC6763] (в Приложении A.2 предложено использование параметров DHCP).

Если локальный посредник или регистратор не найден с помощью механизмов the GRASP или описанного выше обнаружения служб через DNS, заявитель может обратиться к общеизвестным серверам начальной загрузки изготовителей через поиск в DNS общеизвестных URI, таких как brski-registrar.manufacturer.example.com. Детали URI зависят от изготовителя. Изготовители, применяющие такой метод у заявителя, отвечают за предоставление службы регистратора (см. также параграф 2.7).

Службы DNS, возвращённые при каждом запросе, поддерживаются до завершения начальной загрузки. В случае отказа при загрузке и возврата заявителя в состояние Discovery,он продолжает с того места, где остановился, пытаясь выполнить начальную загрузку. Например, если первый отклик Multicast DNS _bootstrapks._tcp.local не работает, применяется второй, затем третий. Если это не помогает, заявитель переходит к обычному поиску служб через DNS.

Приложение C. Примеры ваучеров

В использование ваучеров вовлечены три сущности — MASA выпускает (подписывает) ваучеры, в ваучере упоминается открытый ключ регистратора, а заявитель проверяет ваучер. Для представления воспроизводимых примеров сначала указываются секретные и открытые ключи для примеров MASA и регистратора.

Ключи взяты из открытой реализации BRSKI, называемый Minerva [minerva], доступной на GitHub [minervagithub]. Представленные здесь ключи используются модульных и интеграционных тестах. Код MASA называется highway, код регистратора — fountain, а пример клиента называется reach.

Компоненты открытых ключей представлены как сертификаты в кодировке base64 и декодированы утилитой openssl x509, чтобы можно было видеть расширения. Использовалась версия 1.1.1c библиотеки и утили [openssl].

C.1. Вовлечённые ключи

Изготовитель имеет CA, где подписываются IDevID заявителя. В дополнение к этому агент подписей изготовителя (MASA) подписывает ваучеры и его сертификат должен распространяться устройствам в процессе производства, чтобы ваучеры можно было проверить.

C.1.1. Орган сертификации изготовителя для подписей IDevID

Приведённый ниже секретный ключ применяется CA для подписания сертификатов IDevID.

   <CODE BEGINS> file "vendor.key"
   -----BEGIN EC PRIVATE KEY-----
   MIGkAgEBBDCAYkoLW1IEA5SKKhMMdkTK7sJxk5ybKqYq9Yr5aR7tNwqXyLGS7z8G
   8S4w/UJ58BqgBwYFK4EEACKhZANiAAQu5/yktJbFLjMC87h7b+yTreFuF8GwewKH
   L4mS0r0dVAQubqDUQcTrjvpXrXCpTojiLCzgp8fzkcUDkZ9LD/M90LDipiLNIOkP
   juF8QkoAbT8pMrY83MS8y76wZ7AalNQ=
   -----END EC PRIVATE KEY-----
   <CODE ENDS>

Приведённый ниже открытый ключ служит для проверки сертификатов IDevID. Файл examples/vendor.key.

   <CODE BEGINS> file "vendor.cert"
   Certificate:
       Data:
           Version: 3 (0x2)
           Serial Number: 1216069925 (0x487bc125)
           Signature Algorithm: ecdsa-with-SHA256
           Issuer: CN = highway-test.example.com CA
           Validity
               Not Before: Apr 13 20:34:24 2021 GMT
               Not After : Apr 13 20:34:24 2023 GMT
           Subject: CN = highway-test.example.com CA
           Subject Public Key Info:
               Public Key Algorithm: id-ecPublicKey
                   Public-Key: (384 bit)
                   pub:
                       04:2e:e7:fc:a4:b4:96:c5:2e:33:02:f3:b8:7b:6f:
                       ec:93:ad:e1:6e:17:c1:b0:7b:02:87:2f:89:92:d2:
                       bd:1d:54:04:2e:6e:a0:d4:41:c4:eb:8e:fa:57:ad:
                       70:a9:4e:88:e2:2c:2c:e0:a7:c7:f3:91:c5:03:91:
                       9f:4b:0f:f3:3d:d0:b0:e2:a6:22:cd:20:e9:0f:8e:
                       e1:7c:42:4a:00:6d:3f:29:32:b6:3c:dc:c4:bc:cb:
                       be:b0:67:b0:1a:94:d4
                   ASN1 OID: secp384r1
                   NIST CURVE: P-384
           X509v3 extensions:
               X509v3 Basic Constraints: critical
                   CA:TRUE
               X509v3 Key Usage: critical
                   Certificate Sign, CRL Sign
               X509v3 Subject Key Identifier:
                   5E:0C:A9:52:5A:8C:DF:A9:0F:03:14:E9:96:F1:80:76:
                   8C:53:8A:08
               X509v3 Authority Key Identifier:
                   keyid:5E:0C:A9:52:5A:8C:DF:A9:0F:03:14:E9:96:F1:
                   80:76:8C:53:8A:08

       Signature Algorithm: ecdsa-with-SHA256
            30:64:02:30:60:37:a0:66:89:80:27:e1:0d:e5:43:9a:62:f1:
            02:bc:0f:72:6d:a9:e9:cb:84:a5:c6:44:d3:41:9e:5d:ce:7d:
            46:16:6e:15:de:f7:cc:e8:3e:61:f9:03:7c:20:c4:b7:02:30:
            7f:e9:f3:12:bb:06:c6:24:00:2b:41:aa:21:6b:d8:25:ed:81:
            07:11:ef:66:8f:06:bf:c8:be:f0:58:74:24:45:39:4d:04:fc:
            31:69:6f:cf:db:fe:61:7b:c3:24:31:ff
   -----BEGIN CERTIFICATE-----
   MIIB3TCCAWSgAwIBAgIESHvBJTAKBggqhkjOPQQDAjAmMSQwIgYDVQQDDBtoaWdo
   d2F5LXRlc3QuZXhhbXBsZS5jb20gQ0EwHhcNMjEwNDEzMjAzNDI0WhcNMjMwNDEz
   MjAzNDI0WjAmMSQwIgYDVQQDDBtoaWdod2F5LXRlc3QuZXhhbXBsZS5jb20gQ0Ew
   djAQBgcqhkjOPQIBBgUrgQQAIgNiAAQu5/yktJbFLjMC87h7b+yTreFuF8GwewKH
   L4mS0r0dVAQubqDUQcTrjvpXrXCpTojiLCzgp8fzkcUDkZ9LD/M90LDipiLNIOkP
   juF8QkoAbT8pMrY83MS8y76wZ7AalNSjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYD
   VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBReDKlSWozfqQ8DFOmW8YB2jFOKCDAfBgNV
   HSMEGDAWgBReDKlSWozfqQ8DFOmW8YB2jFOKCDAKBggqhkjOPQQDAgNnADBkAjBg
   N6BmiYAn4Q3lQ5pi8QK8D3JtqenLhKXGRNNBnl3OfUYWbhXe98zoPmH5A3wgxLcC
   MH/p8xK7BsYkACtBqiFr2CXtgQcR72aPBr/IvvBYdCRFOU0E/DFpb8/b/mF7wyQx
   /w==
   -----END CERTIFICATE-----
   <CODE ENDS>

C.1.2. Пара ключей MASA для подписи ваучеров

MASA — это уполномоченный изготовителем агент подписания (Manufacturer Authorized Signing Authority). Приведённые ниже ключи служат для подписывания ваучеров. Пример сертификата TLS (5.4. Организация BRSKI-MASA TLS) для аутентификации HTTP не представлен, поскольку тот имеет базовую форму. Секретный ключ для подписи ваучеров показан ниже.

   <CODE BEGINS> file "masa.key"
   -----BEGIN EC PRIVATE KEY-----
   MHcCAQEEIFhdd0eDdzip67kXx72K+KHGJQYJHNy8pkiLJ6CcvxMGoAoGCCqGSM49
   AwEHoUQDQgAEqgQVo0S54kT4yfkbBxumdHOcHrpsqbOpMKmiMln3oB1HAW25MJV+
   gqi4tMFfSJ0iEwt8kszfWXK4rLgJS2mnpQ==
   -----END EC PRIVATE KEY-----
   <CODE ENDS>

Открытый ключ служит для проверки ваучеров и подписывается показанным выше ключом CA. Файл examples/masa.key.

   <CODE BEGINS> file "masa.cert"
   Certificate:
       Data:
           Version: 3 (0x2)
           Serial Number: 193399345 (0xb870a31)
           Signature Algorithm: ecdsa-with-SHA256
           Issuer: CN = highway-test.example.com CA
           Validity
               Not Before: Apr 13 21:40:16 2021 GMT
               Not After : Apr 13 21:40:16 2023 GMT
           Subject: CN = highway-test.example.com MASA
           Subject Public Key Info:
               Public Key Algorithm: id-ecPublicKey
                   Public-Key: (256 bit)
                   pub:
                       04:aa:04:15:a3:44:b9:e2:44:f8:c9:f9:1b:07:1b:
                       a6:74:73:9c:1e:ba:6c:a9:b3:a9:30:a9:a2:32:59:
                       f7:a0:1d:47:01:6d:b9:30:95:7e:82:a8:b8:b4:c1:
                       5f:48:9d:22:13:0b:7c:92:cc:df:59:72:b8:ac:b8:
                       09:4b:69:a7:a5
                   ASN1 OID: prime256v1
                   NIST CURVE: P-256
           X509v3 extensions:
               X509v3 Basic Constraints: critical
                   CA:FALSE
       Signature Algorithm: ecdsa-with-SHA256
            30:66:02:31:00:ae:cb:61:2d:d4:5c:8d:6e:86:aa:0b:06:1d:
            c6:d3:60:ba:32:73:36:25:d3:23:85:49:87:1c:ce:94:23:79:
            1a:9e:41:55:24:1d:15:22:a1:48:bb:0a:c0:ab:3c:13:73:02:
            31:00:86:3c:67:b3:95:a2:e2:e5:f9:ad:f9:1d:9c:c1:34:32:
            78:f5:cf:ea:d5:47:03:9f:00:bf:d0:59:cb:51:c2:98:04:81:
            24:8a:51:13:50:b1:75:b2:2f:9d:a8:b4:f4:b9
   -----BEGIN CERTIFICATE-----
   MIIBcDCB9qADAgECAgQLhwoxMAoGCCqGSM49BAMCMCYxJDAiBgNVBAMMG2hpZ2h3
   YXktdGVzdC5leGFtcGxlLmNvbSBDQTAeFw0yMTA0MTMyMTQwMTZaFw0yMzA0MTMy
   MTQwMTZaMCgxJjAkBgNVBAMMHWhpZ2h3YXktdGVzdC5leGFtcGxlLmNvbSBNQVNB
   MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEqgQVo0S54kT4yfkbBxumdHOcHrps
   qbOpMKmiMln3oB1HAW25MJV+gqi4tMFfSJ0iEwt8kszfWXK4rLgJS2mnpaMQMA4w
   DAYDVR0TAQH/BAIwADAKBggqhkjOPQQDAgNpADBmAjEArsthLdRcjW6GqgsGHcbT
   YLoyczYl0yOFSYcczpQjeRqeQVUkHRUioUi7CsCrPBNzAjEAhjxns5Wi4uX5rfkd
   nME0Mnj1z+rVRwOfAL/QWctRwpgEgSSKURNQsXWyL52otPS5
   -----END CERTIFICATE-----
   <CODE ENDS>

C.1.3. Орган сертификации регистратора

Этот CA зачисляет заявителя, если тот уполномочен, а также подписывает сертификат регистратора.

   <CODE BEGINS> file "ownerca_secp384r1.key"
   -----BEGIN EC PRIVATE KEY-----
   MIGkAgEBBDCHnLI0MSOLf8XndiZqoZdqblcPR5YSoPGhPOuFxWy1gFi9HbWv8b/R
   EGdRgGEVSjKgBwYFK4EEACKhZANiAAQbf1m6F8MavGaNjGzgw/oxcQ9l9iKRvbdW
   gAfb37h6pUVNeYpGlxlZljGxj2l9Mr48yD5bY7VG9qjVb5v5wPPTuRQ/ckdRpHbd
   0vC/9cqPMAF/+MJf0/UgA0SLi/IHbLQ=
   -----END EC PRIVATE KEY-----
   <CODE ENDS>

Ниже приведён открытый ключ, указываемый в voucher-request регистратора для индикации близости. Файл examples/ownerca_secp384r1.key

   <CODE BEGINS> file "ownerca_secp384r1.cert"
   Certificate:
       Data:
           Version: 3 (0x2)
           Serial Number: 694879833 (0x296b0659)
           Signature Algorithm: ecdsa-with-SHA256
           Issuer: DC = ca, DC = sandelman,
            CN = fountain-test.example.com Unstrung Fountain Root CA
           Validity
               Not Before: Feb 25 21:31:45 2020 GMT
               Not After : Feb 24 21:31:45 2022 GMT
           Subject: DC = ca, DC = sandelman,
            CN = fountain-test.example.com Unstrung Fountain Root CA
           Subject Public Key Info:
               Public Key Algorithm: id-ecPublicKey
                   Public-Key: (384 bit)
                   pub:
                       04:1b:7f:59:ba:17:c3:1a:bc:66:8d:8c:6c:e0:c3:
                       fa:31:71:0f:65:f6:22:91:bd:b7:56:80:07:db:df:
                       b8:7a:a5:45:4d:79:8a:46:97:19:59:96:31:b1:8f:
                       69:7d:32:be:3c:c8:3e:5b:63:b5:46:f6:a8:d5:6f:
                       9b:f9:c0:f3:d3:b9:14:3f:72:47:51:a4:76:dd:d2:
                       f0:bf:f5:ca:8f:30:01:7f:f8:c2:5f:d3:f5:20:03:
                       44:8b:8b:f2:07:6c:b4
                   ASN1 OID: secp384r1
                   NIST CURVE: P-384
           X509v3 extensions:
               X509v3 Basic Constraints: critical
                   CA:TRUE
               X509v3 Key Usage: critical
                   Certificate Sign, CRL Sign
               X509v3 Subject Key Identifier:
                   B9:A5:F6:CB:11:E1:07:A4:49:2C:A7:08:C6:7C:10:BC:
                   87:B3:74:26
               X509v3 Authority Key Identifier:
                   keyid:B9:A5:F6:CB:11:E1:07:A4:49:2C:A7:08:C6:7C:
                   10:BC:87:B3:74:26

       Signature Algorithm: ecdsa-with-SHA256
            30:64:02:30:20:83:06:ce:8d:98:a4:54:7a:66:4c:4a:3a:70:
            c2:52:36:5a:52:8d:59:7d:20:9b:2a:69:14:58:87:38:d8:55:
            79:dd:fd:29:38:95:1e:91:93:76:b4:f5:66:29:44:b4:02:30:
            6f:38:f9:af:12:ed:30:d5:85:29:7c:b1:16:58:bd:67:91:43:
            c4:0d:30:f9:d8:1c:ac:2f:06:dd:bc:d5:06:42:2c:84:a2:04:
            ea:02:a4:5f:17:51:26:fb:d9:2f:d2:5c
   -----BEGIN CERTIFICATE-----
   MIICazCCAfKgAwIBAgIEKWsGWTAKBggqhkjOPQQDAjBtMRIwEAYKCZImiZPyLGQB
   GRYCY2ExGTAXBgoJkiaJk/IsZAEZFglzYW5kZWxtYW4xPDA6BgNVBAMMM2ZvdW50
   YWluLXRlc3QuZXhhbXBsZS5jb20gVW5zdHJ1bmcgRm91bnRhaW4gUm9vdCBDQTAe
   Fw0yMDAyMjUyMTMxNDVaFw0yMjAyMjQyMTMxNDVaMG0xEjAQBgoJkiaJk/IsZAEZ
   FgJjYTEZMBcGCgmSJomT8ixkARkWCXNhbmRlbG1hbjE8MDoGA1UEAwwzZm91bnRh
   aW4tdGVzdC5leGFtcGxlLmNvbSBVbnN0cnVuZyBGb3VudGFpbiBSb290IENBMHYw
   EAYHKoZIzj0CAQYFK4EEACIDYgAEG39ZuhfDGrxmjYxs4MP6MXEPZfYikb23VoAH
   29+4eqVFTXmKRpcZWZYxsY9pfTK+PMg+W2O1Rvao1W+b+cDz07kUP3JHUaR23dLw
   v/XKjzABf/jCX9P1IANEi4vyB2y0o2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
   DwEB/wQEAwIBBjAdBgNVHQ4EFgQUuaX2yxHhB6RJLKcIxnwQvIezdCYwHwYDVR0j
   BBgwFoAUuaX2yxHhB6RJLKcIxnwQvIezdCYwCgYIKoZIzj0EAwIDZwAwZAIwIIMG
   zo2YpFR6ZkxKOnDCUjZaUo1ZfSCbKmkUWIc42FV53f0pOJUekZN2tPVmKUS0AjBv
   OPmvEu0w1YUpfLEWWL1nkUPEDTD52BysLwbdvNUGQiyEogTqAqRfF1Em+9kv0lw=
   -----END CERTIFICATE-----
   <CODE ENDS>

C.1.4. Пара ключей регистратора

Регистратор является представителем владельца домена. Приведённый ниже ключ подписывает voucher-requests от регистратора и завершает соединение TLS от заявителя.

   <CODE BEGINS> file "jrc_prime256v1.key"
   -----BEGIN EC PRIVATE KEY-----
   MHcCAQEEIFZodk+PC5Mu24+ra0sbOjKzan+dW5rvDAR7YuJUOC1YoAoGCCqGSM49
   AwEHoUQDQgAElmVQcjS6n+Xd5l/28IFv6UiegQwSBztGj5dkK2MAjQIPV8l8lH+E
   jLIOYdbJiI0VtEIf1/Jqt+TOBfinTNOLOg==
   -----END EC PRIVATE KEY-----
   <CODE ENDS>

Открытый ключ указывается в voucher-request от заявителя для индикации близости.

   <CODE BEGINS> file "jrc_prime256v1.cert"
   Certificate:
       Data:
           Version: 3 (0x2)
           Serial Number: 1066965842 (0x3f989b52)
           Signature Algorithm: ecdsa-with-SHA256
           Issuer: DC = ca, DC = sandelman,
            CN = fountain-test.example.com Unstrung Fountain Root CA
           Validity
               Not Before: Feb 25 21:31:54 2020 GMT
               Not After : Feb 24 21:31:54 2022 GMT
           Subject: DC = ca, DC = sandelman,
            CN = fountain-test.example.com
           Subject Public Key Info:
               Public Key Algorithm: id-ecPublicKey
                   Public-Key: (256 bit)
                   pub:
                       04:96:65:50:72:34:ba:9f:e5:dd:e6:5f:f6:f0:81:
                       6f:e9:48:9e:81:0c:12:07:3b:46:8f:97:64:2b:63:
                       00:8d:02:0f:57:c9:7c:94:7f:84:8c:b2:0e:61:d6:
                       c9:88:8d:15:b4:42:1f:d7:f2:6a:b7:e4:ce:05:f8:
                       a7:4c:d3:8b:3a
                   ASN1 OID: prime256v1
                   NIST CURVE: P-256
           X509v3 extensions:
               X509v3 Extended Key Usage: critical
                   CMC Registration Authority
               X509v3 Key Usage: critical
                   Digital Signature
       Signature Algorithm: ecdsa-with-SHA256
            30:65:02:30:66:4f:60:4c:55:48:1e:96:07:f8:dd:1f:b9:c8:
            12:8d:45:36:87:9b:23:c0:bc:bb:f1:cb:3d:26:15:56:6f:5f:
            1f:bf:d5:1c:0e:6a:09:af:1b:76:97:99:19:23:fd:7e:02:31:
            00:bc:ac:c3:41:b0:ba:0d:af:52:f9:9c:6e:7a:7f:00:1d:23:
            c8:62:01:61:bc:4b:c5:c0:47:99:35:0a:0c:77:61:44:01:4a:
            07:52:70:57:00:75:ff:be:07:0e:98:cb:e5
   -----BEGIN CERTIFICATE-----
   MIIB/DCCAYKgAwIBAgIEP5ibUjAKBggqhkjOPQQDAjBtMRIwEAYKCZImiZPyLGQB
   GRYCY2ExGTAXBgoJkiaJk/IsZAEZFglzYW5kZWxtYW4xPDA6BgNVBAMMM2ZvdW50
   YWluLXRlc3QuZXhhbXBsZS5jb20gVW5zdHJ1bmcgRm91bnRhaW4gUm9vdCBDQTAe
   Fw0yMDAyMjUyMTMxNTRaFw0yMjAyMjQyMTMxNTRaMFMxEjAQBgoJkiaJk/IsZAEZ
   FgJjYTEZMBcGCgmSJomT8ixkARkWCXNhbmRlbG1hbjEiMCAGA1UEAwwZZm91bnRh
   aW4tdGVzdC5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJZl
   UHI0up/l3eZf9vCBb+lInoEMEgc7Ro+XZCtjAI0CD1fJfJR/hIyyDmHWyYiNFbRC
   H9fyarfkzgX4p0zTizqjKjAoMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMcMA4GA1Ud
   DwEB/wQEAwIHgDAKBggqhkjOPQQDAgNoADBlAjBmT2BMVUgelgf43R+5yBKNRTaH
   myPAvLvxyz0mFVZvXx+/1RwOagmvG3aXmRkj/X4CMQC8rMNBsLoNr1L5nG56fwAd
   I8hiAWG8S8XAR5k1Cgx3YUQBSgdScFcAdf++Bw6Yy+U=
   -----END CERTIFICATE-----
   <CODE ENDS>

C.1.5. Пара ключей заявителя

Заявитель имеет пару ключей IDevID, создаваемую при производстве.

   <CODE BEGINS> file "idevid_00-D0-E5-F2-00-02.key"
   -----BEGIN EC PRIVATE KEY-----
   MHcCAQEEIBHNh6r8QRevRuo+tEmBJeFjQKf6bpFA/9NGoltv+9sNoAoGCCqGSM49
   AwEHoUQDQgAEA6N1Q4ezfMAKmoecrfb0OBMc1AyEH+BATkF58FsTSyBxs0SbSWLx
   FjDOuwB9gLGn2TsTUJumJ6VPw5Z/TP4hJw==
   -----END EC PRIVATE KEY-----
   <CODE ENDS>

Сертификат, применяемый регистратором для поиска MASA представлен ниже.

   <CODE BEGINS> file "idevid_00-D0-E5-F2-00-02.cert"
   Certificate:
       Data:
           Version: 3 (0x2)
           Serial Number: 521731815 (0x1f18fee7)
           Signature Algorithm: ecdsa-with-SHA256
           Issuer: CN = highway-test.example.com CA
           Validity
               Not Before: Apr 27 18:29:30 2021 GMT
               Not After : Dec 31 00:00:00 2999 GMT
           Subject: serialNumber = 00-D0-E5-F2-00-02
           Subject Public Key Info:
               Public Key Algorithm: id-ecPublicKey
                   Public-Key: (256 bit)
                   pub:
                       04:03:a3:75:43:87:b3:7c:c0:0a:9a:87:9c:ad:f6:
                       f4:38:13:1c:d4:0c:84:1f:e0:40:4e:41:79:f0:5b:
                       13:4b:20:71:b3:44:9b:49:62:f1:16:30:ce:bb:00:
                       7d:80:b1:a7:d9:3b:13:50:9b:a6:27:a5:4f:c3:96:
                       7f:4c:fe:21:27
                   ASN1 OID: prime256v1
                   NIST CURVE: P-256
           X509v3 extensions:
               X509v3 Subject Key Identifier:
                   45:88:CC:96:96:00:64:37:B0:BA:23:65:64:64:54:08:
                   06:6C:56:AD
               X509v3 Basic Constraints:
                   CA:FALSE
               1.3.6.1.5.5.7.1.32:
                   ..highway-test.example.com:9443
       Signature Algorithm: ecdsa-with-SHA256
            30:65:02:30:62:2a:db:be:34:f7:1b:cb:85:de:26:8e:43:00:
            f9:0d:88:c8:77:a8:dd:3c:08:40:54:bc:ec:3d:b6:dc:70:2b:
            c3:7f:ca:19:21:9a:a0:ab:c5:51:8e:aa:df:36:de:8b:02:31:
            00:b2:5d:59:f8:47:c7:ed:03:97:a8:c0:c7:a8:81:fa:a8:86:
            ed:67:64:37:51:7a:6e:9c:a3:82:4d:6d:ad:bc:f3:35:9e:9d:
            6a:a2:6d:7f:7f:25:1c:03:ef:f0:ba:9b:71
   -----BEGIN CERTIFICATE-----
   MIIBrzCCATWgAwIBAgIEHxj+5zAKBggqhkjOPQQDAjAmMSQwIgYDVQQDDBtoaWdo
   d2F5LXRlc3QuZXhhbXBsZS5jb20gQ0EwIBcNMjEwNDI3MTgyOTMwWhgPMjk5OTEy
   MzEwMDAwMDBaMBwxGjAYBgNVBAUTETAwLUQwLUU1LUYyLTAwLTAyMFkwEwYHKoZI
   zj0CAQYIKoZIzj0DAQcDQgAEA6N1Q4ezfMAKmoecrfb0OBMc1AyEH+BATkF58FsT
   SyBxs0SbSWLxFjDOuwB9gLGn2TsTUJumJ6VPw5Z/TP4hJ6NZMFcwHQYDVR0OBBYE
   FEWIzJaWAGQ3sLojZWRkVAgGbFatMAkGA1UdEwQCMAAwKwYIKwYBBQUHASAEHxYd
   aGlnaHdheS10ZXN0LmV4YW1wbGUuY29tOjk0NDMwCgYIKoZIzj0EAwIDaAAwZQIw
   YirbvjT3G8uF3iaOQwD5DYjId6jdPAhAVLzsPbbccCvDf8oZIZqgq8VRjqrfNt6L
   AjEAsl1Z+EfH7QOXqMDHqIH6qIbtZ2Q3UXpunKOCTW2tvPM1np1qom1/fyUcA+/w
   uptx
   -----END CERTIFICATE-----
   <CODE ENDS>

C.2. Примеры процессов

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

Для удобства вывод asn1parse был ограничен 68 без перевода строк.

C.2.1. От заявителя к регистратору

Как описано в параграфе 5.2, заявитель подписывает свой voucher-request, содержащий открытый ключ регистратора в поле proximity-registrar-cert. Кодировка base64 ниже для удобства представлена с размером строк 60 символов.

   <CODE BEGINS> file "vr_00-D0-E5-F2-00-02.b64"
   MIIGcAYJKoZIhvcNAQcCoIIGYTCCBl0CAQExDTALBglghkgBZQMEAgEwggOJBgkqhkiG
   9w0BBwGgggN6BIIDdnsiaWV0Zi12b3VjaGVyLXJlcXVlc3Q6dm91Y2hlciI6eyJhc3Nl
   cnRpb24iOiJwcm94aW1pdHkiLCJjcmVhdGVkLW9uIjoiMjAyMS0wNC0xM1QxNzo0Mzoy
   My43NDctMDQ6MDAiLCJzZXJpYWwtbnVtYmVyIjoiMDAtRDAtRTUtRjItMDAtMDIiLCJu
   b25jZSI6Ii1fWEU5eks5cThMbDFxeWxNdExLZWciLCJwcm94aW1pdHktcmVnaXN0cmFy
   LWNlcnQiOiJNSUlCL0RDQ0FZS2dBd0lCQWdJRVA1aWJVakFLQmdncWhrak9QUVFEQWpC
   dE1SSXdFQVlLQ1pJbWlaUHlMR1FCR1JZQ1kyRXhHVEFYQmdvSmtpYUprL0lzWkFFWkZn
   bHpZVzVrWld4dFlXNHhQREE2QmdOVkJBTU1NMlp2ZFc1MFlXbHVMWFJsYzNRdVpYaGhi
   WEJzWlM1amIyMGdWVzV6ZEhKMWJtY2dSbTkxYm5SaGFXNGdVbTl2ZENCRFFUQWVGdzB5
   TURBeU1qVXlNVE14TlRSYUZ3MHlNakF5TWpReU1UTXhOVFJhTUZNeEVqQVFCZ29Ka2lh
   SmsvSXNaQUVaRmdKallURVpNQmNHQ2dtU0pvbVQ4aXhrQVJrV0NYTmhibVJsYkcxaGJq
   RWlNQ0FHQTFVRUF3d1pabTkxYm5SaGFXNHRkR1Z6ZEM1bGVHRnRjR3hsTG1OdmJUQlpN
   Qk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJKWmxVSEkwdXAvbDNlWmY5dkNC
   YitsSW5vRU1FZ2M3Um8rWFpDdGpBSTBDRDFmSmZKUi9oSXl5RG1IV3lZaU5GYlJDSDlm
   eWFyZmt6Z1g0cDB6VGl6cWpLakFvTUJZR0ExVWRKUUVCL3dRTU1Bb0dDQ3NHQVFVRkJ3
   TWNNQTRHQTFVZER3RUIvd1FFQXdJSGdEQUtCZ2dxaGtqT1BRUURBZ05vQURCbEFqQm1U
   MkJNVlVnZWxnZjQzUis1eUJLTlJUYUhteVBBdkx2eHl6MG1GVlp2WHgrLzFSd09hZ212
   RzNhWG1Sa2ovWDRDTVFDOHJNTkJzTG9OcjFMNW5HNTZmd0FkSThoaUFXRzhTOFhBUjVr
   MUNneDNZVVFCU2dkU2NGY0FkZisrQnc2WXkrVT0ifX2gggGyMIIBrjCCATWgAwIBAgIE
   DYOv2TAKBggqhkjOPQQDAjAmMSQwIgYDVQQDDBtoaWdod2F5LXRlc3QuZXhhbXBsZS5j
   b20gQ0EwIBcNMjEwNDEzMjAzNzM5WhgPMjk5OTEyMzEwMDAwMDBaMBwxGjAYBgNVBAUM
   ETAwLUQwLUU1LUYyLTAwLTAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEA6N1Q4ez
   fMAKmoecrfb0OBMc1AyEH+BATkF58FsTSyBxs0SbSWLxFjDOuwB9gLGn2TsTUJumJ6VP
   w5Z/TP4hJ6NZMFcwHQYDVR0OBBYEFEWIzJaWAGQ3sLojZWRkVAgGbFatMAkGA1UdEwQC
   MAAwKwYIKwYBBQUHASAEHxYdaGlnaHdheS10ZXN0LmV4YW1wbGUuY29tOjk0NDMwCgYI
   KoZIzj0EAwIDZwAwZAIwTmlG8sXkKGNbwbKQcYMapFbmSbnHHURFUoFuRqvbgYX7FlXp
   BczfwF2kllNuujigAjAow1kc4r55EmiH+OMEXjBNlWlBSZC5QuJjEf0Jsmxssc+pucjO
   J4ShqnexMEy7bjAxggEEMIIBAAIBATAuMCYxJDAiBgNVBAMMG2hpZ2h3YXktdGVzdC5l
   eGFtcGxlLmNvbSBDQQIEDYOv2TALBglghkgBZQMEAgGgaTAYBgkqhkiG9w0BCQMxCwYJ
   KoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0yMTA0MTMyMTQzMjNaMC8GCSqGSIb3DQEJ
   BDEiBCBJwhyYibIjeqeR3bOaLURzMlGrc3F2X+kvJ1errtoCtTAKBggqhkjOPQQDAgRH
   MEUCIQCmYuCE61HFQXH/E16GDOCsVquDtgr+Q/6/Du/9QkzA7gIgf7MFhAIPW2PNwRa2
   vZFQAKXUbimkiHKzXBA8md0VHbU=
   <CODE ENDS>

Декодирование ASN1 артефакта из файла examples/vr_00-D0-E5-F2-00-02.b64 имеет вид

    0:d=0  hl=4 l=1648 cons: SEQUENCE
    4:d=1  hl=2 l=   9 prim: OBJECT            :pkcs7-signedData
   15:d=1  hl=4 l=1633 cons: cont [ 0 ]
   19:d=2  hl=4 l=1629 cons: SEQUENCE
   23:d=3  hl=2 l=   1 prim: INTEGER           :01
   26:d=3  hl=2 l=  13 cons: SET
   28:d=4  hl=2 l=  11 cons: SEQUENCE
   30:d=5  hl=2 l=   9 prim: OBJECT            :sha256
   41:d=3  hl=4 l= 905 cons: SEQUENCE
   45:d=4  hl=2 l=   9 prim: OBJECT            :pkcs7-data
   56:d=4  hl=4 l= 890 cons: cont [ 0 ]
   60:d=5  hl=4 l= 886 prim: OCTET STRING      :{"ietf-voucher-request:v
  950:d=3  hl=4 l= 434 cons: cont [ 0 ]
  954:d=4  hl=4 l= 430 cons: SEQUENCE
  958:d=5  hl=4 l= 309 cons: SEQUENCE
  962:d=6  hl=2 l=   3 cons: cont [ 0 ]
  964:d=7  hl=2 l=   1 prim: INTEGER           :02
  967:d=6  hl=2 l=   4 prim: INTEGER           :0D83AFD9
  973:d=6  hl=2 l=  10 cons: SEQUENCE
  975:d=7  hl=2 l=   8 prim: OBJECT            :ecdsa-with-SHA256
  985:d=6  hl=2 l=  38 cons: SEQUENCE
  987:d=7  hl=2 l=  36 cons: SET
  989:d=8  hl=2 l=  34 cons: SEQUENCE
  991:d=9  hl=2 l=   3 prim: OBJECT            :commonName
  996:d=9  hl=2 l=  27 prim: UTF8STRING        :highway-test.example.com
 1025:d=6  hl=2 l=  32 cons: SEQUENCE
 1027:d=7  hl=2 l=  13 prim: UTCTIME           :210413203739Z
 1042:d=7  hl=2 l=  15 prim: GENERALIZEDTIME   :29991231000000Z
 1059:d=6  hl=2 l=  28 cons: SEQUENCE
 1061:d=7  hl=2 l=  26 cons: SET
 1063:d=8  hl=2 l=  24 cons: SEQUENCE
 1065:d=9  hl=2 l=   3 prim: OBJECT            :serialNumber
 1070:d=9  hl=2 l=  17 prim: UTF8STRING        :00-D0-E5-F2-00-02
 1089:d=6  hl=2 l=  89 cons: SEQUENCE
 1091:d=7  hl=2 l=  19 cons: SEQUENCE
 1093:d=8  hl=2 l=   7 prim: OBJECT            :id-ecPublicKey
 1102:d=8  hl=2 l=   8 prim: OBJECT            :prime256v1
 1112:d=7  hl=2 l=  66 prim: BIT STRING
 1180:d=6  hl=2 l=  89 cons: cont [ 3 ]
 1182:d=7  hl=2 l=  87 cons: SEQUENCE
 1184:d=8  hl=2 l=  29 cons: SEQUENCE
 1186:d=9  hl=2 l=   3 prim: OBJECT            :X509v3 Subject Key Ident
 1191:d=9  hl=2 l=  22 prim: OCTET STRING      [HEX DUMP]:04144588CC9696
 1215:d=8  hl=2 l=   9 cons: SEQUENCE
 1217:d=9  hl=2 l=   3 prim: OBJECT            :X509v3 Basic Constraints
 1222:d=9  hl=2 l=   2 prim: OCTET STRING      [HEX DUMP]:3000
 1226:d=8  hl=2 l=  43 cons: SEQUENCE
 1228:d=9  hl=2 l=   8 prim: OBJECT            :1.3.6.1.5.5.7.1.32
 1238:d=9  hl=2 l=  31 prim: OCTET STRING      [HEX DUMP]:161D6869676877
 1271:d=5  hl=2 l=  10 cons: SEQUENCE
 1273:d=6  hl=2 l=   8 prim: OBJECT            :ecdsa-with-SHA256
 1283:d=5  hl=2 l= 103 prim: BIT STRING
 1388:d=3  hl=4 l= 260 cons: SET
 1392:d=4  hl=4 l= 256 cons: SEQUENCE
 1396:d=5  hl=2 l=   1 prim: INTEGER           :01
 1399:d=5  hl=2 l=  46 cons: SEQUENCE
 1401:d=6  hl=2 l=  38 cons: SEQUENCE
 1403:d=7  hl=2 l=  36 cons: SET
 1405:d=8  hl=2 l=  34 cons: SEQUENCE
 1407:d=9  hl=2 l=   3 prim: OBJECT            :commonName
 1412:d=9  hl=2 l=  27 prim: UTF8STRING        :highway-test.example.com
 1441:d=6  hl=2 l=   4 prim: INTEGER           :0D83AFD9
 1447:d=5  hl=2 l=  11 cons: SEQUENCE
 1449:d=6  hl=2 l=   9 prim: OBJECT            :sha256
 1460:d=5  hl=2 l= 105 cons: cont [ 0 ]
 1462:d=6  hl=2 l=  24 cons: SEQUENCE
 1464:d=7  hl=2 l=   9 prim: OBJECT            :contentType
 1475:d=7  hl=2 l=  11 cons: SET
 1477:d=8  hl=2 l=   9 prim: OBJECT            :pkcs7-data
 1488:d=6  hl=2 l=  28 cons: SEQUENCE
 1490:d=7  hl=2 l=   9 prim: OBJECT            :signingTime
 1501:d=7  hl=2 l=  15 cons: SET
 1503:d=8  hl=2 l=  13 prim: UTCTIME           :210413214323Z
 1518:d=6  hl=2 l=  47 cons: SEQUENCE
 1520:d=7  hl=2 l=   9 prim: OBJECT            :messageDigest
 1531:d=7  hl=2 l=  34 cons: SET
 1533:d=8  hl=2 l=  32 prim: OCTET STRING      [HEX DUMP]:49C21C9889B223
 1567:d=5  hl=2 l=  10 cons: SEQUENCE
 1569:d=6  hl=2 l=   8 prim: OBJECT            :ecdsa-with-SHA256
 1579:d=5  hl=2 l=  71 prim: OCTET STRING      [HEX DUMP]:3045022100A662

Код JSON, содержащийся в voucher-request, имеет вид

   {"ietf-voucher-request:voucher":{"assertion":"proximity","cr
   eated-on":"2021-04-13T17:43:23.747-04:00","serial-number":"0
   0-D0-E5-F2-00-02","nonce":"-_XE9zK9q8Ll1qylMtLKeg","proximit
   y-registrar-cert":"MIIB/DCCAYKgAwIBAgIEP5ibUjAKBggqhkjOPQQDA
   jBtMRIwEAYKCZImiZPyLGQBGRYCY2ExGTAXBgoJkiaJk/IsZAEZFglzYW5kZ
   WxtYW4xPDA6BgNVBAMMM2ZvdW50YWluLXRlc3QuZXhhbXBsZS5jb20gVW5zd
   HJ1bmcgRm91bnRhaW4gUm9vdCBDQTAeFw0yMDAyMjUyMTMxNTRaFw0yMjAyM
   jQyMTMxNTRaMFMxEjAQBgoJkiaJk/IsZAEZFgJjYTEZMBcGCgmSJomT8ixkA
   RkWCXNhbmRlbG1hbjEiMCAGA1UEAwwZZm91bnRhaW4tdGVzdC5leGFtcGxlL
   mNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJZlUHI0up/l3eZf9vCBb
   +lInoEMEgc7Ro+XZCtjAI0CD1fJfJR/hIyyDmHWyYiNFbRCH9fyarfkzgX4p
   0zTizqjKjAoMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMcMA4GA1UdDwEB/wQEA
   wIHgDAKBggqhkjOPQQDAgNoADBlAjBmT2BMVUgelgf43R+5yBKNRTaHmyPAv
   Lvxyz0mFVZvXx+/1RwOagmvG3aXmRkj/X4CMQC8rMNBsLoNr1L5nG56fwAdI
   8hiAWG8S8XAR5k1Cgx3YUQBSgdScFcAdf++Bw6Yy+U="}}

C.2.2. От регистратора к MASA

Как указано в параграфе 5.5, регистратор подписывает свой voucher-request и включает voucher-request заявителя в prior-signed-voucher-request.

   <CODE BEGINS> file "parboiled_vr_00-D0-E5-F2-00-02.b64"
   MIIPYwYJKoZIhvcNAQcCoIIPVDCCD1ACAQExDTALBglghkgBZQMEAgEwggl4BgkqhkiG
   9w0BBwGggglpBIIJZXsiaWV0Zi12b3VjaGVyLXJlcXVlc3Q6dm91Y2hlciI6eyJhc3Nl
   cnRpb24iOiJwcm94aW1pdHkiLCJjcmVhdGVkLW9uIjoiMjAyMS0wNC0xM1QyMTo0Mzoy
   My43ODdaIiwic2VyaWFsLW51bWJlciI6IjAwLUQwLUU1LUYyLTAwLTAyIiwibm9uY2Ui
   OiItX1hFOXpLOXE4TGwxcXlsTXRMS2VnIiwicHJpb3Itc2lnbmVkLXZvdWNoZXItcmVx
   dWVzdCI6Ik1JSUdjQVlKS29aSWh2Y05BUWNDb0lJR1lUQ0NCbDBDQVFFeERUQUxCZ2xn
   aGtnQlpRTUVBZ0V3Z2dPSkJna3Foa2lHOXcwQkJ3R2dnZ042QklJRGRuc2lhV1YwWmkx
   MmIzVmphR1Z5TFhKbGNYVmxjM1E2ZG05MVkyaGxjaUk2ZXlKaGMzTmxjblJwYjI0aU9p
   SndjbTk0YVcxcGRIa2lMQ0pqY21WaGRHVmtMVzl1SWpvaU1qQXlNUzB3TkMweE0xUXhO
   em8wTXpveU15NDNORGN0TURRNk1EQWlMQ0p6WlhKcFlXd3RiblZ0WW1WeUlqb2lNREF0
   UkRBdFJUVXRSakl0TURBdE1ESWlMQ0p1YjI1alpTSTZJaTFmV0VVNWVrczVjVGhNYkRG
   eGVXeE5kRXhMWldjaUxDSndjbTk0YVcxcGRIa3RjbVZuYVhOMGNtRnlMV05sY25RaU9p
   Sk5TVWxDTDBSRFEwRlpTMmRCZDBsQ1FXZEpSVkExYVdKVmFrRkxRbWRuY1docmFrOVFV
   VkZFUVdwQ2RFMVNTWGRGUVZsTFExcEpiV2xhVUhsTVIxRkNSMUpaUTFreVJYaEhWRUZZ
   UW1kdlNtdHBZVXByTDBseldrRkZXa1puYkhwWlZ6VnJXbGQ0ZEZsWE5IaFFSRUUyUW1k
   T1ZrSkJUVTFOTWxwMlpGYzFNRmxYYkhWTVdGSnNZek5SZFZwWWFHaGlXRUp6V2xNMWFt
   SXlNR2RXVnpWNlpFaEtNV0p0WTJkU2JUa3hZbTVTYUdGWE5HZFZiVGwyWkVOQ1JGRlVR
   V1ZHZHpCNVRVUkJlVTFxVlhsTlZFMTRUbFJTWVVaM01IbE5ha0Y1VFdwUmVVMVVUWGhP
   VkZKaFRVWk5lRVZxUVZGQ1oyOUthMmxoU21zdlNYTmFRVVZhUm1kS2FsbFVSVnBOUW1O
   SFEyZHRVMHB2YlZRNGFYaHJRVkpyVjBOWVRtaGliVkpzWWtjeGFHSnFSV2xOUTBGSFFU
   RlZSVUYzZDFwYWJUa3hZbTVTYUdGWE5IUmtSMVo2WkVNMWJHVkhSblJqUjNoc1RHMU9k
   bUpVUWxwTlFrMUhRbmx4UjFOTk5EbEJaMFZIUTBOeFIxTk5ORGxCZDBWSVFUQkpRVUpL
   V214VlNFa3dkWEF2YkRObFdtWTVka05DWWl0c1NXNXZSVTFGWjJNM1VtOHJXRnBEZEdw
   QlNUQkRSREZtU21aS1VpOW9TWGw1UkcxSVYzbFphVTVHWWxKRFNEbG1lV0Z5Wm10Nlox
   ZzBjREI2VkdsNmNXcExha0Z2VFVKWlIwRXhWV1JLVVVWQ0wzZFJUVTFCYjBkRFEzTkhR
   VkZWUmtKM1RXTk5RVFJIUVRGVlpFUjNSVUl2ZDFGRlFYZEpTR2RFUVV0Q1oyZHhhR3Rx
   VDFCUlVVUkJaMDV2UVVSQ2JFRnFRbTFVTWtKTlZsVm5aV3huWmpRelVpczFlVUpMVGxK
   VVlVaHRlVkJCZGt4MmVIbDZNRzFHVmxwMldIZ3JMekZTZDA5aFoyMTJSek5oV0cxU2Ey
   b3ZXRFJEVFZGRE9ISk5Ua0p6VEc5T2NqRk1OVzVITlRabWQwRmtTVGhvYVVGWFJ6aFRP
   RmhCVWpWck1VTm5lRE5aVlZGQ1UyZGtVMk5HWTBGa1ppc3JRbmMyV1hrclZUMGlmWDJn
   Z2dHeU1JSUJyakNDQVRXZ0F3SUJBZ0lFRFlPdjJUQUtCZ2dxaGtqT1BRUURBakFtTVNR
   d0lnWURWUVFEREJ0b2FXZG9kMkY1TFhSbGMzUXVaWGhoYlhCc1pTNWpiMjBnUTBFd0lC
   Y05NakV3TkRFek1qQXpOek01V2hnUE1qazVPVEV5TXpFd01EQXdNREJhTUJ3eEdqQVlC
   Z05WQkFVTUVUQXdMVVF3TFVVMUxVWXlMVEF3TFRBeU1Ga3dFd1lIS29aSXpqMENBUVlJ
   S29aSXpqMERBUWNEUWdBRUE2TjFRNGV6Zk1BS21vZWNyZmIwT0JNYzFBeUVIK0JBVGtG
   NThGc1RTeUJ4czBTYlNXTHhGakRPdXdCOWdMR24yVHNUVUp1bUo2VlB3NVovVFA0aEo2
   TlpNRmN3SFFZRFZSME9CQllFRkVXSXpKYVdBR1Ezc0xvalpXUmtWQWdHYkZhdE1Ba0dB
   MVVkRXdRQ01BQXdLd1lJS3dZQkJRVUhBU0FFSHhZZGFHbG5hSGRoZVMxMFpYTjBMbVY0
   WVcxd2JHVXVZMjl0T2prME5ETXdDZ1lJS29aSXpqMEVBd0lEWndBd1pBSXdUbWxHOHNY
   a0tHTmJ3YktRY1lNYXBGYm1TYm5ISFVSRlVvRnVScXZiZ1lYN0ZsWHBCY3pmd0Yya2xs
   TnV1amlnQWpBb3cxa2M0cjU1RW1pSCtPTUVYakJObFdsQlNaQzVRdUpqRWYwSnNteHNz
   YytwdWNqT0o0U2hxbmV4TUV5N2JqQXhnZ0VFTUlJQkFBSUJBVEF1TUNZeEpEQWlCZ05W
   QkFNTUcyaHBaMmgzWVhrdGRHVnpkQzVsZUdGdGNHeGxMbU52YlNCRFFRSUVEWU92MlRB
   TEJnbGdoa2dCWlFNRUFnR2dhVEFZQmdrcWhraUc5dzBCQ1FNeEN3WUpLb1pJaHZjTkFR
   Y0JNQndHQ1NxR1NJYjNEUUVKQlRFUEZ3MHlNVEEwTVRNeU1UUXpNak5hTUM4R0NTcUdT
   SWIzRFFFSkJERWlCQ0JKd2h5WWliSWplcWVSM2JPYUxVUnpNbEdyYzNGMlgra3ZKMWVy
   cnRvQ3RUQUtCZ2dxaGtqT1BRUURBZ1JITUVVQ0lRQ21ZdUNFNjFIRlFYSC9FMTZHRE9D
   c1ZxdUR0Z3IrUS82L0R1LzlRa3pBN2dJZ2Y3TUZoQUlQVzJQTndSYTJ2WkZRQUtYVWJp
   bWtpSEt6WEJBOG1kMFZIYlU9In19oIIEbzCCAfwwggGCoAMCAQICBD+Ym1IwCgYIKoZI
   zj0EAwIwbTESMBAGCgmSJomT8ixkARkWAmNhMRkwFwYKCZImiZPyLGQBGRYJc2FuZGVs
   bWFuMTwwOgYDVQQDDDNmb3VudGFpbi10ZXN0LmV4YW1wbGUuY29tIFVuc3RydW5nIEZv
   dW50YWluIFJvb3QgQ0EwHhcNMjAwMjI1MjEzMTU0WhcNMjIwMjI0MjEzMTU0WjBTMRIw
   EAYKCZImiZPyLGQBGRYCY2ExGTAXBgoJkiaJk/IsZAEZFglzYW5kZWxtYW4xIjAgBgNV
   BAMMGWZvdW50YWluLXRlc3QuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMB
   BwNCAASWZVByNLqf5d3mX/bwgW/pSJ6BDBIHO0aPl2QrYwCNAg9XyXyUf4SMsg5h1smI
   jRW0Qh/X8mq35M4F+KdM04s6oyowKDAWBgNVHSUBAf8EDDAKBggrBgEFBQcDHDAOBgNV
   HQ8BAf8EBAMCB4AwCgYIKoZIzj0EAwIDaAAwZQIwZk9gTFVIHpYH+N0fucgSjUU2h5sj
   wLy78cs9JhVWb18fv9UcDmoJrxt2l5kZI/1+AjEAvKzDQbC6Da9S+Zxuen8AHSPIYgFh
   vEvFwEeZNQoMd2FEAUoHUnBXAHX/vgcOmMvlMIICazCCAfKgAwIBAgIEKWsGWTAKBggq
   hkjOPQQDAjBtMRIwEAYKCZImiZPyLGQBGRYCY2ExGTAXBgoJkiaJk/IsZAEZFglzYW5k
   ZWxtYW4xPDA6BgNVBAMMM2ZvdW50YWluLXRlc3QuZXhhbXBsZS5jb20gVW5zdHJ1bmcg
   Rm91bnRhaW4gUm9vdCBDQTAeFw0yMDAyMjUyMTMxNDVaFw0yMjAyMjQyMTMxNDVaMG0x
   EjAQBgoJkiaJk/IsZAEZFgJjYTEZMBcGCgmSJomT8ixkARkWCXNhbmRlbG1hbjE8MDoG
   A1UEAwwzZm91bnRhaW4tdGVzdC5leGFtcGxlLmNvbSBVbnN0cnVuZyBGb3VudGFpbiBS
   b290IENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEG39ZuhfDGrxmjYxs4MP6MXEPZfYi
   kb23VoAH29+4eqVFTXmKRpcZWZYxsY9pfTK+PMg+W2O1Rvao1W+b+cDz07kUP3JHUaR2
   3dLwv/XKjzABf/jCX9P1IANEi4vyB2y0o2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
   DwEB/wQEAwIBBjAdBgNVHQ4EFgQUuaX2yxHhB6RJLKcIxnwQvIezdCYwHwYDVR0jBBgw
   FoAUuaX2yxHhB6RJLKcIxnwQvIezdCYwCgYIKoZIzj0EAwIDZwAwZAIwIIMGzo2YpFR6
   ZkxKOnDCUjZaUo1ZfSCbKmkUWIc42FV53f0pOJUekZN2tPVmKUS0AjBvOPmvEu0w1YUp
   fLEWWL1nkUPEDTD52BysLwbdvNUGQiyEogTqAqRfF1Em+9kv0lwxggFLMIIBRwIBATB1
   MG0xEjAQBgoJkiaJk/IsZAEZFgJjYTEZMBcGCgmSJomT8ixkARkWCXNhbmRlbG1hbjE8
   MDoGA1UEAwwzZm91bnRhaW4tdGVzdC5leGFtcGxlLmNvbSBVbnN0cnVuZyBGb3VudGFp
   biBSb290IENBAgQ/mJtSMAsGCWCGSAFlAwQCAaBpMBgGCSqGSIb3DQEJAzELBgkqhkiG
   9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTIxMDQxMzIxNDMyM1owLwYJKoZIhvcNAQkEMSIE
   IEnOrdWjlG70K74IhCJ7UXi+wPS+r2C8DFEqjabGP+G8MAoGCCqGSM49BAMCBEcwRQIh
   AMhO3M+tSWb2wKTBOXPArN+XvjSzAhaQA/uLj3qhPwi/AiBDDthf6mjMuirqXE0yjMif
   C2UY9oNUFF9Nl0wEQpBBAA==
   <CODE ENDS>

Ниже представлено декодирование ASN1 артефакта из файла examples/parboiled_vr_00_D0-E5-02-00-2D.b64.

    0:d=0  hl=4 l=3939 cons: SEQUENCE
    4:d=1  hl=2 l=   9 prim: OBJECT            :pkcs7-signedData
   15:d=1  hl=4 l=3924 cons: cont [ 0 ]
   19:d=2  hl=4 l=3920 cons: SEQUENCE
   23:d=3  hl=2 l=   1 prim: INTEGER           :01
   26:d=3  hl=2 l=  13 cons: SET
   28:d=4  hl=2 l=  11 cons: SEQUENCE
   30:d=5  hl=2 l=   9 prim: OBJECT            :sha256
   41:d=3  hl=4 l=2424 cons: SEQUENCE
   45:d=4  hl=2 l=   9 prim: OBJECT            :pkcs7-data
   56:d=4  hl=4 l=2409 cons: cont [ 0 ]
   60:d=5  hl=4 l=2405 prim: OCTET STRING      :{"ietf-voucher-request:v
 2469:d=3  hl=4 l=1135 cons: cont [ 0 ]
 2473:d=4  hl=4 l= 508 cons: SEQUENCE
 2477:d=5  hl=4 l= 386 cons: SEQUENCE
 2481:d=6  hl=2 l=   3 cons: cont [ 0 ]
 2483:d=7  hl=2 l=   1 prim: INTEGER           :02
 2486:d=6  hl=2 l=   4 prim: INTEGER           :3F989B52
 2492:d=6  hl=2 l=  10 cons: SEQUENCE
 2494:d=7  hl=2 l=   8 prim: OBJECT            :ecdsa-with-SHA256
 2504:d=6  hl=2 l= 109 cons: SEQUENCE
 2506:d=7  hl=2 l=  18 cons: SET
 2508:d=8  hl=2 l=  16 cons: SEQUENCE
 2510:d=9  hl=2 l=  10 prim: OBJECT            :domainComponent
 2522:d=9  hl=2 l=   2 prim: IA5STRING         :ca
 2526:d=7  hl=2 l=  25 cons: SET
 2528:d=8  hl=2 l=  23 cons: SEQUENCE
 2530:d=9  hl=2 l=  10 prim: OBJECT            :domainComponent
 2542:d=9  hl=2 l=   9 prim: IA5STRING         :sandelman
 2553:d=7  hl=2 l=  60 cons: SET
 2555:d=8  hl=2 l=  58 cons: SEQUENCE
 2557:d=9  hl=2 l=   3 prim: OBJECT            :commonName
 2562:d=9  hl=2 l=  51 prim: UTF8STRING        :fountain-test.example.co
 2615:d=6  hl=2 l=  30 cons: SEQUENCE
 2617:d=7  hl=2 l=  13 prim: UTCTIME           :200225213154Z
 2632:d=7  hl=2 l=  13 prim: UTCTIME           :220224213154Z
 2647:d=6  hl=2 l=  83 cons: SEQUENCE
 2649:d=7  hl=2 l=  18 cons: SET
 2651:d=8  hl=2 l=  16 cons: SEQUENCE
 2653:d=9  hl=2 l=  10 prim: OBJECT            :domainComponent
 2665:d=9  hl=2 l=   2 prim: IA5STRING         :ca
 2669:d=7  hl=2 l=  25 cons: SET
 2671:d=8  hl=2 l=  23 cons: SEQUENCE
 2673:d=9  hl=2 l=  10 prim: OBJECT            :domainComponent
 2685:d=9  hl=2 l=   9 prim: IA5STRING         :sandelman
 2696:d=7  hl=2 l=  34 cons: SET
 2698:d=8  hl=2 l=  32 cons: SEQUENCE
 2700:d=9  hl=2 l=   3 prim: OBJECT            :commonName
 2705:d=9  hl=2 l=  25 prim: UTF8STRING        :fountain-test.example.co
 2732:d=6  hl=2 l=  89 cons: SEQUENCE
 2734:d=7  hl=2 l=  19 cons: SEQUENCE
 2736:d=8  hl=2 l=   7 prim: OBJECT            :id-ecPublicKey
 2745:d=8  hl=2 l=   8 prim: OBJECT            :prime256v1
 2755:d=7  hl=2 l=  66 prim: BIT STRING
 2823:d=6  hl=2 l=  42 cons: cont [ 3 ]
 2825:d=7  hl=2 l=  40 cons: SEQUENCE
 2827:d=8  hl=2 l=  22 cons: SEQUENCE
 2829:d=9  hl=2 l=   3 prim: OBJECT            :X509v3 Extended Key Usag
 2834:d=9  hl=2 l=   1 prim: BOOLEAN           :255
 2837:d=9  hl=2 l=  12 prim: OCTET STRING      [HEX DUMP]:300A06082B0601
 2851:d=8  hl=2 l=  14 cons: SEQUENCE
 2853:d=9  hl=2 l=   3 prim: OBJECT            :X509v3 Key Usage
 2858:d=9  hl=2 l=   1 prim: BOOLEAN           :255
 2861:d=9  hl=2 l=   4 prim: OCTET STRING      [HEX DUMP]:03020780
 2867:d=5  hl=2 l=  10 cons: SEQUENCE
 2869:d=6  hl=2 l=   8 prim: OBJECT            :ecdsa-with-SHA256
 2879:d=5  hl=2 l= 104 prim: BIT STRING
 2985:d=4  hl=4 l= 619 cons: SEQUENCE
 2989:d=5  hl=4 l= 498 cons: SEQUENCE
 2993:d=6  hl=2 l=   3 cons: cont [ 0 ]
 2995:d=7  hl=2 l=   1 prim: INTEGER           :02
 2998:d=6  hl=2 l=   4 prim: INTEGER           :296B0659
 3004:d=6  hl=2 l=  10 cons: SEQUENCE
 3006:d=7  hl=2 l=   8 prim: OBJECT            :ecdsa-with-SHA256
 3016:d=6  hl=2 l= 109 cons: SEQUENCE
 3018:d=7  hl=2 l=  18 cons: SET
 3020:d=8  hl=2 l=  16 cons: SEQUENCE
 3022:d=9  hl=2 l=  10 prim: OBJECT            :domainComponent
 3034:d=9  hl=2 l=   2 prim: IA5STRING         :ca
 3038:d=7  hl=2 l=  25 cons: SET
 3040:d=8  hl=2 l=  23 cons: SEQUENCE
 3042:d=9  hl=2 l=  10 prim: OBJECT            :domainComponent
 3054:d=9  hl=2 l=   9 prim: IA5STRING         :sandelman
 3065:d=7  hl=2 l=  60 cons: SET
 3067:d=8  hl=2 l=  58 cons: SEQUENCE
 3069:d=9  hl=2 l=   3 prim: OBJECT            :commonName
 3074:d=9  hl=2 l=  51 prim: UTF8STRING        :fountain-test.example.co
 3127:d=6  hl=2 l=  30 cons: SEQUENCE
 3129:d=7  hl=2 l=  13 prim: UTCTIME           :200225213145Z
 3144:d=7  hl=2 l=  13 prim: UTCTIME           :220224213145Z
 3159:d=6  hl=2 l= 109 cons: SEQUENCE
 3161:d=7  hl=2 l=  18 cons: SET
 3163:d=8  hl=2 l=  16 cons: SEQUENCE
 3165:d=9  hl=2 l=  10 prim: OBJECT            :domainComponent
 3177:d=9  hl=2 l=   2 prim: IA5STRING         :ca
 3181:d=7  hl=2 l=  25 cons: SET
 3183:d=8  hl=2 l=  23 cons: SEQUENCE
 3185:d=9  hl=2 l=  10 prim: OBJECT            :domainComponent
 3197:d=9  hl=2 l=   9 prim: IA5STRING         :sandelman
 3208:d=7  hl=2 l=  60 cons: SET
 3210:d=8  hl=2 l=  58 cons: SEQUENCE
 3212:d=9  hl=2 l=   3 prim: OBJECT            :commonName
 3217:d=9  hl=2 l=  51 prim: UTF8STRING        :fountain-test.example.co
 3270:d=6  hl=2 l= 118 cons: SEQUENCE
 3272:d=7  hl=2 l=  16 cons: SEQUENCE
 3274:d=8  hl=2 l=   7 prim: OBJECT            :id-ecPublicKey
 3283:d=8  hl=2 l=   5 prim: OBJECT            :secp384r1
 3290:d=7  hl=2 l=  98 prim: BIT STRING
 3390:d=6  hl=2 l=  99 cons: cont [ 3 ]
 3392:d=7  hl=2 l=  97 cons: SEQUENCE
 3394:d=8  hl=2 l=  15 cons: SEQUENCE
 3396:d=9  hl=2 l=   3 prim: OBJECT            :X509v3 Basic Constraints
 3401:d=9  hl=2 l=   1 prim: BOOLEAN           :255
 3404:d=9  hl=2 l=   5 prim: OCTET STRING      [HEX DUMP]:30030101FF
 3411:d=8  hl=2 l=  14 cons: SEQUENCE
 3413:d=9  hl=2 l=   3 prim: OBJECT            :X509v3 Key Usage
 3418:d=9  hl=2 l=   1 prim: BOOLEAN           :255
 3421:d=9  hl=2 l=   4 prim: OCTET STRING      [HEX DUMP]:03020106
 3427:d=8  hl=2 l=  29 cons: SEQUENCE
 3429:d=9  hl=2 l=   3 prim: OBJECT            :X509v3 Subject Key Ident
 3434:d=9  hl=2 l=  22 prim: OCTET STRING      [HEX DUMP]:0414B9A5F6CB11
 3458:d=8  hl=2 l=  31 cons: SEQUENCE
 3460:d=9  hl=2 l=   3 prim: OBJECT            :X509v3 Authority Key Ide
 3465:d=9  hl=2 l=  24 prim: OCTET STRING      [HEX DUMP]:30168014B9A5F6
 3491:d=5  hl=2 l=  10 cons: SEQUENCE
 3493:d=6  hl=2 l=   8 prim: OBJECT            :ecdsa-with-SHA256
 3503:d=5  hl=2 l= 103 prim: BIT STRING
 3608:d=3  hl=4 l= 331 cons: SET
 3612:d=4  hl=4 l= 327 cons: SEQUENCE
 3616:d=5  hl=2 l=   1 prim: INTEGER           :01
 3619:d=5  hl=2 l= 117 cons: SEQUENCE
 3621:d=6  hl=2 l= 109 cons: SEQUENCE
 3623:d=7  hl=2 l=  18 cons: SET
 3625:d=8  hl=2 l=  16 cons: SEQUENCE
 3627:d=9  hl=2 l=  10 prim: OBJECT            :domainComponent
 3639:d=9  hl=2 l=   2 prim: IA5STRING         :ca
 3643:d=7  hl=2 l=  25 cons: SET
 3645:d=8  hl=2 l=  23 cons: SEQUENCE
 3647:d=9  hl=2 l=  10 prim: OBJECT            :domainComponent
 3659:d=9  hl=2 l=   9 prim: IA5STRING         :sandelman
 3670:d=7  hl=2 l=  60 cons: SET
 3672:d=8  hl=2 l=  58 cons: SEQUENCE
 3674:d=9  hl=2 l=   3 prim: OBJECT            :commonName
 3679:d=9  hl=2 l=  51 prim: UTF8STRING        :fountain-test.example.co
 3732:d=6  hl=2 l=   4 prim: INTEGER           :3F989B52
 3738:d=5  hl=2 l=  11 cons: SEQUENCE
 3740:d=6  hl=2 l=   9 prim: OBJECT            :sha256
 3751:d=5  hl=2 l= 105 cons: cont [ 0 ]
 3753:d=6  hl=2 l=  24 cons: SEQUENCE
 3755:d=7  hl=2 l=   9 prim: OBJECT            :contentType
 3766:d=7  hl=2 l=  11 cons: SET
 3768:d=8  hl=2 l=   9 prim: OBJECT            :pkcs7-data
 3779:d=6  hl=2 l=  28 cons: SEQUENCE
 3781:d=7  hl=2 l=   9 prim: OBJECT            :signingTime
 3792:d=7  hl=2 l=  15 cons: SET
 3794:d=8  hl=2 l=  13 prim: UTCTIME           :210413214323Z
 3809:d=6  hl=2 l=  47 cons: SEQUENCE
 3811:d=7  hl=2 l=   9 prim: OBJECT            :messageDigest
 3822:d=7  hl=2 l=  34 cons: SET
 3824:d=8  hl=2 l=  32 prim: OCTET STRING      [HEX DUMP]:49CEADD5A3946E
 3858:d=5  hl=2 l=  10 cons: SEQUENCE
 3860:d=6  hl=2 l=   8 prim: OBJECT            :ecdsa-with-SHA256
 3870:d=5  hl=2 l=  71 prim: OCTET STRING      [HEX DUMP]:3045022100C84E

Код JSON, содержащийся в voucher-request, приведён ниже. Отметим, что предыдущий voucher-request находится в атрибуте prior-signed-voucher-request.

   {"ietf-voucher-request:voucher":{"assertion":"proximity","cr
   eated-on":"2021-04-13T21:43:23.787Z","serial-number":"00-D0-
   E5-F2-00-02","nonce":"-_XE9zK9q8Ll1qylMtLKeg","prior-signed-
   voucher-request":"MIIGcAYJKoZIhvcNAQcCoIIGYTCCBl0CAQExDTALBg
   lghkgBZQMEAgEwggOJBgkqhkiG9w0BBwGgggN6BIIDdnsiaWV0Zi12b3VjaG
   VyLXJlcXVlc3Q6dm91Y2hlciI6eyJhc3NlcnRpb24iOiJwcm94aW1pdHkiLC
   JjcmVhdGVkLW9uIjoiMjAyMS0wNC0xM1QxNzo0MzoyMy43NDctMDQ6MDAiLC
   JzZXJpYWwtbnVtYmVyIjoiMDAtRDAtRTUtRjItMDAtMDIiLCJub25jZSI6Ii
   1fWEU5eks5cThMbDFxeWxNdExLZWciLCJwcm94aW1pdHktcmVnaXN0cmFyLW
   NlcnQiOiJNSUlCL0RDQ0FZS2dBd0lCQWdJRVA1aWJVakFLQmdncWhrak9QUV
   FEQWpCdE1SSXdFQVlLQ1pJbWlaUHlMR1FCR1JZQ1kyRXhHVEFYQmdvSmtpYU
   prL0lzWkFFWkZnbHpZVzVrWld4dFlXNHhQREE2QmdOVkJBTU1NMlp2ZFc1MF
   lXbHVMWFJsYzNRdVpYaGhiWEJzWlM1amIyMGdWVzV6ZEhKMWJtY2dSbTkxYm
   5SaGFXNGdVbTl2ZENCRFFUQWVGdzB5TURBeU1qVXlNVE14TlRSYUZ3MHlNak
   F5TWpReU1UTXhOVFJhTUZNeEVqQVFCZ29Ka2lhSmsvSXNaQUVaRmdKallURV
   pNQmNHQ2dtU0pvbVQ4aXhrQVJrV0NYTmhibVJsYkcxaGJqRWlNQ0FHQTFVRU
   F3d1pabTkxYm5SaGFXNHRkR1Z6ZEM1bGVHRnRjR3hsTG1OdmJUQlpNQk1HQn
   lxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJKWmxVSEkwdXAvbDNlWmY5dk
   NCYitsSW5vRU1FZ2M3Um8rWFpDdGpBSTBDRDFmSmZKUi9oSXl5RG1IV3lZaU
   5GYlJDSDlmeWFyZmt6Z1g0cDB6VGl6cWpLakFvTUJZR0ExVWRKUUVCL3dRTU
   1Bb0dDQ3NHQVFVRkJ3TWNNQTRHQTFVZER3RUIvd1FFQXdJSGdEQUtCZ2dxaG
   tqT1BRUURBZ05vQURCbEFqQm1UMkJNVlVnZWxnZjQzUis1eUJLTlJUYUhteV
   BBdkx2eHl6MG1GVlp2WHgrLzFSd09hZ212RzNhWG1Sa2ovWDRDTVFDOHJNTk
   JzTG9OcjFMNW5HNTZmd0FkSThoaUFXRzhTOFhBUjVrMUNneDNZVVFCU2dkU2
   NGY0FkZisrQnc2WXkrVT0ifX2gggGyMIIBrjCCATWgAwIBAgIEDYOv2TAKBg
   gqhkjOPQQDAjAmMSQwIgYDVQQDDBtoaWdod2F5LXRlc3QuZXhhbXBsZS5jb2
   0gQ0EwIBcNMjEwNDEzMjAzNzM5WhgPMjk5OTEyMzEwMDAwMDBaMBwxGjAYBg
   NVBAUMETAwLUQwLUU1LUYyLTAwLTAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQ
   cDQgAEA6N1Q4ezfMAKmoecrfb0OBMc1AyEH+BATkF58FsTSyBxs0SbSWLxFj
   DOuwB9gLGn2TsTUJumJ6VPw5Z/TP4hJ6NZMFcwHQYDVR0OBBYEFEWIzJaWAG
   Q3sLojZWRkVAgGbFatMAkGA1UdEwQCMAAwKwYIKwYBBQUHASAEHxYdaGlnaH
   dheS10ZXN0LmV4YW1wbGUuY29tOjk0NDMwCgYIKoZIzj0EAwIDZwAwZAIwTm
   lG8sXkKGNbwbKQcYMapFbmSbnHHURFUoFuRqvbgYX7FlXpBczfwF2kllNuuj
   igAjAow1kc4r55EmiH+OMEXjBNlWlBSZC5QuJjEf0Jsmxssc+pucjOJ4Shqn
   exMEy7bjAxggEEMIIBAAIBATAuMCYxJDAiBgNVBAMMG2hpZ2h3YXktdGVzdC
   5leGFtcGxlLmNvbSBDQQIEDYOv2TALBglghkgBZQMEAgGgaTAYBgkqhkiG9w
   0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0yMTA0MTMyMTQzMj
   NaMC8GCSqGSIb3DQEJBDEiBCBJwhyYibIjeqeR3bOaLURzMlGrc3F2X+kvJ1
   errtoCtTAKBggqhkjOPQQDAgRHMEUCIQCmYuCE61HFQXH/E16GDOCsVquDtg
   r+Q/6/Du/9QkzA7gIgf7MFhAIPW2PNwRa2vZFQAKXUbimkiHKzXBA8md0VHb
   U="}}

C.2.3. От MASA к регистратору

Агент MASA возвращает регистратору ваучер, который транслируется заявителю.

   <CODE BEGINS> file "voucher_00-D0-E5-F2-00-02.b64"
   MIIGIgYJKoZIhvcNAQcCoIIGEzCCBg8CAQExDTALBglghkgBZQMEAgEwggN4BgkqhkiG
   9w0BBwGgggNpBIIDZXsiaWV0Zi12b3VjaGVyOnZvdWNoZXIiOnsiYXNzZXJ0aW9uIjoi
   bG9nZ2VkIiwiY3JlYXRlZC1vbiI6IjIwMjEtMDQtMTNUMTc6NDM6MjQuNTg5LTA0OjAw
   Iiwic2VyaWFsLW51bWJlciI6IjAwLUQwLUU1LUYyLTAwLTAyIiwibm9uY2UiOiItX1hF
   OXpLOXE4TGwxcXlsTXRMS2VnIiwicGlubmVkLWRvbWFpbi1jZXJ0IjoiTUlJQi9EQ0NB
   WUtnQXdJQkFnSUVQNWliVWpBS0JnZ3Foa2pPUFFRREFqQnRNUkl3RUFZS0NaSW1pWlB5
   TEdRQkdSWUNZMkV4R1RBWEJnb0praWFKay9Jc1pBRVpGZ2x6WVc1a1pXeHRZVzR4UERB
   NkJnTlZCQU1NTTJadmRXNTBZV2x1TFhSbGMzUXVaWGhoYlhCc1pTNWpiMjBnVlc1emRI
   SjFibWNnUm05MWJuUmhhVzRnVW05dmRDQkRRVEFlRncweU1EQXlNalV5TVRNeE5UUmFG
   dzB5TWpBeU1qUXlNVE14TlRSYU1GTXhFakFRQmdvSmtpYUprL0lzWkFFWkZnSmpZVEVa
   TUJjR0NnbVNKb21UOGl4a0FSa1dDWE5oYm1SbGJHMWhiakVpTUNBR0ExVUVBd3daWm05
   MWJuUmhhVzR0ZEdWemRDNWxlR0Z0Y0d4bExtTnZiVEJaTUJNR0J5cUdTTTQ5QWdFR0ND
   cUdTTTQ5QXdFSEEwSUFCSlpsVUhJMHVwL2wzZVpmOXZDQmIrbElub0VNRWdjN1JvK1ha
   Q3RqQUkwQ0QxZkpmSlIvaEl5eURtSFd5WWlORmJSQ0g5ZnlhcmZremdYNHAwelRpenFq
   S2pBb01CWUdBMVVkSlFFQi93UU1NQW9HQ0NzR0FRVUZCd01jTUE0R0ExVWREd0VCL3dR
   RUF3SUhnREFLQmdncWhrak9QUVFEQWdOb0FEQmxBakJtVDJCTVZVZ2VsZ2Y0M1IrNXlC
   S05SVGFIbXlQQXZMdnh5ejBtRlZadlh4Ky8xUndPYWdtdkczYVhtUmtqL1g0Q01RQzhy
   TU5Cc0xvTnIxTDVuRzU2ZndBZEk4aGlBV0c4UzhYQVI1azFDZ3gzWVVRQlNnZFNjRmNB
   ZGYrK0J3Nll5K1U9In19oIIBdDCCAXAwgfagAwIBAgIEC4cKMTAKBggqhkjOPQQDAjAm
   MSQwIgYDVQQDDBtoaWdod2F5LXRlc3QuZXhhbXBsZS5jb20gQ0EwHhcNMjEwNDEzMjE0
   MDE2WhcNMjMwNDEzMjE0MDE2WjAoMSYwJAYDVQQDDB1oaWdod2F5LXRlc3QuZXhhbXBs
   ZS5jb20gTUFTQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABKoEFaNEueJE+Mn5Gwcb
   pnRznB66bKmzqTCpojJZ96AdRwFtuTCVfoKouLTBX0idIhMLfJLM31lyuKy4CUtpp6Wj
   EDAOMAwGA1UdEwEB/wQCMAAwCgYIKoZIzj0EAwIDaQAwZgIxAK7LYS3UXI1uhqoLBh3G
   02C6MnM2JdMjhUmHHM6UI3kankFVJB0VIqFIuwrAqzwTcwIxAIY8Z7OVouLl+a35HZzB
   NDJ49c/q1UcDnwC/0FnLUcKYBIEkilETULF1si+dqLT0uTGCAQUwggEBAgEBMC4wJjEk
   MCIGA1UEAwwbaGlnaHdheS10ZXN0LmV4YW1wbGUuY29tIENBAgQLhwoxMAsGCWCGSAFl
   AwQCAaBpMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTIx
   MDQxMzIxNDMyNFowLwYJKoZIhvcNAQkEMSIEIFUUjg4WYVO+MpX122Qfk/7zm/G6/B59
   HD/xrVR0lGIjMAoGCCqGSM49BAMCBEgwRgIhAOhUfxbH2dwpB2BrTDcsYSjRkCCk/WE6
   Mdt+y4z5KD9IAiEAphwdIUb40A0noNIUpH7N2lTyAFZgyn1lNHTteY9DmYI=
   <CODE ENDS>

Ниже представлено декодирование ASN1 для артефакта из файла examples/voucher_00-D0-E5-F2-00-02.b64

    0:d=0  hl=4 l=1570 cons: SEQUENCE
    4:d=1  hl=2 l=   9 prim: OBJECT            :pkcs7-signedData
   15:d=1  hl=4 l=1555 cons: cont [ 0 ]
   19:d=2  hl=4 l=1551 cons: SEQUENCE
   23:d=3  hl=2 l=   1 prim: INTEGER           :01
   26:d=3  hl=2 l=  13 cons: SET
   28:d=4  hl=2 l=  11 cons: SEQUENCE
   30:d=5  hl=2 l=   9 prim: OBJECT            :sha256
   41:d=3  hl=4 l= 888 cons: SEQUENCE
   45:d=4  hl=2 l=   9 prim: OBJECT            :pkcs7-data
   56:d=4  hl=4 l= 873 cons: cont [ 0 ]
   60:d=5  hl=4 l= 869 prim: OCTET STRING      :{"ietf-voucher:voucher":
  933:d=3  hl=4 l= 372 cons: cont [ 0 ]
  937:d=4  hl=4 l= 368 cons: SEQUENCE
  941:d=5  hl=3 l= 246 cons: SEQUENCE
  944:d=6  hl=2 l=   3 cons: cont [ 0 ]
  946:d=7  hl=2 l=   1 prim: INTEGER           :02
  949:d=6  hl=2 l=   4 prim: INTEGER           :0B870A31
  955:d=6  hl=2 l=  10 cons: SEQUENCE
  957:d=7  hl=2 l=   8 prim: OBJECT            :ecdsa-with-SHA256
  967:d=6  hl=2 l=  38 cons: SEQUENCE
  969:d=7  hl=2 l=  36 cons: SET
  971:d=8  hl=2 l=  34 cons: SEQUENCE
  973:d=9  hl=2 l=   3 prim: OBJECT            :commonName
  978:d=9  hl=2 l=  27 prim: UTF8STRING        :highway-test.example.com
 1007:d=6  hl=2 l=  30 cons: SEQUENCE
 1009:d=7  hl=2 l=  13 prim: UTCTIME           :210413214016Z
 1024:d=7  hl=2 l=  13 prim: UTCTIME           :230413214016Z
 1039:d=6  hl=2 l=  40 cons: SEQUENCE
 1041:d=7  hl=2 l=  38 cons: SET
 1043:d=8  hl=2 l=  36 cons: SEQUENCE
 1045:d=9  hl=2 l=   3 prim: OBJECT            :commonName
 1050:d=9  hl=2 l=  29 prim: UTF8STRING        :highway-test.example.com
 1081:d=6  hl=2 l=  89 cons: SEQUENCE
 1083:d=7  hl=2 l=  19 cons: SEQUENCE
 1085:d=8  hl=2 l=   7 prim: OBJECT            :id-ecPublicKey
 1094:d=8  hl=2 l=   8 prim: OBJECT            :prime256v1
 1104:d=7  hl=2 l=  66 prim: BIT STRING
 1172:d=6  hl=2 l=  16 cons: cont [ 3 ]
 1174:d=7  hl=2 l=  14 cons: SEQUENCE
 1176:d=8  hl=2 l=  12 cons: SEQUENCE
 1178:d=9  hl=2 l=   3 prim: OBJECT            :X509v3 Basic Constraints
 1183:d=9  hl=2 l=   1 prim: BOOLEAN           :255
 1186:d=9  hl=2 l=   2 prim: OCTET STRING      [HEX DUMP]:3000
 1190:d=5  hl=2 l=  10 cons: SEQUENCE
 1192:d=6  hl=2 l=   8 prim: OBJECT            :ecdsa-with-SHA256
 1202:d=5  hl=2 l= 105 prim: BIT STRING
 1309:d=3  hl=4 l= 261 cons: SET
 1313:d=4  hl=4 l= 257 cons: SEQUENCE
 1317:d=5  hl=2 l=   1 prim: INTEGER           :01
 1320:d=5  hl=2 l=  46 cons: SEQUENCE
 1322:d=6  hl=2 l=  38 cons: SEQUENCE
 1324:d=7  hl=2 l=  36 cons: SET
 1326:d=8  hl=2 l=  34 cons: SEQUENCE
 1328:d=9  hl=2 l=   3 prim: OBJECT            :commonName
 1333:d=9  hl=2 l=  27 prim: UTF8STRING        :highway-test.example.com
 1362:d=6  hl=2 l=   4 prim: INTEGER           :0B870A31
 1368:d=5  hl=2 l=  11 cons: SEQUENCE
 1370:d=6  hl=2 l=   9 prim: OBJECT            :sha256
 1381:d=5  hl=2 l= 105 cons: cont [ 0 ]
 1383:d=6  hl=2 l=  24 cons: SEQUENCE
 1385:d=7  hl=2 l=   9 prim: OBJECT            :contentType
 1396:d=7  hl=2 l=  11 cons: SET
 1398:d=8  hl=2 l=   9 prim: OBJECT            :pkcs7-data
 1409:d=6  hl=2 l=  28 cons: SEQUENCE
 1411:d=7  hl=2 l=   9 prim: OBJECT            :signingTime
 1422:d=7  hl=2 l=  15 cons: SET
 1424:d=8  hl=2 l=  13 prim: UTCTIME           :210413214324Z
 1439:d=6  hl=2 l=  47 cons: SEQUENCE
 1441:d=7  hl=2 l=   9 prim: OBJECT            :messageDigest
 1452:d=7  hl=2 l=  34 cons: SET
 1454:d=8  hl=2 l=  32 prim: OCTET STRING      [HEX DUMP]:55148E0E166153
 1488:d=5  hl=2 l=  10 cons: SEQUENCE
 1490:d=6  hl=2 l=   8 prim: OBJECT            :ecdsa-with-SHA256
 1500:d=5  hl=2 l=  72 prim: OCTET STRING      [HEX DUMP]:3046022100E854

Благодарности

Спасибо рецензентам за их вклад, в частности, William Atwood, Brian Carpenter, Fuyu Eleven, Eliot Lear, Sergey Kasatkin, Anoop Kumar, Tom Petch, Markus Stenberg, Peter van der Stok, Thomas Werner.

Важные обзоры представили Jari Arkko, Christian Huitema, Russ Housley.

Henk Birkholz представил CDDL для отклика audit-log.

Этот документ начался с двухстраничного изложения идей от Steinthor Bjarnason.

Кроме того, многие члены IESG, включая Adam Roach, Alexey Melnikov, Alissa Cooper, Benjamin Kaduk, Éric Vyncke, Roman Danyliw, Magnus Westerlund, представили существенные обзорные комментации.

Адреса авторов


Перевод на русский язык

Николай Малых
nmalykh@protokols.ru

1Internet Engineering Task Force — комиссия по решению инженерных задач Internet.

2Internet Engineering Steering Group — комиссия по инженерным разработкам Internet.

3Subscriber Identification Module — модуль идентификации подписчика (абонента).

4Cryptographic Message Syntax — синтаксис криптографический сообщений.

5Concise Data Definition Language — краткий язык определения данных.

6Man-in-the-Middle — перехват и изменение данных с участием человека.

7В оригинале последующий текст этого абзаца отличается. См. https://www.rfc-editor.org/errata/eid6648. Прим. перев.

8В оригинале это предложение указано иначе. См. https://www.rfc-editor.org/errata/eid6642. Прим. перев.

9В оригинале этот абзац отсутствует. См. https://www.rfc-editor.org/errata/eid6649. Прим. перев.

10В оригинале ошибочно сказано Transport Performance Metrics. См. https://www.rfc-editor.org/errata/eid6716. Прим. перев.

11Content Delivery Network — сеть доставки содержимого.

12Опубликовано в RFC 9148. Прим. перев.

Рубрика: RFC | Оставить комментарий

RFC 9020 YANG Data Model for Segment Routing

Internet Engineering Task Force (IETF)                      S. Litkowski
Request for Comments: 9020                                 Cisco Systems
Category: Standards Track                                          Y. Qu
ISSN: 2070-1721                                                Futurewei
                                                               A. Lindem
                                                           Cisco Systems
                                                               P. Sarkar
                                                             VMware, Inc
                                                             J. Tantsura
                                                        Juniper Networks
                                                                May 2021

YANG Data Model for Segment Routing

Модель данных YANG для маршрутизации по сегментам

PDF

Аннотация

Этот документ задаёт три модели YANG. Первая описывает конфигурацию и рабочее состояние для маршрутизации по сегментам (Segment Routing или SR) и будет дополняться для различных плоскостей данных SR. Вторая модель задаёт набор базовых типов и группировок для SR. Третья модель определяет конфигурацию и рабочее состояние для плоскости данных SR MPLS.

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

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

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

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

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

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

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

1. Введение

Этот документ задаёт три модели данных YANG [RFC7950]. Первая описывает конфигурацию и рабочее состояние для маршрутизации по сегментам (SR) [RFC8402]. Документ не задаёт расширений IGP для поддержки SR, но второй модуль определяет базовые группировки, которые могут применяться в таких модулях. Причина выбора состоит в том, чтбы избежать требования поддержки реализациями всех расширений IGP. Например, реализация может поддерживать расширение IS-IS, не поддерживая расширение OSPF. Третья модель данных YANG задаёт модуль для использования в элементах сети для настройки и эксплуатации плоскости данных SR MPLS [RFC8660].

Модули YANG в этом документе соответствуют архитектуре хранилищ данных управления сетью (Network Management Datastore Architecture или NMDA) [RFC8342].

2. Терминология и нотация

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

2.1. Диаграммы деревьев

В диаграммах деревьев применяется нотация, заданная в [RFC8340].

2.2. Префиксы имён узлов данных

В этом документе имена узлов данных, действий и других объектов модели данных часто применяются без префиксов, если из контекста ясно, в каком модуле YANG определено каждое имя. При отсутствии такой ясности имена указываются со стандартными префиксами, связанными с соответствующими модулямиYANG (Таблица 1).

Таблица 1. Префиксы в модулях YANG.

 

Префикс

Модуль YANG

Документ

if

ietf-interfaces

[RFC8343]

rt

ietf-routing

[RFC8349]

rt-types

ietf-routing-types

[RFC8294]

yang

ietf-yang-types

[RFC6991]

inet

ietf-inet-types

[RFC6991]

 

3. Устройство модели данных

Модуль YANG ietf-segment-routing дополняет контейнер routing из модуля ietf-routing [RFC8349] и определяет базовое состояние настройки и работы SR. Этот модуль дополняется модулями для различных плоскостей данных.

Модуль ietf-segment-routing-mpls дополняет ietf-segment-routing и поддерживает конфигурацию и рабочее состояние плоскости данных SR-MPLS.

Модуль ietf-segment-routing-common задаёт базовые типы и группировки, которые следует применять в модулях расширения IGP.

   module: ietf-segment-routing
     augment /rt:routing:
       +--rw segment-routing

   module: ietf-segment-routing-mpls
     augment /rt:routing/sr:segment-routing:
       +--rw sr-mpls
          +--rw bindings
          |  +--rw mapping-server {mapping-server}?
          |  |  +--rw policy* [name]
          |  |     +--rw name       string
          |  |     +--rw entries
          |  |        +--rw mapping-entry* [prefix algorithm]
          |  |           +--rw prefix        inet:ip-prefix
          |  |           +--rw value-type?   enumeration
          |  |           +--rw start-sid     uint32
          |  |           +--rw range?        uint32
          |  |           +--rw algorithm     identityref
          |  +--rw connected-prefix-sid-map
          |  |  +--rw connected-prefix-sid* [prefix algorithm]
          |  |     +--rw prefix               inet:ip-prefix
          |  |     +--rw value-type?          enumeration
          |  |     +--rw start-sid            uint32
          |  |     +--rw range?               uint32
          |  |     +--rw algorithm            identityref
          |  |     +--rw last-hop-behavior?   enumeration
          |  +--rw local-prefix-sid
          |     +--rw local-prefix-sid* [prefix algorithm]
          |        +--rw prefix        inet:ip-prefix
          |        +--rw value-type?   enumeration
          |        +--rw start-sid     uint32
          |        +--rw range?        uint32
          |        +--rw algorithm     identityref
          +--rw srgb
          |  +--rw srgb* [lower-bound upper-bound]
          |     +--rw lower-bound    uint32
          |     +--rw upper-bound    uint32
          +--rw srlb
          |  +--rw srlb* [lower-bound upper-bound]
          |     +--rw lower-bound    uint32
          |     +--rw upper-bound    uint32
          +--ro label-blocks* []
          |  +--ro lower-bound?   uint32
          |  +--ro upper-bound?   uint32
          |  +--ro size?          uint32
          |  +--ro free?          uint32
          |  +--ro used?          uint32
          |  +--ro scope?         enumeration
          +--ro sid-db
             +--ro sid* [target sid source source-protocol binding-type]
                +--ro target             string
                +--ro sid                uint32
                +--ro algorithm?         uint8
                +--ro source             inet:ip-address
                +--ro used?              boolean
                +--ro source-protocol    -> /rt:routing
                                            /control-plane-protocols
                                            /control-plane-protocol/name
                +--ro binding-type       enumeration
                +--ro scope?             enumeration

     notifications:
       +---n segment-routing-srgb-collision
       |  +--ro srgb-collisions* []
       |     +--ro lower-bound?          uint32
       |     +--ro upper-bound?          uint32
       |     +--ro routing-protocol?     -> /rt:routing
       |                                    /control-plane-protocols
       |                                    /control-plane-protocol/name
       |     +--ro originating-rtr-id?   router-or-system-id
       +---n segment-routing-global-sid-collision
       |  +--ro received-target?       string
       |  +--ro new-sid-rtr-id?        router-or-system-id
       |  +--ro original-target?       string
       |  +--ro original-sid-rtr-id?   router-or-system-id
       |  +--ro index?                 uint32
       |  +--ro routing-protocol?      -> /rt:routing
       |                                  /control-plane-protocols
       |                                  /control-plane-protocol/name
       +---n segment-routing-index-out-of-range
          +--ro received-target?    string
          +--ro received-index?     uint32
          +--ro routing-protocol?   -> /rt:routing
                                       /control-plane-protocols
                                       /control-plane-protocol/name

4. Конфигурация

Модуль ietf-segment-routing-mpls дополняет /rt:routing/sr:segment-routing: контейнером sr-mpls, который определяет все параметры конфигурации, относящиеся к плоскости данных SR MPLS. Конфигурация sr-mpls разделена на глобальную и настройки интерфейсов. Глобальные настройки указаны ниже.

Bindings — привязки

Задают отображения префиксов на идентификаторы сегментов (Prefix-SID). Оператор может контролировать анонсы Prefix-SID независимо для IPv4 и IPv6. Поддерживается два типа отображений.

Mapping-server — сервер отображения

Отображаются префиксы, которые не локальны для SID. Конфигурация привязок не разрешает автоматически их анонсирование, и оно должно контролироваться каждым экземпляром протокола маршрутизации (см. 5. Конфигурация плоскости управления IGP). Можно задать несколько правил отображения.

Connected prefixes — подключенные префиксы

Подключенные префиксы отображаются на SID. Анонсы отображений будет выполняться IGP при включении SR (см. 5. Конфигурация плоскости управления IGP). SID можно указать индексом (принято по умолчанию) или абсолютным значением. Конфигурация last-hop-behavior диктует поведение предпоследнего узла пересылки MPLS (Penultimate Hop Popping или PHP) — explicit-null, php, non-php.

Segment Routing Global Block (SRGB) — глобальный блок SR

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

Segment Routing Local Block (SRLB) — локальный блок SR

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

5. Конфигурация плоскости управления IGP

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

Этот модуль задаёт группировки, которые следует использовать в модулях IGP SR. Группировка sr-control-plane определяет базовую глобальную конфигурацию для IGP. Лист enabled включает расширения SR для экземпляра протокола маршрутизации. Контейнер bindings управляет анонсами экземпляра протокола маршрутизации для локальных присвязок и обработкой полученных привязок.

5.1. Конфигурация интерфейса IGP

Конфигурация интерфейса является частью группировки igp-interface и включает свойства SID-смежности (Adj-SID).

5.1.1. Свойства SID-смежности (Adj-SID)

5.1.1.1. Привязка

При наличии параллельных каналов IP между маршрутизаторами могут анонсироваться дополнительные Adj-SID [RFC8402], представляющие более 1 смежности (т. е. группу смежностей). Конфигурация advertise-adj-group-sid управляет анонсированием таких дополнительных Adj-SID. Список advertise-adj-group-sid представляет групповые идентификаторы, каждый из которых указывает собранные вместе интерфейсы.

+-------+                 +------+
|       | ------- L1 ---- |      |
|   R1  | ------- L2 ---- |  R2  |
|       | ------- L3 ---- |      |
|       | ------- L4 ---- |      |
+-------+                 +------+

На рисунке маршрутизаторы R1 и R2 соединены 4 каналами, на каждом из которых установлена маршрутная смежность. Оператор хочет создать Adj-SID, представляющие группы (bundle) каналов. Можно представить две разных группы — L1/L2 и L3/L4. Для этого оператор может настроить group-id X для интерфейсов L1 и L2 и group-id Y для L3 и L4. В результате R1 анонсирует дополнительный Adj-SID для каждой смежности. Например, Adj-SID со значением 400 будет добавлен к L1 и L2, а Adj-SID 500 — к L3 и L4. Поскольку L1/L2 и L3/L4 не используют общий group-id, выделены разные значения SID.

5.1.1.2. Защита

Лист advertise-protection определяет анонсирование защиты для интерфейса, но не включает и не отключает эту защиту. При использовании варианта single для интерфейса будет анонсироваться 1 Adj-SID. Если интерфейс защищён, для Adj-SID будет установлен B-Flag. Если выбран вариант dual и интерфейс защищён, для смежности интерфейсов бедет анонсироваться 2 Adj-SID, в одном из которых B-Flag установлен, в другом сброшен. Этот вариант предназначен для случая организации трафика, когда путь должен использовать защищённые, либо незащищённые сегменты.

6. Данные состояния

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

7. Уведомления

Модель определяет указанные ниже уведомления для SR.

segment-routing-srgb-collision

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

segment-routing-global-sid-collision

Передаётся, когда индекс, анонсируемый плоскостью управления, уже применяется с другой целью (в этой версии целями являются только префиксы IPv4 и IPv6).

segment-routing-index-out-of-range

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

8. Модули YANG

В этот документ включены три модуля YANG.

В тексте документа не указаны, но упоминаются в модулях ietf-segment-routing.yang, ietf-segment-routing-common.yang, ietf-segment-routing-mpls.yang [RFC6991], [RFC8294], [RFC8661], [RFC8665], [RFC8667], [RFC8669], [RFC8814].

8.1. Модуль YANG для SR

Модуль ietf-segment-routing.yang задаёт базовую схему для SR и дополняется моделями для разных плоскостей данных SR.

   <CODE BEGINS> file "ietf-segment-routing@2021-05-26.yang"
   module ietf-segment-routing {
     yang-version 1.1;
     namespace "urn:ietf:params:xml:ns:yang:ietf-segment-routing";
     prefix sr;

     import ietf-routing {
       prefix rt;
       reference "RFC 8349: A YANG Data Model for Routing
                            Management (NMDA Version)";
     }

     organization
       "IETF SPRING - SPRING Working Group";
     contact
       "WG Web:   <https://datatracker.ietf.org/wg/spring/> 
        WG List:  <mailto:spring@ietf.org> 

        Author:    Stephane Litkowski
                  <mailto:slitkows.ietf@gmail.com> 
        Author:    Yingzhen Qu
                  <mailto:yingzhen.qu@futurewei.com> 
        Author:    Acee Lindem
                  <mailto:acee@cisco.com> 
        Author:    Pushpasis Sarkar
                  <mailto:pushpasis.ietf@gmail.com> 
        Author:    Jeff Tantsura
                  <jefftant.ietf@gmail.com> 

       ";
     description
       "Этот модуль YANG задаёт базовую модель для SR. Он будет 
        дполняться моделями для разных плоскостей данных SR.

        Модуль соответствует архитектуре NMDA, описанной в RFC 8242.

        Ключевые слова ДОЛЖНО, НЕДОПУСТИМО, ТРЕБУЕТСЯ, НУЖНО, НЕ НУЖНО, 
        СЛЕДУЕТ, НЕ СЛЕДУЕТ, РЕКОМЕНДУЕТСЯ, НЕ РЕКОМЕНДУЕТСЯ, МОЖНО,
        НЕОБЯЗАТЕЛЬНО в этом документе трактуются в соответствии с 
        BCP 14 (RFC 2119) (RFC 8174) тогда и только тогда, когда они
        указаны заглавными буквами, как показано здесь.
        Авторские права (Copyright (c) 2021) принадлежат IETF Trust и
        лицам, указанным как авторы. Все права защищены.

        Распространение и применение модуля в исходной или двоичной 
        форме с изменениями или без таковых разрешено в соответствии с
        лицензией Simplified BSD License, изложенной в параграфе 4.c
        IETF Trust's Legal Provisions Relating to IETF Documents
        (https://trustee.ietf.org/license-info). 

        Эта версия модуля YANG является частью RFC 9020, где правовые
        аспекты приведены более полно.";

     reference
       "RFC 9020: YANG Data Model for Segment Routing.";

     revision 2021-05-26 {
       description
         "Исходный выпуск";
       reference
         "RFC 9020: YANG Data Model for Segment Routing.";
     }

     augment "/rt:routing" {
       description
         "Этот модуль дополняет модель данных маршрутизации (RFC 8349)
          маршрутизацией по сегментам (Segment Routing или SR).";
       container segment-routing {
         description
           "Конфигурация SR. Этот контейнер будет дополняться моделями
            для разных плоскостей данных SR.";
         reference
           "RFC 8402: Segment Routing Architecture.";
       }
     }
   }
   <CODE ENDS>

8.2. Модуль YANG для базовых типов SR

Модуль ietf-segment-routing-common.yang определяет набор базовых типов и группировок для SR, заданной [RFC8402].

   <CODE BEGINS> file "ietf-segment-routing-common@2021-05-26.yang"
   module ietf-segment-routing-common {
     yang-version 1.1;
     namespace
      "urn:ietf:params:xml:ns:yang:ietf-segment-routing-common";
     prefix sr-cmn;

     import ietf-inet-types {
       prefix inet;
       reference
         "RFC 6991: Common YANG Data Types";
     }

     organization
       "IETF SPRING - SPRING Working Group";
     contact
       "WG Web:   <https://datatracker.ietf.org/wg/spring/> 
        WG List:  <mailto:spring@ietf.org> 

        Author:    Stephane Litkowski
                  <mailto:slitkows.ietf@gmail.com> 
        Author:    Yingzhen Qu
                  <mailto:yingzhen.qu@futurewei.com> 
        Author:    Acee Lindem
                  <mailto:acee@cisco.com> 
        Author:    Pushpasis Sarkar
                  <mailto:pushpasis.ietf@gmail.com> 
        Author:    Jeff Tantsura
                  <jefftant.ietf@gmail.com> 

       ";
     description
       "Этот модуль YANG определяет набор базовых типов и группировок
        для маршрутизации по сегментам (SR), описанной в RFC 8402.

        Модуль соответствует архитектуре NMDA, описанной в RFC 8242.

        Ключевые слова ДОЛЖНО, НЕДОПУСТИМО, ТРЕБУЕТСЯ, НУЖНО, НЕ НУЖНО, 
        СЛЕДУЕТ, НЕ СЛЕДУЕТ, РЕКОМЕНДУЕТСЯ, НЕ РЕКОМЕНДУЕТСЯ, МОЖНО,
        НЕОБЯЗАТЕЛЬНО в этом документе трактуются в соответствии с 
        BCP 14 (RFC 2119) (RFC 8174) тогда и только тогда, когда они
        указаны заглавными буквами, как показано здесь.
        Авторские права (Copyright (c) 2021) принадлежат IETF Trust и
        лицам, указанным как авторы. Все права защищены.

        Распространение и применение модуля в исходной или двоичной 
        форме с изменениями или без таковых разрешено в соответствии с
        лицензией Simplified BSD License, изложенной в параграфе 4.c
        IETF Trust's Legal Provisions Relating to IETF Documents
        (https://trustee.ietf.org/license-info). 

        Эта версия модуля YANG является частью RFC 9020, где правовые
        аспекты приведены более полно.";
     reference
       "RFC 9020: YANG Data Model for Segment Routing";

     revision 2021-05-26 {
       description
         "Исходный выпуск";
       reference
         "RFC 9020: YANG Data Model for Segment Routing";
     }

     feature sid-last-hop-behavior {
       description
         "Настраиваемое поведение last-hop.";
       reference
         "RFC 8660: Segment Routing with the MPLS Data Plane";
     }

     identity prefix-sid-algorithm {
       description
         "Базовый идентификатор для алгоритма prefix-sid.";
       reference
         "RFC 8402: Segment Routing Architecture";
     }

     identity prefix-sid-algorithm-shortest-path {
       base prefix-sid-algorithm;
       description
         "Алгоритм SPF Prefix-SID (принят по умолчанию).";
     }

     identity prefix-sid-algorithm-strict-spf {
       base prefix-sid-algorithm;
       description
         "Этот алгоритм требует пересылки пакетов в соответствии
          с алгоритмом SPF, поддерживающим ECMP.";
     }

     grouping srlr {
       description
         "Группировка для конфигурации SR Label Range.";
       leaf lower-bound {
         type uint32;
         description
           "Нижнее значение диапазона меток.";
       }
       leaf upper-bound {
         type uint32;
         must '../lower-bound < ../upper-bound' {
           error-message
             "Значение upper-bound должно быть больше lower-bound.";
           description
             "Значение должно быть больше чем lower-bound.";
         }
         description
           "Верхнее значение диапазона меток.";
       }
     }

     grouping srgb {
       description
         "Группировка для SR Global Label Range.";
       list srgb {
         key "lower-bound upper-bound";
         ordered-by user;
         description
           "Список глобальных блоков для анонсирования.";
         uses srlr;
       }
     }

     grouping srlb {
       description
         "Группировка для SR Local Block Range.";
       list srlb {
         key "lower-bound upper-bound";
         ordered-by user;
         description
           "Список SRLB.";
         uses srlr;
       }
     }

     grouping sid-value-type {
       description
         "Задаёт способ представления SID.";
       leaf value-type {
         type enumeration {
           enum index {
             description
               "Значение будет интерпретироваться как индекс.";
           }
           enum absolute {
             description
               "Абсолютное значение.";
           }
         }
         default "index";
         description
           "Этот лист задаёт интерпретацию значений.";
       }
     }

     grouping prefix-sid {
       description
         "Задаёт конфигурацию Prefix-SID.";
       leaf prefix {
         type inet:ip-prefix;
         description
           "Подключённый Prefix-SID.";
       }
       uses prefix-sid-attributes;
     }

     grouping ipv4-sid {
       description
         "Группировка для IPv4 Prefix-SID.";
       leaf prefix {
         type inet:ipv4-prefix;
         description
           "Подключённый IPv4 Prefix-SID.";
       }
       uses prefix-sid-attributes;
     }

     grouping ipv6-sid {
       description
         "Группировка для IPv6 Prefix-SID.";
       leaf prefix {
         type inet:ipv6-prefix;
         description
           "Подключённый IPv6 Prefix-SID.";
       }
       uses prefix-sid-attributes;
     }

     grouping last-hop-behavior {
       description
         "Задаёт поведение last-hop.";
       leaf last-hop-behavior {
         if-feature "sid-last-hop-behavior";
         type enumeration {
           enum explicit-null {
             description
               "использовать explicit-null для SID.";
           }
           enum no-php {
             description
               "Не применять MPLS PHP для SID.";
           }
           enum php {
             description
               "Применять MPLS PHP для SID.";
           }
         }
         description
           "Настройка поведения last-hop.";
       }
     }

     grouping prefix-sid-attributes {
       description
         "Группировка для атрибутов префикса SR.";
       uses sid-value-type;
       leaf start-sid {
         type uint32;
         mandatory true;
         description
           "Значение, связанное с префиксом, которое должно
            интерпретироваться в контексте sid-value-type.";
       }
       leaf range {
         type uint32;
         description
           "Указывает, сколько SID можно выделить.";
       }
       leaf algorithm {
         type identityref {
           base prefix-sid-algorithm;
         }
         description
           "Алгоритм Prefix-SID.";
       }
     }
   }
   <CODE ENDS>

8.3. Модуль YANG для SR MPLS

Модуль ietf-segment-routing-mpls.yang определяет конфигурацию и рабочее состояние для плоскости данных SR MPLS.

   <CODE BEGINS> file "ietf-segment-routing-mpls@2021-05-26.yang"
   module ietf-segment-routing-mpls {
     yang-version 1.1;
     namespace "urn:ietf:params:xml:ns:yang:ietf-segment-routing-mpls";
     prefix sr-mpls;

     import ietf-inet-types {
       prefix inet;
       reference
         "RFC 6991: Common YANG Data Types";
     }
     import ietf-routing {
       prefix rt;
       reference
         "RFC 8349: A YANG Data Model for Routing
                    Management (NMDA Version)";
     }
     import ietf-routing-types {
       prefix rt-types;
       reference
         "RFC 8294: Common YANG Data Types for the
                    Routing Area";
     }
     import ietf-segment-routing {
       prefix sr;
       reference
         "RFC 9020: YANG Data Model for Segment Routing";
     }
     import ietf-segment-routing-common {
       prefix sr-cmn;
       reference
         "RFC 9020: YANG Data Model for Segment Routing";
     }

     organization
       "IETF SPRING - SPRING Working Group";
     contact
       "WG Web:   <https://datatracker.ietf.org/wg/spring/> 
        WG List:  <mailto:spring@ietf.org> 

        Author:    Stephane Litkowski
                  <mailto:slitkows.ietf@gmail.com> 
        Author:    Yingzhen Qu
                  <mailto:yingzhen.qu@futurewei.com> 
        Author:    Acee Lindem
                  <mailto:acee@cisco.com>
        Author:    Pushpasis Sarkar
                  <mailto:pushpasis.ietf@gmail.com> 
        Author:    Jeff Tantsura
                  <jefftant.ietf@gmail.com> 

       ";
     description
       "Этот модуль YANG определяет базовую модель конфигурации для
        плоскости данных SR MPLS.

        Модуль соответствует архитектуре NMDA, описанной в RFC 8242.

        Ключевые слова ДОЛЖНО, НЕДОПУСТИМО, ТРЕБУЕТСЯ, НУЖНО, НЕ НУЖНО, 
        СЛЕДУЕТ, НЕ СЛЕДУЕТ, РЕКОМЕНДУЕТСЯ, НЕ РЕКОМЕНДУЕТСЯ, МОЖНО,
        НЕОБЯЗАТЕЛЬНО в этом документе трактуются в соответствии с 
        BCP 14 (RFC 2119) (RFC 8174) тогда и только тогда, когда они
        указаны заглавными буквами, как показано здесь.
        Авторские права (Copyright (c) 2021) принадлежат IETF Trust и
        лицам, указанным как авторы. Все права защищены.

        Распространение и применение модуля в исходной или двоичной 
        форме с изменениями или без таковых разрешено в соответствии с
        лицензией Simplified BSD License, изложенной в параграфе 4.c
        IETF Trust's Legal Provisions Relating to IETF Documents
        (https://trustee.ietf.org/license-info). 

        Эта версия модуля YANG является частью RFC 9020, где правовые
        аспекты приведены более полно.";
     reference
       "RFC 9020: YANG Data Model for Segment Routing";

     revision 2021-05-26 {
       description
         "Исходный выпуск";
       reference
         "RFC 9020: YANG Data Model for Segment Routing";
     }

     feature mapping-server {
       description
         "Поддержка сервера отображения SR (SRMS).";
       reference
         "RFC 8661: Segment Routing MPLS Interworking
                    with LDP";
     }

     feature protocol-srgb {
       description
         "Поддержка конфигурации SRGB по протоколам.";
       reference
         "RFC 8660: Segment Routing with the MPLS
                    Data Plane";
     }

     typedef system-id {
       type string {
         pattern '[0-9A-Fa-f]{4}\.[0-9A-Fa-f]{4}\.[0-9A-Fa-f]{4}';
       }
       description
         "Этот тип задаёт IS-IS system-id с использованием шаблона,
          например, system-id 0143.0438.AEF0.";
     }

     typedef router-or-system-id {
       type union {
         type rt-types:router-id;
         type system-id;
       }
       description
         "OSPF/BGP router-id или IS-IS system ID.";
     }

     grouping sr-control-plane {
       description
         "Определяет конфигурацию протокола.";
       container segment-routing {
         description
           "Глобальная конфигурация SR.";
         leaf enabled {
           type boolean;
           default "false";
           description
             "Разрешает расширения протокола плоскости управления SR.";
         }
         container bindings {
           if-feature "mapping-server";
           description
             "Управляет анонсированием и получением привязок.";
           container advertise {
             description
               "Управляет анонсированием локальных отображений 
                в TLV привязок.";
             leaf-list policies {
               type leafref {
                 path "/rt:routing/sr:segment-routing/sr-mpls:sr-mpls"
                    + "/sr-mpls:bindings/sr-mpls:mapping-server"
                    + "/sr-mpls:policy/sr-mpls:name";
               }
               description
                 "List of binding advertisement policies.";
             }
           }
           leaf receive {
             type boolean;
             default "true";
             description
               "Разрешает получать и применять TLV привязок.";
           }
         }
       }
     }

     grouping igp-interface {
       description
         "Группировка для конфигурации интерфейса IGP.";
       container segment-routing {
         description
           "Контейнер для конфигурации интерфейса SR.";
         container adjacency-sid {
           description
             "Конфигурация SID-смежности (Adj-SID).";
           reference
             "RFC 8660: Segment Routing with the MPLS
                        Data Plane";
           list adj-sids {
             key "value";
             uses sr-cmn:sid-value-type;
             leaf value {
               type uint32;
               description
                 "Значение Adj-SID.";
             }
             leaf protected {
               type boolean;
               default "false";
               description
                 "Применяется для защиты Adj-SID, например, применения
                  IP Fast Reroute (IPFRR) или MPLS-FRR.";
             }
             leaf weight {
               type uint8;
               description
                 "Коэффициент распределения нагрузки между параллельными
                  смежностями.";
               reference
                 "RFC 8402: Segment Routing Architecture
                  RFC 8665: OSPF Extensions for Segment Routing
                  RFC 8667: IS-IS Extensions for Segment
                            Routing";
             }
             description
               "Список Adj-SID и их конфигурация.";
           }
           list advertise-adj-group-sid {
             key "group-id";
             description
               "Управляет анонсированием S-flag или G-flag. Включает
                анонсирование общего Adj-SID для параллельных каналов.";
             reference
               "RFC 8665: OSPF Extensions for Segment Routing,
                          Section 6.1
                RFC 8667: IS-IS Extensions for Segment
                          Routing, Section 2.2.1";
             leaf group-id {
               type uint32;
               description
                 "Внутреннее значение для идентификации group-ID. 
                  Интерфейсы с одним group-ID будут сгруппированы.";
             }
           }
           leaf advertise-protection {
             type enumeration {
               enum single {
                 description
                   "Один Adj-SID связывается со смежностью и отражает
                    конфигурацию защиты.";
               }
               enum dual {
                 description
                   "2 Adj-SID связываются со смежностью, если интерфейс
                    защищен. В этом случае 1 Adj-SID анонсируется с
                    флагом резервирования (backup), а у другого этот 
                    флаг будет сброшен. Если защита не настроена, будет
                    анонсироваться 1 Adj-SID со сброшенным флагом.";
               }
             }
             description
               "Если установлено, Adj-SID указывает защищённую 
                смежность.";
             reference
               "RFC 8665: OSPF Extensions for Segment Routing,
                          Section 6.1
                RFC 8667: IS-IS Extensions for Segment
                          Routing, Section 2.2.1";
           }
         }
       }
     }

     augment "/rt:routing/sr:segment-routing" {
       description
         "Дополняет модель данных маршрутизации (RFC 8349)
          маршрутизацией SR с плоскостью данных MPLS.";
       container sr-mpls {
         description
           "Глобальная конфигурация и рабочее состояние SR.";
         container bindings {
           description
             "Список привязок.";
           container mapping-server {
             if-feature "mapping-server";
             description
               "Конфигурация локальных записей сервера отображения.";
             list policy {
               key "name";
               description
                 "Список правил сервера отображения.";
               leaf name {
                 type string;
                 description
                   "Имя политики отображения.";
               }
               container entries {
                 description
                   "Записи отображений IPv4/IPv6.";
                 list mapping-entry {
                   key "prefix algorithm";
                   description
                     "Записи отображений.";
                   uses sr-cmn:prefix-sid;
                 }
               }
             }
           }
           container connected-prefix-sid-map {
             description
               "Конфигурация Prefix-SID.";
             list connected-prefix-sid {
               key "prefix algorithm";
               description
                 "Список отображений Prefix-SID на локальные 
                  префиксы IPv4/IPv6.";
               uses sr-cmn:prefix-sid;
               uses sr-cmn:last-hop-behavior;
             }
           }
           container local-prefix-sid {
             description
               "Конфигурация локальных SID.";
             list local-prefix-sid {
               key "prefix algorithm";
               description
                 "Список локальных IPv4/IPv6 Prefix-SID.";
               uses sr-cmn:prefix-sid;
             }
           }
         }
         container srgb {
           description
             "Конфигурация глобальных SRGB.";
           uses sr-cmn:srgb;
         }
         container srlb {
           description
             "Конфигурация локального блока SR (SRLB).";
           uses sr-cmn:srlb;
         }
         list label-blocks {
           config false;
           description
             "Список используемых сейчас блоков меток.";
           leaf lower-bound {
             type uint32;
             description
               "Нижняя граница блока меток.";
           }
           leaf upper-bound {
             type uint32;
             description
               "Верхняя граница блока меток .";
           }
           leaf size {
             type uint32;
             description
               "Число индексов в блоке.";
           }
           leaf free {
             type uint32;
             description
               "Число свободных индексов в блоке.";
           }
           leaf used {
             type uint32;
             description
               "Число использованных индексов в блоке.";
           }
           leaf scope {
             type enumeration {
               enum global {
                 description
                   "Глобальный SID.";
               }
               enum local {
                 description
                   "Локальный SID.";
               }
             }
             description
               "Область действия этого блока меток.";
           }
         }
         container sid-db {
           config false;
           description
             "Список префиксов и ассоциаций SID.";
           list sid {
             key "target sid source source-protocol binding-type";
             ordered-by system;
             description
               "Привязка SID.";
             leaf target {
               type string;
               description
                 "Цель привязки (префикс или что-то иное).";
             }
             leaf sid {
               type uint32;
               description
                 "Индекс, связанный с префиксом.";
             }
             leaf algorithm {
               type uint8;
               description
                 "Алгоритм для использования с Prefix-SID.";
               reference
                 "RFC 8665: OSPF Extensions for Segment Routing
                  RFC 8667: IS-IS Extensions for Segment
                            Routing
                  RFC 8669: Segment Routing Prefix Segment
                            Identifier Extensions to BGP";
             }
             leaf source {
               type inet:ip-address;
               description
                 "IP-адрес маршрутизатора, владеющего привязкой.";
             }
             leaf used {
               type boolean;
               description
                 "Указывает, установлены ли привязки в плоскости
                  пересылки.";
             }
             leaf source-protocol {
               type leafref {
                 path "/rt:routing/rt:control-plane-protocols/"
                    + "rt:control-plane-protocol/rt:name";
               }
               description
                 "Протокол маршрутизации, владеющий привязкой.";
             }
             leaf binding-type {
               type enumeration {
                 enum prefix-sid {
                   description
                     "Привязки изучаются из Prefix-SID.";
                 }
                 enum binding-tlv {
                   description
                     "Привязки изучаются из TLV привязок.";
                 }
               }
               description
                 "Тип привязки.";
             }
             leaf scope {
               type enumeration {
                 enum global {
                   description
                     "Глобальный SID.";
                 }
                 enum local {
                   description
                     "Локальный SID.";
                 }
               }
               description
                 "Область действия SID.";
             }
           }
         }
       }
     }

     notification segment-routing-srgb-collision {
       description
         "Передаётся при конфликте блоков SRGB, полученных 
          от разных маршрутизаторов.";
       list srgb-collisions {
         description
           "Список конфликтующих блоков SRGB.";
         leaf lower-bound {
           type uint32;
           description
             "Нижнее значение в блоке.";
         }
         leaf upper-bound {
           type uint32;
           description
             "Верхнее значение в блоке.";
         }
         leaf routing-protocol {
           type leafref {
             path "/rt:routing/rt:control-plane-protocols/"
                + "rt:control-plane-protocol/rt:name";
           }
           description
             "Ссылка на протокол маршрутизации для конфликта SRGB.";
         }
         leaf originating-rtr-id {
           type router-or-system-id;
           description
             "Идентификатор маршрутизатора, создавшего этот блок SRGB.";
         }
       }
     }

     notification segment-routing-global-sid-collision {
       description
         "Передаётся при получении нового отображения, где SID уже
          используется. Генерация уведомлений должна происходить с
          интервалом не меньше 5 секунд.";
       leaf received-target {
         type string;
         description
           "Цель в полученном анонсе маршрутизатора вызвала конфликт
            SID.";
       }
       leaf new-sid-rtr-id {
         type router-or-system-id;
         description
           "Router ID из анонса конфликтующего SID.";
       }
       leaf original-target {
         type string;
         description
           "В базе данных уже доступна цель с SID, который получен.";
       }
       leaf original-sid-rtr-id {
         type router-or-system-id;
         description
           "Router ID маршрутизатора, исходно анонсировавшего 
            конфликтующий SID, т. е., экземпляр в базе данных.";
       }
       leaf index {
         type uint32;
         description
           "Значение индекса, использованного 2 разными префиксами.";
       }
       leaf routing-protocol {
         type leafref {
           path "/rt:routing/rt:control-plane-protocols/"
              + "rt:control-plane-protocol/rt:name";
         }
         description
           "Ссылка на протокол маршрутизации для конфликтующего SID.";
       }
     }

     notification segment-routing-index-out-of-range {
       description
         "Передаётся, когда полученная привязка содержит индекс сегмента
          вне локально заданных диапазонов. Генерация уведомлений должна
          происходить с интервалом не меньше 5 секунд.";
       leaf received-target {
         type string;
         description
           "Предназначенная человеку строка, представляющая цель,
            полученную в зависящем от протокола уведомлении, 
            соответствующем индексу вне диапазона.";
       }
       leaf received-index {
         type uint32;
         description
           "Значение полученного индекса.";
       }
       leaf routing-protocol {
         type leafref {
           path "/rt:routing/rt:control-plane-protocols/"
              + "rt:control-plane-protocol/rt:name";
         }
         description
           "Ссылка на протокол маршрутизации для индекса вне диапазона";
       }
     }
   }
   <CODE ENDS>

9. Вопросы безопасности

Заданные этим документом модули YANG определяют схему для данных, предназначенную для доступа через сеть с использованием протоколов управления, таких как NETCONF [RFC6241] или RESTCONF [RFC8040]. Нижним уровнем NETCONF служит защищённый транспорт с обязательной поддержкой SSH (Secure Shell) [RFC6242]. Нижним уровнем RESTCONF служит протокол HTTPS с обязательной поддержкой защиты на транспортном уровне (TLS) [RFC8446].

Модель доступа к конфигурации сети (NACM – Network Configuration Access Control Model) [RFC8341] обеспечивает возможность разрешить доступ лишь определённых пользователей NETCONF или RESTCONF к заранее заданному подмножеству операций NETCONF или RESTCONF и содержимого.

В модулях данных YANG определено множество узлов данных, которые разрешают запись, создание и удаление (т. е. config true, как принято по умолчанию). Эти узлы могут быть конфиденциальными или уязвимыми в некоторых сетевых средах. Запись в такие узлы (например, edit-config) без должной защиты может негативно влиять на работу сети. Ниже перечислены ветви и узлы, которые могут быть конфиденциальны или уязвимы.

/segment-routing

/segment-routing/mpls

/segment-routing/mpls/bindings

Изменение локальных привязок может приводить к DoS3-атаке. Атакующий может также пытаться организовать конфликты сегментов (используя один идентификатор сегмента для разных целей) для перенаправления трафика в доверенном домене. Однако трафик из этого домена не будет выходить. Перенаправление можно использовать для отправки трафика на скомпрометированные узлы или обхода некоторых функций защиты (например, межсетевого экрана). Обсуждение доверенных доменов SR-MPLS приведено в параграфе 8.1 [RFC8402].

/segment-routing/mpls/srgb

Изменение SRGB может служить для организации DoS-атаки. Например, при снижении размера SRGB до очень малого значения большая часть имеющихся сегментов больше не будет установлена и это нарушит трафик.

/segment-routing/mpls/srlb

Изменение SRLB может служить для организации DoS-атаки, похожей на случай изменения SRGB.

Некоторые из доступных для чтения узлов в этом модуле YANG могут быть конфиденциальны или уязвимы в той или иной сетевой среде. Важно контролировать доступ к таким объектам (например, get, get-config, notification). Ниже перечислены ветви и узлы, которые могут быть конфиденциальны или уязвимы.

/segment-routing/mpls/bindings

Знание этих узлов данных можно использовать для DoS-атаки на локальный маршрутизатор.

/segment-routing/mpls/sid-db

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

10. Взаимодействие с IANA

Этот документ регистрирует указанные ниже URI в реестре IETF XML Registry [RFC3688].

   ID:  yang:ietf-segment-routing-common
   URI:  urn:ietf:params:xml:ns:yang:ietf-segment-routing-common
   Registrant Contact:  The IESG.
   XML:  N/A, запрошенный URI является пространстовм имён XML.

   ID:  yang:ietf-segment-routing
   URI:  urn:ietf:params:xml:ns:yang:ietf-segment-routing
   Registrant Contact:  The IESG.
   XML:  N/A, запрошенный URI является пространстовм имён XML.

   ID:  yang:ietf-segment-routing-mpls
   URI:  urn:ietf:params:xml:ns:yang:ietf-segment-routing-mpls
   Registrant Contact:  The IESG.
   XML:  N/A, запрошенный URI является пространстовм имён XML.

Этот документ регистрирует указанные ниже модули YANG в реестре YANG Module Names [RFC6020].

   Name:  ietf-segment-routing-common
   Maintained by IANA:  N
   Namespace:  urn:ietf:params:xml:ns:yang:ietf-segment-routing-common
   Prefix:  sr-cmn
   Reference:  RFC 9020

   Name:  ietf-segment-routing
   Maintained by IANA:  N
   Namespace:  urn:ietf:params:xml:ns:yang:ietf-segment-routing
   Prefix:  sr
   Reference:  RFC 9020

   Name:  ietf-segment-routing-mpls
   Maintained by IANA:  N
   Namespace:  urn:ietf:params:xml:ns:yang:ietf-segment-routing-mpls
   Prefix:  sr-mpls
   Reference:  RFC 9020

11. Литература

11.1. Нормативные документы

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>.

[RFC3688] Mealling, M., «The IETF XML Registry», BCP 81, RFC 3688, DOI 10.17487/RFC3688, January 2004, <https://www.rfc-editor.org/info/rfc3688>.

[RFC6020] Bjorklund, M., Ed., «YANG — A Data Modeling Language for the Network Configuration Protocol (NETCONF)», RFC 6020, DOI 10.17487/RFC6020, October 2010, <https://www.rfc-editor.org/info/rfc6020>.

[RFC6241] Enns, R., Ed., Bjorklund, M., Ed., Schoenwaelder, J., Ed., and A. Bierman, Ed., «Network Configuration Protocol (NETCONF)», RFC 6241, DOI 10.17487/RFC6241, June 2011, <https://www.rfc-editor.org/info/rfc6241>.

[RFC6242] Wasserman, M., «Using the NETCONF Protocol over Secure Shell (SSH)», RFC 6242, DOI 10.17487/RFC6242, June 2011, <https://www.rfc-editor.org/info/rfc6242>.

[RFC6991] Schoenwaelder, J., Ed., «Common YANG Data Types», RFC 6991, DOI 10.17487/RFC6991, July 2013, <https://www.rfc-editor.org/info/rfc6991>.

[RFC7950] Bjorklund, M., Ed., «The YANG 1.1 Data Modeling Language», RFC 7950, DOI 10.17487/RFC7950, August 2016, <https://www.rfc-editor.org/info/rfc7950>.

[RFC8040] Bierman, A., Bjorklund, M., and K. Watsen, «RESTCONF Protocol», RFC 8040, DOI 10.17487/RFC8040, January 2017, <https://www.rfc-editor.org/info/rfc8040>.

[RFC8174] Leiba, B., «Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words», BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[RFC8294] Liu, X., Qu, Y., Lindem, A., Hopps, C., and L. Berger, «Common YANG Data Types for the Routing Area», RFC 8294, DOI 10.17487/RFC8294, December 2017, <https://www.rfc-editor.org/info/rfc8294>.

[RFC8341] Bierman, A. and M. Bjorklund, «Network Configuration Access Control Model», STD 91, RFC 8341, DOI 10.17487/RFC8341, March 2018, <https://www.rfc-editor.org/info/rfc8341>.

[RFC8342] Bjorklund, M., Schoenwaelder, J., Shafer, P., Watsen, K., and R. Wilton, «Network Management Datastore Architecture (NMDA)», RFC 8342, DOI 10.17487/RFC8342, March 2018, <https://www.rfc-editor.org/info/rfc8342>.

[RFC8343] Bjorklund, M., «A YANG Data Model for Interface Management», RFC 8343, DOI 10.17487/RFC8343, March 2018, <https://www.rfc-editor.org/info/rfc8343>.

[RFC8349] Lhotka, L., Lindem, A., and Y. Qu, «A YANG Data Model for Routing Management (NMDA Version)», RFC 8349, DOI 10.17487/RFC8349, March 2018, <https://www.rfc-editor.org/info/rfc8349>.

[RFC8402] Filsfils, C., Ed., Previdi, S., Ed., Ginsberg, L., Decraene, B., Litkowski, S., and R. Shakir, «Segment Routing Architecture», RFC 8402, DOI 10.17487/RFC8402, July 2018, <https://www.rfc-editor.org/info/rfc8402>.

[RFC8446] Rescorla, E., «The Transport Layer Security (TLS) Protocol Version 1.3», RFC 8446, DOI 10.17487/RFC8446, August 2018, <https://www.rfc-editor.org/info/rfc8446>.

[RFC8660] Bashandy, A., Ed., Filsfils, C., Ed., Previdi, S., Decraene, B., Litkowski, S., and R. Shakir, «Segment Routing with the MPLS Data Plane», RFC 8660, DOI 10.17487/RFC8660, December 2019, <https://www.rfc-editor.org/info/rfc8660>.

[RFC8661] Bashandy, A., Ed., Filsfils, C., Ed., Previdi, S., Decraene, B., and S. Litkowski, «Segment Routing MPLS Interworking with LDP», RFC 8661, DOI 10.17487/RFC8661, December 2019, <https://www.rfc-editor.org/info/rfc8661>.

[RFC8665] Psenak, P., Ed., Previdi, S., Ed., Filsfils, C., Gredler, H., Shakir, R., Henderickx, W., and J. Tantsura, «OSPF Extensions for Segment Routing», RFC 8665, DOI 10.17487/RFC8665, December 2019, <https://www.rfc-editor.org/info/rfc8665>.

[RFC8667] Previdi, S., Ed., Ginsberg, L., Ed., Filsfils, C., Bashandy, A., Gredler, H., and B. Decraene, «IS-IS Extensions for Segment Routing», RFC 8667, DOI 10.17487/RFC8667, December 2019, <https://www.rfc-editor.org/info/rfc8667>.

[RFC8669] Previdi, S., Filsfils, C., Lindem, A., Ed., Sreekantiah, A., and H. Gredler, «Segment Routing Prefix Segment Identifier Extensions for BGP», RFC 8669, DOI 10.17487/RFC8669, December 2019, <https://www.rfc-editor.org/info/rfc8669>.

[RFC8814] Tantsura, J., Chunduri, U., Talaulikar, K., Mirsky, G., and N. Triantafillis, «Signaling Maximum SID Depth (MSD) Using the Border Gateway Protocol — Link State», RFC 8814, DOI 10.17487/RFC8814, August 2020, <https://www.rfc-editor.org/info/rfc8814>.

[W3C.REC-xml11-20060816] Bray, T., Paoli, J., Sperberg-McQueen, M., Maler, E., Yergeau, F., and J. Cowan, «Extensible Markup Language (XML) 1.1 (Second Edition)», World Wide Web Consortium Recommendation REC-xml11-20060816, 16 August 2006, <https://www.w3.org/TR/2006/REC-xml11-20060816>.

11.2. Дополнительная литература

[RFC8340] Bjorklund, M. and L. Berger, Ed., «YANG Tree Diagrams», BCP 215, RFC 8340, DOI 10.17487/RFC8340, March 2018, <https://www.rfc-editor.org/info/rfc8340>.

[RFC8792] Watsen, K., Auerswald, E., Farrel, A., and Q. Wu, «Handling Long Lines in Content of Internet-Drafts and RFCs», RFC 8792, DOI 10.17487/RFC8792, June 2020, <https://www.rfc-editor.org/info/rfc8792>.

Приложение A. Примеры конфигурации

В примерах ниже символ \ служит для разрыва длинных строк, как описано в [RFC8792].

A.1. SR-MPLS м IPv4

Ниже представлен пример XML [W3C.REC-xml11-20060816], использующий модули YANG SR-MPLS с адресами IPv4.

   <routing xmlns="urn:ietf:params:xml:ns:yang:ietf-routing">
     <segment-routing
       xmlns="urn:ietf:params:xml:ns:yang:ietf-segment-routing">
       <sr-mpls
         xmlns="urn:ietf:params:xml:ns:yang:ietf-segment-routing-mpls">
         <bindings>
           <mapping-server>
             <policy>
               <name>mapping 1</name>
               <entries>
                 <mapping-entry>
                   <prefix>198.51.100.0/24</prefix>
                   <algorithm xmlns:sr-cmn="urn:ietf:params:xml:ns:yang\
                     :ietf-segment-routing-common">\
                     sr-cmn:prefix-sid-algorithm-shortest-path\
                   </algorithm>
                   <start-sid>200</start-sid>
                   <range>100</range>
                 </mapping-entry>
               </entries>
             </policy>
           </mapping-server>
           <connected-prefix-sid-map>
             <connected-prefix-sid>
               <prefix>192.0.2.0/24</prefix>
               <algorithm xmlns:sr-cmn="urn:ietf:params:xml:ns:yang:\
                 ietf-segment-routing-common">\
                 sr-cmn:prefix-sid-algorithm-strict-spf</algorithm>
               <start-sid>100</start-sid>
               <range>1</range>
               <last-hop-behavior>php</last-hop-behavior>
             </connected-prefix-sid>
           </connected-prefix-sid-map>
         </bindings>
         <srgb>
           <srgb>
             <lower-bound>45000</lower-bound>
             <upper-bound>55000</upper-bound>
           </srgb>
         </srgb>
       </sr-mpls>
     </segment-routing>
   </routing>

Ниже тот же пример представлен в формате JSON.

   {
     "ietf-routing:routing": {
       "ietf-segment-routing:segment-routing": {
         "ietf-segment-routing-mpls:sr-mpls": {
           "bindings": {
             "mapping-server": {
               "policy": [
                 {
                   "name": "mapping 1",
                   "entries": {
                     "mapping-entry": [
                       {
                         "prefix": "198.51.100.0/24",
                         "algorithm": "ietf-segment-routing-common:\
                         prefix-sid-algorithm-shortest-path",
                         "start-sid": 200,
                         "range": 100
                       }
                     ]
                   }
                 }
               ]
             },
             "connected-prefix-sid-map": {
               "connected-prefix-sid": [
                 {
                   "prefix": "192.0.2.0/24",
                   "algorithm": "ietf-segment-routing-common:\
                   prefix-sid-algorithm-strict-spf",
                   "start-sid": 100,
                   "range": 1,
                   "last-hop-behavior": "php"
                 }
               ]
             }
           },
           "srgb": {
             "srgb": [
               {
                 "lower-bound": 45000,
                 "upper-bound": 55000
               }
             ]
           }
         }
       }
     }
   }

A.2. SR-MPLS с IPv6

Ниже представлен пример XML [W3C.REC-xml11-20060816], использующий модули YANG SR-MPLS с адресами IPv6.

   <routing xmlns="urn:ietf:params:xml:ns:yang:ietf-routing">
     <segment-routing
       xmlns="urn:ietf:params:xml:ns:yang:ietf-segment-routing">
       <sr-mpls
         xmlns="urn:ietf:params:xml:ns:yang:ietf-segment-routing-mpls">
         <bindings>
           <mapping-server>
             <policy>
               <name>mapping 1</name>
               <entries>
                 <mapping-entry>
                   <prefix>2001:db8:aaaa:bbbb::/64</prefix>
                   <algorithm xmlns:sr-cmn="urn:ietf:params:xml:ns:yang\
                     :ietf-segment-routing-common">\
                     sr-cmn:prefix-sid-algorithm-shortest-path\
                   </algorithm>
                   <start-sid>200</start-sid>
                   <range>100</range>
                 </mapping-entry>
               </entries>
             </policy>
           </mapping-server>
           <connected-prefix-sid-map>
             <connected-prefix-sid>
               <prefix>2001:db8:aaaa:cccc::/64</prefix>
               <algorithm xmlns:sr-cmn="urn:ietf:params:xml:ns:yang:\
                 ietf-segment-routing-common">\
                 sr-cmn:prefix-sid-algorithm-strict-spf</algorithm>
               <start-sid>100</start-sid>
               <range>1</range>
               <last-hop-behavior>php</last-hop-behavior>
             </connected-prefix-sid>
           </connected-prefix-sid-map>
         </bindings>
         <srgb>
           <srgb>
             <lower-bound>45000</lower-bound>
             <upper-bound>55000</upper-bound>
           </srgb>
         </srgb>
       </sr-mpls>
     </segment-routing>
   </routing>

Ниже тот же пример представлен в формате JSON.

   {
     "ietf-routing:routing": {
       "ietf-segment-routing:segment-routing": {
         "ietf-segment-routing-mpls:sr-mpls": {
           "bindings": {
             "mapping-server": {
               "policy": [
                 {
                   "name": "mapping 1",
                   "entries": {
                     "mapping-entry": [
                       {
                         "prefix": "2001:db8:aaaa:bbbb::/64",
                         "algorithm": "ietf-segment-routing-common:\
                         prefix-sid-algorithm-shortest-path",
                         "start-sid": 200,
                         "range": 100
                       }
                     ]
                   }
                 }
               ]
             },
             "connected-prefix-sid-map": {
               "connected-prefix-sid": [
                 {
                   "prefix": "2001:db8:aaaa:cccc::/64",
                   "algorithm": "ietf-segment-routing-common:\
                   prefix-sid-algorithm-strict-spf",
                   "start-sid": 100,
                   "range": 1,
                   "last-hop-behavior": "php"
                 }
               ]
             }
           },
           "srgb": {
             "srgb": [
               {
                 "lower-bound": 45000,
                 "upper-bound": 55000
               }
             ]
           }
         }
       }
     }
   }

Благодарности

Авторы благодарны Derek Yeung, Greg Hankins, Hannes Gredler, Uma Chunduri, Jeffrey Zhang, Shradda Hedge, Les Ginsberg за их вклад в работу.

Спасибо Ladislav Lhotka и Tom Petch за подробные рецензии и полезные комментари.

Авторы признательны Benjamin Kaduk, Alvaro Retana, and Roman Danyliw за рецензию IESG и комментарии.

Адреса авторов


Перевод на русский язык

Николай Малых

nmalykh@protokols.ru

1Internet Engineering Task Force — комиссия по решению инженерных задач Internet.

2Internet Engineering Steering Group — комиссия по инженерным разработкам Internet.

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

Рубрика: RFC | Оставить комментарий

RFC 8994 An Autonomic Control Plane (ACP)

Internet Engineering Task Force (IETF)                    T. Eckert, Ed.
Request for Comments: 8994                                 Futurewei USA
Category: Standards Track                              M. Behringer, Ed.
ISSN: 2070-1721                                                         
                                                            S. Bjarnason
                                                          Arbor Networks
                                                                May 2021

An Autonomic Control Plane (ACP)

Автономная плоскость управления

PDF

Аннотация

Автономным (самоуправляемым) функциям для взаимодействия нужна плоскость управления, которая зависит от некой адресации и маршрутизации. Такой автономной плоскости управления (Autonomic Control Plane или ACP) в идеале следует быть самоуправляемой и максимально независимой от конфигурации. В этом документе определена такая плоскость управления, предназначенная прежде всего для работы с автономными функциями. Она также служит отдельным виртуальным каналом (virtual out-of-band channel) для взаимодействий OAM через сеть, который обеспечивает автоматически настраиваемый, поэтапно (hop-by-hop) аутентифицируемый и шифрованный обмен данными с автоматической настройкой IPv6 даже в ненастроенной или некорректно настроенной сети.

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

Документ содержит проект стандарта Internet (Standards Track).

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

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

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

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

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

1. Введение (информационное)

Автономные сети (Autonomic Networking) — это концепция самоуправления — автономные функции самостоятельно настраиваются и согласуют параметры и настройки через сеть. В документе Autonomic Networking: Definitions and Design Goals [RFC7575] рассмотрены основные идеи и цели разработки самоуправляемых (автономных) сетей. Анализ пробелов в части таких разработок приведён в документе General Gap Analysis for Autonomic Networking [RFC7576]. Эталонная архитектура сетей с самоуправлением в рамках IETF представленв в документе A Reference Model for Autonomic Networking [RFC8993].

Для функций самоуправления нужна соответствующая коммуникационная инфраструктура, которая должна быть защищённой, отказоустойчивой и пригодной для всех автономных функций. В разделе 5 [RFC7575] описана такая инфраструктура, названная автономной плоскостью управления (Autonomic Control Plane или ACP). Для лучшего понимания её следовало бы назвать автономной коммуникационной инфраструктурой для OAM и управления (Autonomic communications infrastructure for OAM and control), но для согласованности документов здесь применяется термин ACP.

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

Пример отказа при управлении по основному каналу в результате внесённых оператором ошибок в конфигурации, приведён в разделе III.B.15 (стр. 8) [FCC].

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

Традиционно для решения этой проблемы или по меньшей мере восстановления используются физически отделённые (out-of-band) сети управления. В худшем случае персонал направляется на сайт для доступа через отдельные порты управления (служебный порт, последовательная консоль, порт Ethernet-управления). Однако оба варианты недёшевы.

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

В этом документе описано модульное решение для самоформирующейся, самоуправляемой и самозащищающейся плоскости ACP, представляющей собой виртуальную отдельную (out-of-band) сеть с максимальной независимостью от конфигурации, адресации и маршрутизации, чтобы избежать проблем самозависимости современных сетей IP при работе по основным (in-band) каналам той же физической сети, для управления которой она служит. Устройство ACP рассчитано на максимально возможное сочетание устойчивости отдельных (out-of-band) сетей управления с низкой стоимостью традиционного управления сетями IP по основному каналу (in-band). Детали решения описаны в разделе 6. Создание ACP (нормативный раздел).

В полностью автономной сети без унаследованных функций и протоколов управление и/или поддержки плоскость данных будет просто плоскостью пересылки для пакетов «данных» IPv6, которые отличаются от пакетов управления и поддержки, пересылаемых ACP. В такой сети не будет неавтономного управления узлами и неавтономной плоскости управления.

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

При добавлении функциональности ACP на узлах без автономных функций управления и поддержки (неавтономные узлы или узлы без самоуправления), ACP лучше абстрагировать как специальный экземпляр виртуальной маршрутизации и пересылки (Virtual Routing and Forwarding или VRF) — виртуальный маршрутизатор, а имеющуюся плоскость управления считать частью плоскости данных, чтобы избежать применения для этого случая особой терминологии.

Подобно плоскости пересылки для пакетов «данных», функциями неавтономного управления и поддержки можно управлять (использовать их) через ACP. Такая терминология согласуется с имеющимися документами, такими как Using an Autonomic Control Plane for Stable Connectivity of Network Operations, Administration, and Maintenance (OAM) [RFC8368].

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

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

  1. Взаимодействие автономных функций через ACP и прямой поддержкой функций самоуправляемых сетей, как описано в [RFC8993]. Например, протокол GRASP («GeneRic Autonomic Signaling Protocol (GRASP)» [RFC8990]) работает через ACP и использует её как «подложку защищённого транспорта».

  2. Контроллер или система управления сетью может использовать ACP для защищённой загрузки сетевых устройств в удалённых точках, даже когда сеть (плоскость данных) к ним ещё не настроена. Настройка загрузки, зависящая от плоскости данных, не требуется. Пример процесса защищённой загрузки представлен в Bootstrapping Remote Secure Key Infrastructure (BRSKI) [RFC8995].

  3. Оператор может применять ACP для доступа к удаленным устройствам с использованием таких протоколов, как SSH (Secure SHell) или NETCONF (Network Configuration Protocol) даже в ненастроенной или некорректно настроенной сети.

В разделе 3 эти задачи рассмотрены на примерах использования ACP, раздел 4 задаёт требования, а раздел 5 содержит обзор устройства ACP. Нормативная часть документа начинается с раздела 6, где задана спецификация ACP. В разделе 7 описана поддержка ACP в коммутаторах (L2), а раздел 8 посвящён интеграции с узлами и сетями, не поддерживающими ACP. Остальные разделы не являются нормативными. В разделе 10 описаны преимущества ACP, раздел 9 содержит эксплуатационные рекомендации, в Приложении A приведены дополнительные сведения и рассмотрены возможные расширения, которые не были применены в спецификации, но считаются важными. Реализация Приложения A не требуется для создания полной и совместимой реализации ACP.

ACP обеспечивает защищённую связность IPv6 и может применяться для защищённых соединений не только в самоуправлении, как требует для ACP [RFC7575], но и для традиционного (централизованного) управления. ACP можно реализовать и использовать без других компонентов автономных сетей, требуется лишь GRASP. ACP полагается на протокол GRASP с незапрашиваемым обнаружением локальных каналов (Discovery Unsolicited Link-Local или DULL, параграф 6.4) для автоматического поиска соседей ACP и включает экземпляр ACP GRASP для обнаружения служб клиентами ACP (параграф 6.9), в том числе для поддержки сертификатов ACP.

В [RFC8368] описано, как можно использовать ACP автономно для обеспечения защищённой и стабильной связности автономных и неавтономных приложений OAM, в частности, на современных неавтономных узлах и/или в сетях. Документ также объясняет, как существующие управляющие решения могут применять ACP вместе с традиционными моделями управления, когда следует применять ACP и как можно объединить ACP с системами OAM, поддерживающими лишь IPv4.

Объединение ACP с BRSKI3 [RFC8995] ведёт к автономной сетевой инфраструктуре (Autonomic Network Infrastructure или ANI) [RFC8993], обеспечивающей автономную связность с защищённой автоматической (zero-touch) загрузкой из BRSKI. Сама инфраструктура ANI не создаёт автономной сети, но позволяет организовать более или менее автономные сети на своей основе, используя централизованную автоматизацию в стиле SDN (см. Software-Defined Networking (SDN): Layers and Architecture Terminology [RFC7426]) или распределенную автоматизацию через автономные агенты сервиса (Autonomic Service Agent или ASA) и/или автономные функции (Autonomic Functions или AF). Дополнительные сведения можно получить из [RFC8993].

1.1. Применимость и область действия

Используемые в этом параграфе термины приведены в разделе 2. Термины и сокращения (информационный раздел).

Устройство ACP, заданное этим документом, считается применимым ко всем типам «профессионально управляемых» сетей: сервис-провайдеры, ЛВС, городские (Metropolitan Area Network или MAN/Metro), распределенные (Wide Area Network или WAN), корпоративные информационные (Enterprise Information Technology или IT), технологические (Operational Technology или OT) сети. ACP может работать с оборудованием сетевого (L3) и канального L2 уровня, таким как мосты (см. раздел 7. Поддержка ACP на коммутаторах и портах L2 (нормативный)). Поэтапная (hop-by-hop) аутентификация, защита целостности и конфиденциальности, применяемая в ACP, может согласовываться, поэтому ACP можно распространить на среды с разными предпочтительными протоколами. Минимальные требования этого документа нацелены на обеспечения максимальной совместимости, задавая поддержку опций в зависимости от типа устройств — IPsec (см. Security Architecture for the Internet Protocol [RFC4301]) или защита транспорта дейтаграмм (Datagram Transport Layer Security или DTLS, см. параграф 6.8.4. ACP по протоколу DTLS).

Реализация ACP включает код инфраструктуры открытых ключей (Public Key Infrastructure или PKI) для сертификатов ACP, в том числе EST (см. Enrollment over Secure Transport [RFC7030]), GRASP, UDP, TCP, защита транспортного уровня (Transport Layer Security или TLS, см. параграф 6.1. Требования к использованию TLS). Дополнительные сведения в части защищенности и надёжности GRASP и EST, применяемого в защищённых каналах ACP (таких как IPsec и DTLS) и экземплярах пересылки и маршрутизации пакетов IPv6 с помощью RPL приведены в документе RPL: IPv6 Routing Protocol for Low-Power and Lossy Networks [RFC6550] (отдельно от маршрутизации и пересылки пользовательских пакетов в плоскости данных).

В ACP применяется только IPv6, чтобы избежать сложностей работы с двойным стеком (IPv6 и IPv4). Тем не менее, ACP можно интегрировать без изменений с сетевыми устройствами, поддерживающими лишь IPv4. Плоскость данных менять не потребуется и она может по-прежнему работать лишь с IPv4. Для таких устройств протокол IPv6 будет дополнительной областью реализации, требуемой лишь для ACP.

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

Протокол RPL был выбран потому, что у него менее жёсткие требования к размеру таблиц маршрутизации по сравнению с другими протоколами с автономно настраиваемыми областями. Опыт реализации больших сетей IoT4 служит основой для широкого развёртывания RPL. Выбранный в ACP профиль RPL не использует каких-либо специфических для этого протокола функций плоскости данных (заголовки расширения IPv6), делая его реализацию исключительно программным требованием плоскости управления.

GRASP является единственным совершенно новым протоколом в ACP и его выбор обусловлен отсутствием другого протокола, обеспечивающего требуемые для ACP функции. Протокол GRASP был разработан специально для этого.

ACP подходит для устройств с ограничениями в части CPU и памяти, а также сетей, ограниченных по скорости и надёжности, но этот документ не пытается определить максимальные ограничения для устройств и сетей применительно к ACP. RPL и DTLS для защищённых каналов ACP уже делают ACP подходящим решением для сред с ограничениями. Поддержка устройств с ограничениями в этой спецификации условна и неполна, поскольку для надёжного транспорта GRASP (параграф 6.9.2. ACP как защищённая транспортная подложка для GRASP) заданы лишь TCP и TLS. В Приложении A.8 обсуждаются будущие стандарты и подходящие расширения и вариации ACP, которые могут лучше соответствовать ожиданиям и отличать от положенных в основу текущего решения, включая лучшую поддержку устройств с ограничениями.

2. Термины и сокращения (информационный раздел)

Этот документ служит нормативной спецификацией поведения узлов ACP, а также разъяснением контекста с помощью описания требований, преимуществ, архитектуры и аспектов работы. Нормативные разделы помечены и используют ключевые слова BCP 14. Информативные разделы тоже помечены, но ключевых слов не используют.

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

Ниже указаны используемые в документе термины (в алфавитном порядке). Вводимые документом термины объясняются при первом использовании, а в список включены лишь для полноты.

ACP — Autonomic Control Plane

Автономная плоскость управления — автономная (самоуправляемая) функция, определённая в этом документе. Она обеспечивает защищённую, автоматизированную (zero-touch), транзитивную (через всю сеть) связность IPv6 для всех узлов в одном домене ACP, а также экземпляр GRASP, работающий через соединения ACP IPv6. Основным назначением ACP является использование в качестве компонента ANI для обеспечения работы автономных сетей (Autonomic Network), а также в в простых сетях ANI (без автономных функций) или полностью самостоятельно.

ACP address — адрес ACP

Адрес IPv6, назначенный узлу ACP. Хранится в поле acp-node-name сертификата ACP.

ACP address range or set — диапазон или набор адресов ACP

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

ACP certificate — сертификат ACP

Сертификат отождествления локального устройства (Local Device IDentity или LDevID), соответствующий профилю Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile [RFC5280] и содержащий поле acp-node-name, используемое ACP для выяснения его адреса ACP, а также выведения и криптографической оценки его принадлежности к домену ACP. В контекте ANI сертификат ACP называют также сертификатом ANI, в контексте AN — сертификатом AN.

ACP connect interface — интерфейс соединения ACP

Интерфейс на узле ACP, обеспечивающий доступ к не поддерживающим ACP узлам без использования защищённого канала ACP. См. параграф 8.1.1. Контроллер или NMS без поддержки ACP.

ACP domain — домен ACP

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

ACP loopback interface — петлевой интерфейс ACP

Петлевой (loopback) интерфейс в ACP VRF с адресом ACP. См. параграф 6.13.5.1. Петлевые интерфейсы ACP.

ACP network — сеть ACP

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

ACP (ULA) prefix(es) — префикс(ы) ACP (ULA)

Префиксы IPv6 /48, используемые в ACP. В нормальном или простом случае ACP имеет один уникальный локальный префикс (Unique Local Address или ULA), см. параграф 6.11. Адресация внутри ACP. Таблица маршрутизации ACP может включать множество префиксов ULA, если применяется опция rsub для создания нескольких префиксов ULA (6.2.2. AcpNodeName в сертификате ACP). ACP может также включать иные (не ULA) префиксы, если они настроены на интерфейсах ACP connect (8.1.1. Контроллер или NMS без поддержки ACP).

ACP secure channel — защищённый канал ACP

Канал, аутентифицированный с помощью сертификатов ACP, обеспечивающий защиту целостности и конфиденциальности путём шифрования. Такие каналы организуются между (обычно) смежными узлами ACP для передачи трафика ACP VRF по основному каналу (in-band) через те же соединения и пути, что и трафик данных, но с изоляцией от него и защитой.

ACP secure channel protocol — протокол защищённого канала ACP

Протокол для создания защищённого канала ACP, например, Internet Key Exchange Protocol version 2 (IKEv2) с IPsec или DTLS.

ACP virtual interface — виртуальный интерфейс ACP

Интерфейс в ACP VRF, отображенный на один или несколько защищённых каналов ACP (6.13.5. Интерфейсы ACP).

acp-node-name field — поле имени узла ACP

Информационное поле в сертификате ACP, где хранятся относящиеся к ACP сведения: имя домена ACP, адрес узла ACP IPv6, а также необязательные атрибуты роли узла.

AN — Autonomic Network

Автономная (самоуправляемая) сеть в соответствии с [RFC8993]. Основными её компонентами являются ANI, автономные функции и намерения (Intent).

(AN) Domain Name

Полное доменное имя (Fully Qualified Domain Name или FQDN) в поле acp-node-name сертификата домена (6.2. Домен, сертификат и сеть ACP).

ANI (nodes/network) — Autonomic Network Infrastructure

Автономная сетевая инфраструктура (ANI) является инфраструктурой для обеспечения работы автономных сетей. Она включает ACP, BRSKI и GRASP. Каждая автономная сеть включает ANI, но не каждой ANI требуется включать автономные функции помимо ANI (и Intent). Сеть ANI без других автономных функций может, например, поддерживать защищённую автоматическую (zero-touch) загрузку и стабильную связность для сетей SDN (см. [RFC8368]).

ANIMA — Autonomic Networking Integrated Model and Approach — модель и подход для автономных сетей

ACP, BRSKI и GRASP являются спецификациями рабочей группы IETF ANIMA.

ASA — Autonomic Service Agent

Автономный агент службы — программные модули, работающие в устройстве ANI. Компоненты, образующие ANI (BRSKI, ACP, GRASP), также описываются как агенты ASA.

autonomic function — автономная функция

Функция и/или служба в автономной сети (AN), состоящая из одного или нескольких агентов ASA на одном или нескольких узлах ANI.

BRSKI — Bootstrapping Remote Secure Key Infrastructure [RFC8995]

Протокол, расширяющий EST для защищённой автоматической загрузки в сочетании с ACP. Узлы ANI используют ACP, BRSKI, GRASP.

CA — Certification Authority.

Удостоверяющий центр — орган, выпускающий цифровые сертификаты. CA применяет свой секретный ключ для подписывания выданных сертификатов. Доверяющая сторона применяет открытый ключ CA для проверки подписи.

CRL — Certificate Revocation List

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

data plane — плоскость данных

Контрапункт ACP VRF на узле ACP. Служит для пересылки пользовательского трафика в неавтономных узлах и/или, а также для выполнения функций неавтономных плоскостей управления и/или поддержки. На узле полностью автономной сети плоскость данных управляется через автономные функции и намерения (раздел 1).

device — устройство

Физическая система или узел.

enrollment — зачисление

Процесс, посредством которого узел аутентифицирует себя в сети с исходным отождествлением, которое часто называют сертификатом IDevID (Initial Device IDentity), и получает от сети соответствующее отождествления (идентификатор), которое часто называют сертификатом LDevID, и сертификаты одной или нескольких привязок доверия. В ACP сертификат LDevID называют сертификатом ACP.

EST — Enrollment over Secure Transport [RFC7030]

Стандартный протокол IETF для зачисления узла с сертификатом LdevID. Протокол BRSKI основан на EST.

GRASP — GeneRic Autonomic Signaling Protocol

Расширяемый протокол сигнализации, требуемый в ACP для обнаружения соседей. ACP также обеспечивает защищённую транспортную подложку для экземпляра ACP GRASP, который работает по защищённым каналам ACP для поддержки BRSKI и других автономных функций, NOC и/или OAM (см. [RFC8990]).

IDevID

Сертификат Initial Device IDentity X.509, установленный производителем нового оборудования. Сертификат IDevID содержит сведения для отождествления узла в контексте его производителя и/или изготовителя, такие как модель и/или тип и серийный номер (см. [AR8021]). Сертификат IDevID не может быть идентификатором узла для ACP, поскольку он не предоставлен владельцем сети и не может напрямую указывать домен ACP, к которому относится.

In-band — по основному каналу (для управления или сигнализации)

Трафик управления и/или сигнализация плоскости управления в том же канале с использованием тех же ресурсов сети, таких как маршрутизаторы и/или коммутаторы и сетевые каналы, которыми он управляет. In-band-управление является стандартным механизмом поддержки и сигнализации в сетях IP. По сравнению с отдельными каналами (out-of-band) механизмы in-band не требуют дополнительных физических ресурсов, но могут создавать циклические зависимости, влияющие на работу (см. раздел 1).

Intent — намерения

Язык правил для автономной сети в соответствии с [RFC8993].

Loopback interface — петлевой интерфейс

См. ACP loopback interface.

LDevID

Local Device IDentity — это сертификат X.509, установленный при зачислении в сеть. Сертификат домена в ACP является сертификатом LDevID (см. [AR8021]).

management — управление, поддержка

Используется в этом документе как синоним OAM.

MASA (служба) — Manufacturer Authorized Signing Authority

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

MIC — Manufacturer Installed Certificate

Установленный производителем сертификат. Синоним IDevID в некоторых документах (здесь не применяется).

native interface — естественный интерфейс

Интерфейс, существующий на узле без настройки уже работающего узла. На физических узлах это обычно физические интерфейсы, на виртуальных — их эквивалент.

NOC — Network Operations Center

Центр сетевых операций.

node — узел

Система, поддерживающая ACP в соответствии с этим документом. Узел может быть виртуальным или физическим. Физические узлы называют устройствами.

Node-ID — идентификатор узла

Идентификатор узла ACP внутри ACP, может быть 64- (6.11.3. Субсхема адресации ACP Zone (ACP-Zone)) или 78-битовым (6.11.5. Субсхемы ACP Vlong (ACP-Vlong-8 и ACP-Vlong-16)) адресом ACP.

OAM — Operations, Administration, and Management

Эксплуатация, администрирование, управление (включая мониторинг).

Operational Technology (OT) — технологическая сеть

«Оборудование или программа, выделенные для обнаружения или инициирования изменений в физических процессах путём прямого мониторинга и/или управления физическими устройствами, такими как клапаны, насосы и т. п.» [OP-TECH]. В большинстве современных систем сети OT отделены от сетей IT.

out-of-band (management) network — сеть (управления) по отдельному каналу

Вторичная (вспомогательная) сеть, применяемая для управления основной сетью. Оборудование основной сети подключено к сети out-of-band через выделенные порты управления на оборудовании первичной сети. Исторически чаще всего применялись последовательные (консольные) порты управления, но в современном оборудовании часто имеются порты Ethernet, предназначенные лишь для управления. Сеть out-of-band обеспечивает доступ к управлению первичной сетью независимо от состояния последней (см. раздел 1).

out-of-band network, virtual — виртуальная сеть out-of-band

ACP можно называть сетью out-of-band для управления и поддержки, поскольку эта плоскость управления пытается обеспечить преимущества (физически) отдельной сети при работе по основному каналу (in-band) физической сети (см. раздел 1).

root CA — root Certification Authority

Корневой удостоверяющий центр. CA для которого могут применяться процедуры обновления ключа коревого CA (параграф 4.4 в [RFC7030]).

RPL

Протокол маршрутизации IPv6 Routing Protocol для сетей со слабым питанием и потерями (Low-Power and Lossy Networks) [RFC6550]. Этот протокол применяется в ACP.

registrar (ACP, ANI/BRSKI) — регистратор

Регистратор ACP — это человек или программа, организующая зачисление узлов ACP по сертификатам ACP. Узлы ANI используют BRSKI, поэтому регистраторов ANI называют ещё регистраторами BRSKI. Для узлов ACP без ANI этот документ не задаёт механизмов регистрации (см. 6.11.7. Регистраторы ACP). Обновление и иное обслуживание (например, отзыв) сертификатов ACP могут выполнять не только регистраторы. Для обновления сертификатов ACP требуется поддержка EST (см. 6.2.5. Поддержка сертификата и привязки доверия). BRSKI является расширением EST, поэтому регистраторы ANI/BRSKI легко могут поддерживать обновление сертификатов ACP в дополнение к начальному зачислению.

RPI — RPL Packet Information

Информация пакета RPL — заголовок расширения для использования с RPL. Не применяется с RPL в ACP (см. 6.12.1.13. Информационный пакет RPL).

RPL — Routing Protocol for Low-Power and Lossy Networks

Протокол маршрутизации, применяемый в ACP (см. 6.12. Маршрутизация в ACP).

sUDI — secured Unique Device Identifier

Защищённый уникальный идентификатор устройства — синоним IDevID в иных документах (здесь на применяется).

TA — Trust Anchor

Привязка доверия — сущность, которой доверяют в плане проверки пригодности сертификатов. Сведения в TA, такие как самоподписанные сертификаты TA, настраиваются на узле ACP в процессе зачисления (см. параграф 6.1.1 в [RFC5280]).

UDI — Unique Device Identifier

Уникальный идентификатор устройства. В контексте этого документа — незащищённые идентификационные данные узла, обычно включающие хотя бы модель и/или серийный номер устройства, зачастую в формате производителя (см. sUDI и LDevID).

ULA (Global ID prefix)

Уникальный локальный адрес (Unique Local Address) — адрес IPv6 из блока fc00::/7, определеного в Unique Local IPv6 Unicast Addresses [RFC4193]. ULA является в IPv6 преемником приватных адресов IPv4 (Address Allocation for Private Internets [RFC1918]). Адреса ULA имеют существенные отличия от приватных адресов IPv4, важно для применений в ACP, такие как локально назначаемый префикс Global ID, занимающий первые 48 битов адреса ULA (параграф 3.2.1 в [RFC4193]). В этом документе такие префиксы называются префиксами ULA.

(ACP) VRF

ACP в этом документе моделируется как экземпляр виртульной маршрутизации и пересылки (Virtual Routing and Forwarding). Это значит, что ACP базируется на «виртуальных маршрутизаторах», имеющих отдельную таблицу пересылки IPv6, с которой связаны виртуальные интерфейсы ACP, и соответствующую таблицу маршрутизации IPv6, отделённые от плоскости данных. В отличие от VRF на MPLS/VPN PE (BGP/MPLS IP Virtual Private Networks (VPNs) [RFC4364]) и LISP xTR (The Locator/ID Separation Protocol (LISP) [RFC6830]), ACP VRF не имеет каких-либо специальных функций, ориентированных на ядро, и/или протоколов маршрутизации и/или отображения, используемых разными экземплярами VRF. В фирменной продукции VRF, подобные ACP VRF, могут называть ещё VRF-lite.

(ACP) Zone

Зона ACP — это набор узлов ACP, использующих одно значение поля зоны в своих адресах ACP в соответствии с параграфом 6.11.3. Субсхема адресации ACP Zone (ACP-Zone). Зоны служат механизмом поддержки структурированной адресации ACP внутри одного префикса ULA /48.

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

3. Примеры использования ACP (информационный раздел)

В этом разделе обобщены примеры использования, которые предназначены для поддержки ACP. Для их понимания и связи с более широким кругом применения автономных сетей следует прочесть Autonomic Networking Use Case for Distributed Detection of Service Level Agreement (SLA) Violations [RFC8316].

3.1. Инфраструктура для автономных функций

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

3.2. Безопасная начальная загрузка через незащищённую сеть

Сегодня для начальной загрузки нового узла обычно требуется полная и корректная настройка, адресация и защита всех узлов между ним и контролирующим узлом, таким как контроллер SDN (см. [RFC7426]). Начальная загрузка и настройка узлов выполняется кольцами вокруг контроллера — сначала настраивается и загружается ближайшее кольцо, затем следующее и т. д. Без консольного доступа (например, через отдельную сеть) сегодня невозможно обеспечить защищённый доступ к устройствам до настройки всей сети на пути к ним.

С ACP защищённая начальная загрузки новых устройств и новых сетей может происходить без настройки устройств на пути. Когда все устройства на пути поддерживают ACP и механизм автоматической (zero-touch) загрузки, такой как BRSKI, можно запустить ACP в сети ненастроенных устройств без вмешательства оператора и/или системы обеспечения. ACP также предоставляет дополнительную защиту для любых механизмов начальной загрузки благодаря шифруемому обнаружению (ACP GRASP) регистраторов и других серверов начальной загрузки с помощью посредников, подключённых к загружаемым узлам. Шифрование ACP скрывает участников процесса (заявитель и регистратор), осложняя поиск жертвы для атаки. Можно также использовать сертификат ACP для сквозного шифрования связи при загрузке между посредниками и серверами. Отметим, что начальная загрузка здесь включает не только первый шаг, который может быть обеспечен BRSKI (ключи защиты),но и последующие атапы, где загружаются конфигурации.

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

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

На связность плоскости данных могут влиять ошибки и отказы. Примеры включают ошибки в настройке, которые делают серверы AAA5 недоступными или блокируется доступ администратора к устройству, проблемы маршрутизации и адресации могут делать устройства недоступными, отключение интерфейсов, через которые работают сеансы управления может безвозвратно лишить администратора доступа к устройству. Традиционно устранение таких проблем достигается лишь за счёт отдельных (out-of-band) каналов доступа через консольный порт или порт Ethernet для управления.

Зависимости плоскости данных влияют и на приложения в NOC, такие как контроллеры SDN. Некоторые изменения в сети сложно реализовать, поскольку они могут влиять на доступность устройств. Примеры включают смену адресов или масок, маршрутизации или политики безопасности. Сегодня для таких изменений требуется разработки точного плана поэтапной (hop-by-hop) настройки.

Отметим, что конкретные функции плоскости управления для плоскости данных часто зависят от возможности пересылать пакеты управления через плоскость данных. Пакеты проверки живучести и сигнализация протоколов маршрутизации передаются через плоскость данных для проверки доступности, сигнальные пакеты IPv4 служат для маршрутизации IPv4, а сигнальные пакеты IPv6 — для маршрутизации IPv6.

При соответствующей реализации (см. параграф 6.13.2. Адресация на защищённых каналах) ACP обеспечивает доступность независимо от плоскости данных. Это позволяет плоскостям управления и OAM работать более надёжно.

  • Для протоколов плоскости поддержки (management) ACP обеспечивает функциональность виртуальных отдельных каналов (Virtual out-of-Band или VooB), предоставляя связность со всеми узлами независимо от конфигурации плоскости данных, а также таблиц маршрутизации и пересылки.

  • Протоколам плоскости управления (control) ACP позволяет работать даже при временных отказах плоскости данных и во время переходных процессов, таких как смена маршрутизации, которые хотя бы временно могут влиять на плоскость управления. Это особенно важно для автономных агентов служб, которые могут влиять на связность плоскости данных.

В документе Using Autonomic Control Plane for Stable Connectivity of Network OAM [RFC8368] примеры использования ACP рассмотрены более подробно и описано применение ACP в сетевой практике.

4. Требования (информационный раздел)

Ниже указаны требования информационного характера для проектирования ACP, основанные на рассмотренных в разделе 3 примерах. Требования к ACP, указанные в нормативных разделах соответствуют или превосходят их.

ACP1

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

ACP2

Адресное пространство ACP должно быть отделено от адресов плоскости данных. Это обеспечит трассировку, упростит отладку, отделит от плоскости данных и защиты инфраструктуры (фильтрация по адресам).

ACP3

Адресное пространство ACP должно управляться автономно. Это упростит начальную загрузку и (автономную) настройку, повысит отказоустойчивость (администратор не сможет легко нарушить работу сети). Для этого в данном документе применяется схема ULA [RFC4193].

ACP4

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

ACP5

В ACP должна обеспечиваться защита. Проходящие через ACP сообщение должны аутентифицироваться (исходить от доверенных узлов) и настоятельно рекомендуется шифровать их.

Разъяснение требования ACP4. В полностью автономной сети (AN) все надавно написанные агенты служб (ASA) могут взаимодействовать с каждым другим агентом исключительно через GRASP и если бы это было единственным требованием к ACP, не требовась бы связность на уровне IPv6 между узлами, хватило бы GRASP. Тем не менее, поскольку ACP требуется также поддерживать неавтономные сети, очень важно обеспечивать связность IPv6 через ACP для работы любых протоколов транспортного и прикладного уровня.

ACP работает в поэтапном режиме (hop-by-hop), поскольку такое взаимодействие можно организовать на основе адресов IPv6 link-local, которые автономны и не зависят от конфигурации (требование ACP1). Может потребоваться связность ACP через узлы, не относящиеся к ACP, например, для соединения узлов ACP через Internet. Это возможно, но вызывает зависимость от стабильной и отказоустойчивой маршрутизации через узлы без ACP (см. параграф 8.2).

5. Обзор (информационный раздел)

Когда узел имеет сертификат ACP (6.2.1. Сертификаты ACP) и ACP активна (9.3.5. Включение ACP и ANI на уровне узла), узел будет создавать свою плоскость ACP без настройки, как указано ниже.

  1. Узел создаёт экземпляр VRF или похожий виртуальный контекст для ACP.

  2. Узел назначает себе адрес (префикс) ULA IPv6 (6.11. Адресация внутри ACP), взятый из поля acp-node-name (6.2.2. AcpNodeName в сертификате ACP) в своём сертификате ACP (6.2.1. Сертификаты ACP), на петлевом (loopback) интерфейсе (6.11. Адресация внутри ACP) и соединяет этот интерфейс с ACP VRF.

  3. Узел создаёт список кандидатов в партнеры-соседи и типов каналов-кандидатов для организации смежности. Это происходит автоматически для всех кандидатов link-local (6.4. Обнаружение соседей с помощью DULL GRASP) через все естественные интерфейсы (9.3.4. Какие интерфейсы включать автоматически?). Если кандидат в партнёры обнаружен через несколько интерфейсов, будет создаваться 1 смежность на интерфейс. Если узел ACP имеет несколько интерфейсов, подключённых к той же подсети, в которой он служит коммутатором L2 для плоскости данных, он применяет методы ACP с коммутацией L2 (см. раздел 7).

  4. Для каждой записи списка кандидатов в соседи узел согласует защищённый туннель с использованием типа канала-кандидата (см. 6.6. Выбор канала).

  5. Узел проверяет подлинность партнёра при организации защищённого канала и разрешает ему стать частью ACP в соответствии с параграфом 6.2.3. Проверка принадлежности к домену ACP.

  6. Отказ при аутентификации кандидата в партнёры ведёт к дросселированию (throttle) попыток соединения, пока этот кандидат не будет обнаружен (см. 6.7. Проверка кандидата в соседи ACP).

  7. Каждый созданный защищённый канал отображается на виртуальный интерфейс ACP, который помещается в ACP VRF (см. 6.13.5.2. Виртуальные интерфейсы ACP).

  8. На каждом узле запускается облегченный протокол маршрутизации (6.12. Маршрутизация в ACP) для анонсирования доступности адреса (префикса) петлевого интерфейса ACP через плоскость ACP.

  9. На этом завершается создание ACP с защищёнными поэтапными (hop-by-hop) туннелями, автоматической адресацией и маршрутизацией. Узел становится участником ACP.

Примечания.

  • Ни одна из указанных выше операций (кроме настраиваемых явно) не отражается в конфигурации узла.

  • Системы управления сетью без ACP (network management systems или NMS) и контроллеры SDN нужно явно настраивать для соединения с ACP.

  • Для дополнительных партнерских соединений ACP через облака L3 без ACP требуется явная настройка (8.2. Соединение островков ACP через сети L3 без ACP (удалённые соседи)).

Схема ACP приведена на рисунке 1.

             Узел ACP 1                          Узел ACP 2
          ...................               ...................
Защищённый.                 .  Защищённый   .                 . Защищённый
канал        +-----------+  :  канал        :  +-----------+  :канал
   ..--------| ACP VRF   |---------------------| ACP VRF   |---------..
          : / \         / \<--Маршрутизация-->/ \         / \ :
          : \ /         \ /                   \ /         \ / :
   ..--------| Петлевой  |---------------------| Петлевой  |---------..
          :  | интерфейс |  :               :  | интерфейс |  :
          :  +-----------+  :               :  +-----------+  :
          :                 :               :                 :
          :   Плоскость     :...............:   Плоскость     :
          :   данных        :    Канал      :   данных        :
          :.................:               :.................:

Рисунок 1. ACP VRF и защищённые каналы.


Полученная в результате наложенная сеть обычно основана исключительно на поэтапных (hop-by-hop) туннелях. Это обусловлено адресацией link-local на каналах IPv6, не требующей настройки для соединения, что позволяет создавать ACP даже через ненастроенные узлы или при наличии в плоскости данных проблем адресации или маршрутизации.

6. Создание ACP (нормативный раздел)

В этом разделе описаны компоненты и этапы создания ACP. Плоскость ACP автоматически создаёт себя, что делает её «неразрушимой» при большинстве изменений в плоскости данных, включая ошибки в настройке маршрутизации, адресации, NAT, межсетевых экранов или иных фильтров трафика, которые непреднамеренно или иначе с неизбежностью влияют на трафик плоскости управления, такой как команды оператора через интерфейс (CLI) или сессии NETCONF на контроллере, через которые вносятся изменения в плоскость данных.

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

Атаки на сеть с использованием некорректных адресных и маршрутных сведений в плоскости данных не будут влиять на ACP. Даже повреждённые узлы ACP будут иметь существенно меньший фронт атак, потому что только очень немногие конфигурации ACP или интерфейсов (up/down) могут влиять на ACP, а в зависимости от конкретного устройства и таких атак можно избежать (см. 9.3. Включение и отключение ACP и ANI и 11. Вопросы безопасности).

Узел ACP может быть маршрутизатором, коммутатором, контроллером, хостом NMS или иным узлом с поддержкой IPv6. Узел изначально должен иметь свой сертификат ACP, а также (пустую) таблицу соседей (6.3. Таблица смежности ACP). После этого узел может запустить поиск соседей ACP для построения плоскости ACP, как описано ниже.

6.1. Требования к использованию TLS

Ниже приведены требования к TLS при использовании протокола компонентами ACP. Такие компоненты включают поддержку сертификатов ACP через EST (6.2.5. Поддержка сертификата и привязки доверия), соединения TLS для точек распространения CRL (CRL Distribution Point или CRLDP) или ответчиков OCSP (Online Certificate Status Protocol) (6.2.3. Проверка принадлежности к домену ACP) и ACP GRASP (6.9.2. ACP как защищённая транспортная подложка для GRASP). На узлах ANI эти требования относятся и к BRSKI.

Протокол TLS должен соответствовать документу Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS) [RFC7525], требуется поддержка TLS 1.2 (The Transport Layer Security (TLS) Protocol Version 1.2 [RFC5246]), а применять более старые версии TLS недопустимо. Следует поддерживать TLS 1.3 (The Transport Layer Security (TLS) Protocol Version 1.3 [RFC8446]). Выбор TLS 1.2 в качестве наименьшей версии для ACP основан на ожидаемой в настоящее время и весьма вероятной доступности для широкого класса узлов ACP, у которых может не быть гибкого стека TCP/IP.

В TLS должны поддерживаться алгоритмы TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 и TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 и недопустимо предлагать симметричное шифрование или хэширование с ключами короче 384 битов. При поддержке TLS 1.3 должен предлагаться TLS_AES_256_GCM_SHA384 и можно предлагать TLS_CHACHA20_POLY1305_SHA256.

В TLS должно включаться расширение Supported Elliptic Curves, которое должно поддерживать кривые NIST P-256 (secp256r1(22)) и P-384 (secp384r1(24)) из документа Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS) Versions 1.2 and Earlier [RFC8422]. Кроме того, клиентам TLS 1.2 следует передавать расширение ec_point_format с единственным элементом uncompressed.

6.2. Домен, сертификат и сеть ACP

ACP полагается на групповую безопасность. Домен ACP — это группа узлов, доверяющих друг другу в операциях ACP, таких как создание защищённых каналов «точка-точка» между членами домена ACP по протоколам IPsec и т. п. Для аутентификации и предоставления полномочий другому узлу ACP с доступом в домен ACP каждому члену ACP нужен ключевой материал — узел ACP должен иметь сертификат LDevID и сведения об 1 или нескольких привязках доверия (TA), требуемые для проверки принадлежности к домену ACP (6.2.3. Проверка принадлежности к домену ACP).

Задание ключей вручную через общие секреты не подходит для домена ACP, поскольку требует иметь один общий секрет для всех имеющихся и будущих членов домена ACP, чтобы соответствовать ожиданиям автономной организации партнерских (peer-to-peer) защищённых каналов между любыми членами домена ACP. Такой общий секрет привёл бы к слабости защиты. Асимметричный ключевой материал (открытые ключи) без сертификатов не обеспечивает механизма аутентификации принадлежности к домену ACP в автономной партнерской манере для имеющихся и будущих членов домена ACP.

Сертификат LDevID далее называется сертификатом ACP. TA — это сертификат корневого CA в домене ACP domain.

ACP не требует конкретных механизмов предоставления ключевого материала узлу ACP. Требуется лишь соответствие параграфу 6.2.1. Сертификаты ACP, в частности, наличие acp-node-name, указанного в параграфе 6.2.2. AcpNodeName в сертификате ACP, в сертификате домена, а также в сертификатах кандидатов в партнёры ACP. Варианты зачисления и предоставления рассмотрены в приложении A.2. Начальная загрузка BRSKI (ANI).

В этом документе термин ACP часто применяется в тех местах, где документы по автономным сетям [RFC7575] и [RFC8993] применяют слово «автономный» (autonomic). Причина заключается в том, что упомянутые документы рассматривают лишь полностью автономные сети и узлы, но поддержка ACP не требует других компонентов автономной сети за исключением зависимости от GRASP и обеспечения защиты и транспорта для GRASP. Поэтому слово «автономный» могло бы создать путаницу для операторов, заинтересованных лишь в ACP.

В [RFC7575] автономный домен (autonomic domain) определён как набор автономных узлов. Узлам ACP не требуется быть полностью автономными, но когда это так, домен ACP является автономным доменом. В [RFC8993] сертификат домена (domain certificate) определён как сертификат, применяемый в автономном домене. Сертификат ACP является таким сертификатом домена, когда узлы ACP являются (полностью) автономными узлами. Сетью ACP в этом документе называется сеть, созданная активными узлами ACP в домене ACP. Сеть ACP может включать не только узлы ACP, как указано в параграфе 8.1. ACP Connect.

6.2.1. Сертификаты ACP

Сертификаты ACP должны быть совместимыми с [RFC5280] сертификатами X.509 v3 [X.509].

Узлы ACP должны поддерживать обработку сертификатов ACP, TA и сертификатов цепочек сертификации (далее сертификаты) с открытыми ключами RSA и эллиптических кривых (Elliptic Curve Cryptography или ECC).

Узлам ACP недопустимо поддерживать сертификаты с открытыми ключами RSA с модулем короче 2048 битов или групп с порядком менее 256 битов. Они должны поддерживать сертификаты с открытым ключом RSA с модулем 2048 битов и могут поддерживать более длинные ключи RSA. Должны поддерживаться сертификаты с открытым ключом ECC, использующие кривые NIST P-256, и следует поддерживать кривые P-384 и P-521.

Узлам ACP недопустимо поддерживать сертификаты с открытыми ключами RSA с модулем короче 2048 битов или ECC из групп с порядком менее 256 битов. Должны поддерживаться сертификаты подписей RSA с открытым ключом 2048 битов и могут поддерживаться такие сертификаты с более длинным ключом. Должны поддерживаться сертификаты ECDSA, использующие кривые NIST P-256, и следует поддерживать кривые P-384 и P-521.

Узлы ACP должны поддерживать сертификаты RSA с подписями RSA и дайджестом содержимого SHA-256, а также следует поддерживать дайджесты SHA-384 и SHA-512 в таких подписях. Такие же требования применимы к подписям сертификатов ECDSA (Elliptic Curve Digital Signature Algorithm) и дополнительно узлы ACP должны поддерживать подписи ECDSA в сертификатах ECDSA.

В сертификатах ACP следует применять ключ и подпись RSA, когда такой сертификат предназначен для использования лишь при аутентификации ACP. Сертификат ACP может использовать ключ ECC и подпись ECDSA, если этот сертификат предназначен лишь для аутентификации и проверки полномочий в ACP и ANI.

Все протоколы защиты каналов, применяемые для ACP в соответствии с этим документом или его расширениями, должны поддерживать аутентификацию (например, подпись), начиная с этих типов сертификатов. Дополнительные сведения приведены в [RFC8422].

Выбор алгоритмов обусловлен тем, что в 2020 г. RSA применялся все еще чаще ECC, поэтому для RSA указан уровень должен. ECC обеспечивает эквивалентную защиту с более коротким (логарифмически) ключом (см. [RFC8422]). Это может давать преимущества, особенно при ограниченной пропускной способности или наличии узлов с ограничениями в сети ACP/ANI. Некоторые функции ACP, такие как партнерские отношения GRASP через ACP, требуют сквозной аутентификации каждого с каждым, поэтому ECC можно надёжно применять в ACP лишь в тех случаях, когда его должны поддерживать все узлы ACP. Подписи RSA должны поддерживаться и для сертификатов ECC, поскольку сами CA могут ещё не поддерживать ECC.

Сертификат ACP следует применять при каждой аутентификации между узлами с сертификатами ACP (узлы ACP и NOC), где полномочия предоставляются лишь членам домена ACP, например, сквозная защита между узлом ACP и NOC/OAM, а также между ASA и ASA. Проверка принадлежности к домену описана в параграфе 6.2.3. Использование этой проверки стандартизовано здесь для создания защищённых поэтапных каналов ACP (6.8. Протоколы защищённых связей (каналов)) и для ACP GRASP (6.9.2. ACP как защищённая транспортная подложка для GRASP) через TLS.

Для проверки принадлежности к домену ACP требуется минимальное числ0 элементов в сертификате, как описано в параграфе 6.2.3. Отождествление узла в ACP передаётся в поле acp-node-name, как указано в параграфе 6.2.2.

Для применения алгоритма Диффи-Хеллмана на эллиптических кривых (Elliptic Curve Diffie-Hellman или ECDH) напрямую с ключом в сертификате ACP сертификаты с ключами ECC должны указывать поддержку ECDH, если присутствует расширение X.509 v3 keyUsage, должен быть установлен бит keyAgreement. Отметим, что эта опция не требуется ни для одного из требуемых этим документом шифров и может не поддерживаться некоторыми CA.

Остальные поля сертификата ACP заполняются в соответствии с [RFC5280]. Коль скоро они соответствуют [RFC5280], любое иные поля сертификата ACP можно установить по желанию оператора домена ACP через подходящего регистратора ACP и/или процедуры ACP CA. Например, другие поля могут потребоваться для целей, отличающихся от предусмотренных для сертификата ACP (скажем, элементы SubjectName).

В остальном сертификаты ACP могут следовать рекомендациям [CABFORUM].

Для диагностики и рабочих задач полезно скопировать идентифицирующие устройство поля сертификата IDevID узла в сертификат ACP, например, атрибут serialNumber (параграф 6.2.9 в [X.520]) в поле субъекта кодирования отличительного имени. Отметим, что это не serial-number из сертификата (см. также параграф 2.3.1 в [RFC8995]). Это можно сделать, например, если допустимо передать serialNumber по протоколу обнаружения на канальном уровне (Link Layer Discovery Protocol или LLDP) [LLDP], поскольку, как передаваемая через LLDP информация, сведения из сертификата ACP могут извлечь соседние узлы без дальнейшей аутентификации и применить их как для полезной диагностики, так и для вредоносных атак. Извлечение сертификата ACP возможно с помощью (неудачной) попытки создать защищённый канал ACP, а serialNumber обычно содержит сведения о типе устройства, которые могут способствовать более быстрому обнаружения действующих эксплойтов или атак на устройство.

Отметим, что здесь нет намерения ограничить проверку полномочий в ACP или автономных сетях, использующих ACP, просто проверкой принадлежности к домену ACP, заданной в этом документе. Проверка может быть расширена или изменена дополнительными требованиями. Такие проверки полномочий могут в будущем использовать и требовать наличия дополнительных элементов в сертификатах или правилах, а также дополнительных сертификатов. Дополнительная проверка атрибута использования расширенного ключа id-kp-cmcRA рассмотрена в параграфе 6.2.5. Поддержка сертификата и привязки доверия, а также в Certificate Management over CMS (CMC) Updates [RFC6402] и приложении A.9.5. Назначение роли.

6.2.2. AcpNodeName в сертификате ACP

     acp-node-name = local-part "@" acp-domain-name
     local-part = [ acp-address ] [ "+" rsub extensions ]
     acp-address = 32HEXDIG / "0" ; HEXDIG из Приложения B.1 к [RFC5234]
     rsub = [ <subdomain> ] ; <subdomain> из параграфа 3.5 в [RFC1034]
     acp-domain-name = <domain> ; из параграфа 3.5 в [RFC1034]
     extensions = *( "+" extension )
     extension  = 1*etext  ; определение будущего стандарта.
     etext      = ALPHA / DIGIT /  ; Printable US-ASCII
                  "!" / "#" / "$" / "%" / "&" / "'" /
                  "*" / "-" / "/" / "=" / "?" / "^" /
                  "_" / "`" / "{" / "|" / "}" / "~"

     routing-subdomain = [ rsub "." ] acp-domain-name

Рисунок 2. ACP Node Name ABNF.

Например, адрес ACP fd89:b714:f3db:0:200:0:6400:0000, домен ACP с именем acp.example.com и расширение rsub area51.research дают в результате

     acp-node-name      = fd89b714f3db00000200000064000000
                          +area51.research@acp.example.com
     acp-domain-name    = acp.example.com
     routing-subdomain  = area51.research.acp.example.com

Поле acp-node-name на рисунке 2 — это определение ABNF (Augmented BNF for Syntax Specifications: ABNF [RFC5234]) для ACP Node Name. Сертификат ACP должен содержать эту информацию. Он должен включать поле otherName в расширение X.509 Subject Alternative Name, а в otherName должно содержаться AcpNodeName, как указано в параграфе 6.2.2.1. Модуль ASN.1 AcpNodeName .

Соответствующие этой спецификации узлы должны быть способны получить свой адрес ACP через сертификат домена и в этом случае их собственный сертификат ACP должен иметь поле 32HEXDIG acp-address. Регистр символов в поле acp-address значения не важен, поскольку поле имеет тип ABNF HEXDIG. Рекомендуется использовать в поле acp-address строчные буквы. Соответствующие этой спецификации узлы должны быть способны аутентифицировать узлы как членов домена ACP или партнёров по защищённому каналу ACP, когда они имеют поле acp-address=0, и как членов домена ACP (не не партнёров по защищённому каналу ACP), когда поле acp-address отсутствует в AcpNodeName (см. 6.2.3. Проверка принадлежности к домену ACP).

Поле acp-domain-name служит для указания домена ACP, через который узлы ACP проверяют подлинность и полномочия друг друга, например, для создания защищённых каналов ACP между собой (6.2.3. Проверка принадлежности к домену ACP). В acp-domain-name следует указывать FQDN домена Internet, принадлежащего сетевой администрации ACP и в идеале зарезервированного для ACP. В этой спецификации оно служит именем для ACP, которое в идеале является уникально глобальным. Когда имя acp-domain-name уникально в глобальном масштабе, конфликты адресов ACP в разных доменах ACP возможны лишь в результате конфликтов хэш-значений ULA (6.11.2. Базовая схема адресации ACP). Используя разные acp-domain-name, операторы могут различать ACP даже при совпадении TA.

Для сохранения простоты кодирования другие языки для acp-domain-name не рассматриваются. Значение acp-node-name не предназначено для конечных пользователей. Не предусмотрено защиты от выбора оператором любого доменного имени для ACP, даже если тот не владеет доменом. Имя домена служит лишь в качестве хэш-затравки для ULA и операторской диагностики. Поэтому оператору, у которого есть домен лишь на отличном от английского языке (internationalized), следует иметь возможность выбора любой уникальной строки 7-битовых символов ASCII для представления в acp-domain-name доменного имени на другом языке.

Строку routing-subdomain можно создать из acp-node-name и применять для создания хэша ULA (6.11.2. Базовая схема адресации ACP). Наличие rsub позволяет реализовать в одном домене ACP несколько префиксов ULA /48 (см. примеры в A.6. CA, домены и маршрутные субдомены).

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

Ниже указаны и обоснованы принятые варианты кодирования.

  1. Формат.

    1. Требуется включить rsub в local-part. Если в формат включено лишь поле routing-subdomain как доменная часть acp-node-name, rsub и acp-domain-name нельзя отделить друг от друга при определении в процессе проверки принадлежности к домену ACP, какая часть является acp-domain-name, а какая служит лишь для создания отличающегося префикса ULA.

    2. Если acp-address и rsub отсутствуют в AcpNodeName, local-part будет иметь формат «++extension(s)». Два символа + требуются для того, чтобы узел мог однозначно увидеть отсутствие acp-address и rsub.

  2. Причины выбора описанного здесь кодирования доменного имени и адреса ACP.

    1. Поле acp-node-name служит идентификатором ACP для узла. Оно включает компоненты, требуемые для идентификации ACP узла как изнутри, так и извне ACP.

    2. Для ручной и автоматизированной диагностики, а также управления устроствами и ACP требуется иметь понятное человеку и пригодное для машинного разбора стандартное представление acp-node-name в одну строку. Например, системы инвентаризации и другие backend-системы всегда идентифицируют элемент по уникальной строке, а не по комбинации нескольких полей, которая потребовалась бы в ином случае.

    3. Если кодирование отличалось бы от такой строки, пришлось бы задать другое стандартное кодирование, чтобы представить этот формат (стандартное кодирование в строку) для применения операторам.

    4. Адреса вида <local>@<domain> стали предпочтительным форматом для идентификаторов элементов во многих системах, включая большинство идентификаторов в web и мобильных приложениях, таких как многодоменные системы с единым входом.

  3. Совместимость.

    1. Следует обеспечить возможность применения сертификата ACP в качестве сертификата LDevID в системах, используемых помимо ACP. Поэтому информационные элементы, требуемые для ACP, следует кодировать так, чтобы минимизировать возможность несовместимости с другими приложениями. Например, атрибуты поля субъекта часть используются отличными от ACP приложениями, поэтому их не следует занимать новыми значениями ACP.

    2. Элементам не следует требовать дополнительного кодирования и/или декодирования ASN.1, поскольку библиотеки для доступа к сведениям из сертификатов, особенно во встраиваемых устройствах, могут не поддерживать расширенное декодирование ASN.1 сверх предопределённых обязательных полей. Поля subjectAltName и otherName уже используются с одним строковым параметром для нескольких otherName (см. Extensible Messaging and Presence Protocol (XMPP): Core» [RFC6120], «Dynamic Peer Discovery for RADIUS/TLS and RADIUS/DTLS Based on the Network Access Identifier (NAI) [RFC7585], Internet X.509 Public Key Infrastructure Subject Alternative Name for Expression of Service Name [RFC4985], Internationalized Email Addresses in X.509 Certificates [RFC8398]).

    3. Элементам, требуемым для ACP, следует минимизировать риск ошибочной интерпретации при ином применении сертификатов LDevID. Их недопустимо трактовать как адреса электронной почты, поэтому применение опций otherName и rfc822Name в сертификатах будет неуместным.

Подробное описание поля subjectAltName приведено в параграфе 4.2.1.6 [RFC5280].

6.2.2.1. Модуль ASN.1 AcpNodeName

Приведённый ниже модуль ASN.1 нормативно задаёт структуру AcpNodeName. Эта спецификация использует определения ASN.1 из документа New ASN.1 Modules for the Public Key Infrastructure Using X.509 (PKIX) [RFC5912] с нотацией 2002 ASN.1. В [RFC5912] обновлены нормативные документы, использовавшие старую нотацию ASN.1.

   ANIMA-ACP-2020
     { iso(1) identified-organization(3) dod(6)
       internet(1) security(5) mechanisms(5) pkix(7) id-mod(0)
       id-mod-anima-acpnodename-2020(97) }

   DEFINITIONS IMPLICIT TAGS ::=
   BEGIN

   IMPORTS
     OTHER-NAME
     FROM PKIX1Implicit-2009
       { iso(1) identified-organization(3) dod(6) internet(1)
         security(5) mechanisms(5) pkix(7) id-mod(0)
         id-mod-pkix1-implicit-02(59) }

     id-pkix
     FROM PKIX1Explicit-2009
       { iso(1) identified-organization(3) dod(6) internet(1)
         security(5) mechanisms(5) pkix(7) id-mod(0)
         id-mod-pkix1-explicit-02(51) } ;

     id-on OBJECT IDENTIFIER ::= { id-pkix 8 }

     AcpNodeNameOtherNames OTHER-NAME ::= { on-AcpNodeName, ... }

     on-AcpNodeName OTHER-NAME ::= {
         AcpNodeName IDENTIFIED BY id-on-AcpNodeName
     }

     id-on-AcpNodeName OBJECT IDENTIFIER ::= { id-on 10 }

     AcpNodeName ::= IA5String (SIZE (1..MAX))
      -- AcpNodeName в соответствии с этим документом передаёт 
      -- поле acp-node-name, заданное ABNF в параграфе 6.2.2

   END

Рисунок 3. Модуль ASN.1 AcpNodeName.

6.2.3. Проверка принадлежности к домену ACP

Ниже указаны этапы проверки принадлежности к домену ACP на основании сертификата кандидата в партнёры.

  1. Проверяется владение партнёром секретным ключом, соответствующим открытому ключу в сертификате. Эта проверка выполняется с помощью применяемого протокола защищённых связей, например, как описано в параграфе 2.15 Internet Key Exchange Protocol Version 2 (IKEv2) [RFC7296].

  2. Проверяется путь для сертификата партнёра в соответствии с разделом 6 в [RFC5280] по отношению к одной из привязок доверия (TA), связанных с сертификатом ACP узла ACP (6.2.4. Привязки доверия). Это включает проверку срока действия сертификатов в пути.

  3. Если в сертификате партнёра указан ответчик CRLDP ([RFC5280], параграф 4.2.1.13) или OCSP ([RFC5280], параграф 4.2.2.1), сертификат партнёра должен быть действительным в соответствии с этими механизмами, когда они доступны. Проверка OCSP для сертификата партнёра через ACP должна быть успешной, этот партнёр должен отсутствовать в списке CRL, полученном от CRLDP. Эти механизмы недоступны, когда узел ACP не имеет связности (ACP или иной) для получения текущего списка CRL, не имеет доступа к ответчику OCSP, а протокол защищённой связи также не может передать CRL и проверить OCSP.

    Повторные попытки узнать об отзыве через OCSP или CRL следует предпринимать с использованием отсрочки, как описано в 6.7. Проверка кандидата в соседи ACP. Когда узел ACP узнает о недействительности партнерского сертификата ACP, для которого проверка 3 была пропущена в процессе создания защищённого канала ACP, защищённый канал ACP к этому партнёру должен быть закрыт, даже если он является единственным соединением для доступа CRL/OCSP. Это относится ко всем защищённым каналам ACP к данному партнёры, если их больше 1. Соединение по защищённому каналу ACP должно повторяться периодически на случай обретения соседом нового, действительного сертификата.

  4. Проверяется синтаксическая корректность поля acp-node-name в сертификате партнёра и совпадение acp-domain-name в acp-node-name из этого сертификата со значением в сертификате данного узла ACP (с приведением символов к нижнему регистру).

При организации защищённого канала ACP выполняется ещё одна проверка сертификата кандидата в партнёры.

  1. Поле acp-address присутствует в AcpNodeName сертификата и имеет форму 32HEXDIG или 0 (Рисунок 2).

Технически защищённые каналы ACP можно организовать лишь с узлами, имеющими acp-address. Правило 5 гарантирует учёт этого при проверке принадлежности к домену ACP.

Узлы без поля acp-address могут использовать свой сертификат домена ACP лишь для аутентификации защищённого канала без ACP. Это включает, например, узлы NMS, которым разрешено взаимодействовать с ACP через ACP connect (параграф 8.1)

Особый случая значения 0 в поле acp-address сертификата ACP предназначен для узлов, которые могут и должны определять свой адрес ACP с помощью механизма, отличающегося от получения из поля acp-address в сертификате ACP. Таким узлам ACP разрешена организация защищённых каналов ACP. Механизмы определения адреса ACP такими узлами выходят за рамки этой спецификации, но такая возможность включена, чтобы любой узел ACP мог создать защищённые каналы ACP в соответствии с правилом 5.

Необязательное поле rsub в AcpNodeName не связано с проверкой принадлежности к домену ACP, поскольку оно служит лишь для структурирования маршрутизации и адресации внутри ACP, а не ручной взаимной проверки подлинности и полномочий (отсюдя название субдомен маршрутизации — routing subdomain).

  • Этапы 1 — 4 представляют собой стандартную проверку сертификата и аутентификацию секретного ключа в соответствии с [RFC5280], а также протоколов защищённой связи (таких как IKEv2 [RFC7296]) при использовании сертификатов.

  • За исключением открытого ключа, этапы 1 — 4 не проверяют какие-либо заданные заранее элементы отождествления сертификата, такие как префикс доменного имени web-сервера, который часто кодируется в общем имени сертификата. Этап 5 является эквивалентом для AcpNodeName.

  • На этапе 4 выполняются стандартные проверки CRL и OCSP, усовершенствованные для случая отсутствия связности и ограниченной функциональности протоколов защищенной связи.

  • Этапы 1 — 4 разрешают создание любых защищённых соединений между членами одного домена ACP за исключением защищённых каналов ACP.

  • Этап 5 включает дополнительную проверку наличия адреса ACP, требуемого для защищённого канала ACP.

  • Таким образом, этапы 1 — 5 разрешают создание защищённого канала ACP.

Для краткости в оставшейся части документа этот процесс указывается лишь как аутентификация без упоминания проверки полномочий.

6.2.3.1. Проверка часов и времени

Узел ACP с часами (realtime), в которых он уверен, должен проверять временные метки при проверке принадлежности к домену ACP, например, проверять срок действия сертификата на этапе 1 и соответствующее время на этапе 4 для сведений об отзыве (например, signingTimes в подписях Cryptographic Message Syntax (CMS)).

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

Узнать текущее время незащищённым способом можно, например, по протоколу NTP (Network Time Protocol Version 4: Protocol and Algorithms Specification [RFC5905]) через тот же адрес IPv6 link-local, который используется для ACP с соседними узлами ACP. Узлам ACP, предоставляющим NTP без защиты по своим адресам link-local, следует сначала запустить NTP через ACP и получать время NTP через ACP только из доверенных источников. Детали таких процедур NTP выходят за рамки этой спецификации.

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

6.2.4. Привязки доверия

Узлам ACP нужны сведения о привязках доверия (TA) в соответствии с параграфом 6.1.1 (d) в [RFC5280], обычно в форме одного или нескольких сертификатов TA для проверки пути в соответствии с правилом 2 параграфа 6.2.3. Сведения о TA должны предоставляться узлу ACP (вместе с сертификатом домена ACP) регистратором ACP при начальном зачислении узла-кандидата ACP. Узлы ACP должны также поддерживать обновление сведений о TA через EST, как описано в параграфе 6.2.5. Поддержка сертификата и привязки доверия.

Требуемые сведения о TA могут состоять из одного или нескольких сертификатов, необходимых для обновления сертификатов CA, как указано в параграфе 4.4 Internet X.509 Public Key Infrastructure Certificate Management Protocol (CMP) [RFC4210]).

Путь к сертификату — это цепочка сертификатов, начинающаяся с сертификата ACP (лист и/или конечный элемент), за которым могут следовать сертификаты CA, и заканчивающаяся данными о TA, которыми обычно служат 1 или несколько самоподписанных сертификатов TA. Удостоверяющий центра (CA), подписавший сертификат ACP, называется назначающим CA. При отсутствии промежуточных CA назначающим CA служит TA. Путь проверки сертификатов подтверждает, что TA, связанная с ACP разрешает сертификат напрямую или опосредованно через один или несколько промежуточных CA.

Отметим, что у разных узлов ACP могут быть разные промежуточные CA на пути сертификации и даже разные TA. Набор TA для домена ACP должен быть согласованным для всех членов ACP, чтобы любой узел ACP мог проверить подлинность любого другого узла ACP. Протоколы, используемые на этапах 1 — 3 при проверке принадлежности к домену ACP должны поддерживать обмен не только сертификатам узлов ACP но и промежуточными TA.

Для проверки принадлежности к домену ACP узлы ACP должны поддерживать проверку пути сертификации без промежуточных CA или с одним таким CA. Следует поддерживать 2 промежуточных CA и 2 TA (для смены TA).

Сертификаты для ACP должны выдаваться лишь узлам, которым разрешено входить в домен ACP. Когда подписывающий CA полагается на регистратора ACP, он должен подписывать только сертификаты с acp-node-name от доверенных регистраторов ACP. При этом может применяться любой имеющийся CA, не знающий формата acp-node-name.

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

Один владелец может управлять несколькими независимыми доменами ACP с одним набором TA. При этом регистраторы должны знать, в какой плоскости ACP нужно регистрировать узел.

6.2.5. Поддержка сертификата и привязки доверия

Узлы ACP должны поддерживать обновление своего сертификата и данных о TA через EST и могут поддерживать иные механизмы. Требования для TLS указаны в параграфе 6.1. Требования к использованию TLS. Сеть ACP должна иметь хотя бы 1 узел ACP с функциональностью сервера EST, чтобы можео было использовать обновление по EST.

Узлу ACP следует помнить параметры GRASP O_IPv6_LOCATOR сервера EST, на котором он последний раз обновлял свой сертификат ACP. Следует обеспечивать возможность установки этих параметров сервера EST регистратором ACP (6.11.7. Регистраторы ACP), который исходно зачислил устройство ACP с его сертификатом ACP. При использовании BRSKI (см. [RFC8995]) локатор IPv6 для регистратора BRSKI из соединения BRSKI TLS следует запоминать и применять при следующем обновлении через EST, если этот регистратор также объявляет себя сервером EST через GRASP на своём адресе ACP (6.2.5.1. Цель GRASP для сервера EST).

Сервер EST должен представить сертификат, прошедший проверку членства в домене ACP, при организации соединения TLS (правила 1 — 4 из параграфа 6.2.3, но без правила 5, поскольку это не создание защищённого канала ACP). Сертификат сервера EST должен также включать атрибут расширенного использования ключа id-kp-cmcRA [RFC6402], а клиент EST должен проверять его наличие.

Дополнительная проверка поля расширенного применения ключа id-kp-cmcRA гарантирует, что клиенты не станут жертвами подставного сервера EST. Хотя таким незаконным серверам EST не следует иметь возможность поддержки запросов на подпись сертификата (они не могут получит ответ на подпись от действительного CA), они могут представить поддельный сертификат CA клиентам EST, которым нужно обновить просроченные сертификаты CA.

Отметим, что серверам EST, поддерживающим несколько доменов ACP, потребуется отдельный сертификат для каждого домена ACP и нужно отвечать по разным транспортным адресам (IPv6 и/или порт TCP). Это легко автоматизировать на сервере EST, если CA позволяет регистраторам запрашивать для себя сертификаты с расширенным использованием ключа id-kp-cmcRA.

6.2.5.1. Цель GRASP для сервера EST

Узлы ACP, являющиеся серверами EST, должны анонсировать свои услуги в ACP сообщениями GRASP Flood Synchronization (M_FLOOD). Определение этих сообщений дано в параграфе 2.8.11 [RFC8990], а на рисунке 4 представлен пример.

      [M_FLOOD, 12340815, h'fd89b714f3db0000200000064000001', 210000,
          [["SRV.est", 4, 255 ],
          [O_IPv6_LOCATOR,
               h'fd89b714f3db0000200000064000001', IPPROTO_TCP, 443]]
      ]

Рисунок 4. Пример цели GRASP SRV.est.

Формат определения цели в CDDL (см. Concise Data Definition Language (CDDL): A Notational Convention to Express Concise Binary Object Representation (CBOR) and JSON Data Structures [RFC8610]) приведён на рисунке 5.

   flood-message = [M_FLOOD, session-id, initiator, ttl,
                    +[objective, (locator-option / [])]]
                                ; См. пример выше о объяснения ниже
                                ; для initiator и ttl.

   objective = ["SRV.est", objective-flags, loop-count,
                                          objective-value]

   objective-flags = sync-only  ; Как в [RFC8990].
   sync-only       = 4          ; M_FLOOD требует лишь синхронизации.
   loop-count      = 255        ; Рекомендуется при отсутствии механизма
                                ; определения диаметра сети.
   objective-value = any        ; Резерв для будущих расширений.

Рисунок 5. Определение GRASP SRV.est.

Имя SRV.est указывает, что целью служит сервер EST, соответствующий [RFC7030], поскольку est — зарегистрированное имя службы (Internet Assigned Numbers Authority (IANA) Procedures for the Management of the Service Name and Transport Protocol Port Number Registry [RFC6335]) для [RFC7030]. Поле objective-value при его наличии должно игнорироваться. Совместимое с прежними версиями расширение [RFC7030] можно указать в objective-value. Опции обновления сертификата, не совместимые с [RFC7030], должны использовать другие objective-name. Нераспознанные поля objective-value (или их части при непонятной структуре) должны игнорироваться.

Сообщения M_FLOOD должны передаваться периодически. По умолчанию следует использовать интервал 60 секунд, оператору следует иметь возможность изменения периода, но не следует делать его меньше 60 секунд. Частота передачи должна быть такой, чтобы общее число периодических M_FLOOD от всех источников не вызывало значительного трафика в ACP. Для параметра ttl следует устанавливать значение в 3,5 раза больше периода, чтобы можно было отбросить до 3 последовательных сообщений, прежде чем анонс будет сочтён просроченным. В приведённом выше примере установлено ttl = 210000 мсек, т. е. 3,5 + 60 секунд. Когда анонсировавший эти параметры неожиданно «умирает» сразу после отправки M_FLOOD, получатели особзнают это через 210 секунд. Если получатель попытается подключиться к неработающей службе до истечения этого интервала, он столкнётся с отказом, который послужит индикацией недоступности экземпляра сервиса, и выберет иной экземпляр (из другого анонса GRASP).

Цели SRV.est следует анонсировать лишь в случаях, когда узел ACP знает, что он может связаться с CA для обновления EST и/или смены ключей в домене ACP (см. 11. Вопросы безопасности).

6.2.5.2. Обновление

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

Обновление сертификатов следует запускать по истечении 50% срока действия сертификата домена, чтобы у сетевых операций было достаточно времени для поиска и устранения проблем, препятствующих своевременному обновлению сертификата домена, а также для обеспечения продолжения работы частей сети, из которых недоступны CA.

6.2.5.3. Списки отзыва сертификатов (CRL)

Узлу ACP следует поддерживать отзыв сертификата через списки CRL (Certificate Revocation List) по протоколу HTTP с одной или несколькими точками распространения CRL (CRL Distribution Point или CRLDP). CRLDP должны указываться в сертификате домена. Если CRLDP URL использует адрес IPv6 (адрес ULA при использовании заданных в этом документе правил), узел ACP будет соединяться с CRLDP через ACP. Если CRLDP использует доменное имя, узел ACP будет связываться с CRLDP через плоскость данных.

Обычно для CRLDP применяются доменные имена, но для ACP не задана поддержка DNS. Поиск в DNS через плоскость данных не только может вызывать проблемы безопасности, но и не указывает, предназначен ли распознанный адрес для доступа через ACP. Поэтому применение адреса IPv6 вместо имени DNS эффективней, поскольку указывает доступность CRLDP через ACP.

Доступ к CRLDP через ACP можно обеспечить, разместив службы на узле с ACP или подключившись к узлу через интерфейс ACP connect (см. параграф 8.1).

При использовании частной инфраструктуры PKI для сертификатов ACP может потребоваться знать CRL, например, для запрета анализа операционной практики домена путём отслеживания роста CRL. В этом случае можно выбрать HTTPS для защиты конфиденциальности, особенно при доступности CRL в плоскости данных. Для проверки подлинности и полномочий следует использовать сертификаты ACP и проверку принадлежности к домену ACP (параграф 6.2.3). CRLDP может пропускать проверку CRL при аутентификации партнёра, чтобы разрешить извлечение CRL узлам ACP с отозванным сертификатом ACP, что может помочь (бывшему) узлу ACP быстрее узнать об отзыве своего сертификата. Однако это может нарушать требование знать списки (need-to-know). Узлы ACP могут поддерживать операции CRLDP по протоколу HTTPS.

6.2.5.4. Срок действия

Срок действия сертификата может быть короче обычного (1 год), поскольку обновление сертификатов полностью автоматизировано через ACP и EST. Основным фактором, сдерживающим сокращение срока действия, является нагрузка на серверы EST и CA. Поэтому рекомендуется поддерживать сертификаты ACP через цепочку CA, где производительности назначающего CA достаточно для управления краткосрочными сертификатами. Пример реализации этого приведён в параграфе 9.2.4. Регистраторы ACP с суб-CA. См. также Support for Short-Term, Automatically Renewed (STAR) Certificates in the Automated Certificate Management Environment (ACME) [RFC8739].

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

В Приложении A.2 рассмотрена оптимизация поддержки сертификатов при использовании BRSKI [RFC8995].

6.2.5.5. Повторное зачисление

Узел ACP может определить, что срок действия его сертификата ACP закончился, после продолжительного выключения или отсоединения. В этом случае узел ACP следует заново зачислить в роли кандидата ACP. В этой роли узел поддерживает TA и цепочку сертификатов, связанные с сертификатом ACP, исключительно для повторного зачисления и пытается (или ждёт) повторного зачисления с новым сертификатом ACP. Детали этого зависят от механизмов и протоколов, применяемых регистраторами ACP. Использование регистраторов и ваучеров в разъяснено в параграфе 6.11.7. Регистраторы ACP и [RFC8995]. Когда предполагается использование ACP без BRSKI, приведённые ниже сведения о BRSKI и ваучерах можно опустить.

При использовании BRSKI (т. е. на узлах ACP, являющихся узлами ANI) повторно зачисляемый узел-кандидат в ACP пытается регистрироваться как кандидат в узлы ACP (поручительство BRSKI), но вместо применения сертификата IDevID узла ACP ему следует сначала попытаться использовать свой сертификат домена ACP в аутентификации BRSKI TLS. Регистратор BRSKI может принять этот сертификат после завершения его срока исключительно для повторного зачисления. Использование сертификата домена ACP узлом позволяет регистратору BRSKI узнать acp-node-name узла, чтобы назначить те же адресные данные ACP этому узлу в новом сертификате ACP.

Если регистратор BRSKI отвергает применение старого сертификата ACP повторное зачисление узла-кандидата ACP должно предпринять попытку регистрации с использованием сертификата IDevID, как задано в BRSKI, при создании соединения TLS.

При попытке соединения BRSKI со старым сертификатом ACP или сертификатом IDevID кандидату на повторное зачисление в ACP следует аутентифицировать регистратора BRSKI в процессе организации соединения TLS на основе имеющихся сведений о цепочке сертификатов TA, связанных со старым сертификатом ACP. Кандидату на повторное зачисление в ACP следует возвращаться к запросу ваучера у регистратора BRSKI лишь при отказе аутентификации в процессе организации соединения TLS. В качестве меры против атак с попыткой заставить узел ACP забыть прежний (просроченный) сертификат и TA узлу ACP следует чередовать попытки повторного зачисления с использованием старого ключевого материала, сертификата IDevID и запроса ваучера.

При использовании отличных от BRSKI механизмов повторного зачисления сертификата ACP принципы остаются теми же. Кандидат на повторное зачисление в ACP пытается аутентифицировать любые партнерские узлы регистратора ACP, используя протоколы повторного зачисления и/или механизмы с имеющейся цепочкой сертификатов и/или сведениями TA, и предоставляет имеющийся сертификат ACP и другие отождествления (такие как сертификат IDevID), требуемые регистратором.

Сохранение имеющихся сведений о TA особенно важно при использовании механизмов повторного зачисления без аутентификации регистратора ACP (таких как ваучер в BRSKI) и внедрение отказов для сертификата может сделать плоскость ACP уязвимой для удалённых атак с возвратом узла ACP в состояние «утенка» (duckling). Где он принимает повторное зачисление в любой сети, к которой подключается. Поэтому следует поддерживать (просроченный) сертификат ACP и ACP TA и пытаться использовать их как возможное свидетельство для повторного зачисления, пока не получен новый ключевой материал.

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

6.2.5.6. Сертификаты с отказом

Сертификат ACP считается отказавшим, если узел ACP, для которого выпущен сертификат, может определить, что сертификат отозван (или явно не обновлён) или (без явной локальной диагностики) узел ACP не может связаться с другими узлами того же домена ACP, используя этот сертификат ACP. Чтобы определённо связать отказ в соединении с сертификатом ACP, следует проверить принадлежность партнёра к домену (6.2.3. Проверка принадлежности к домену ACP), а диагностика соединения должна исключить другие причины отказа. Такие отказы могут возникать при создании или обновлении соединения по защищённому каналу ACP или ином применении сертификата ACP, например при соединении TLS с сервером EST для обновления сертификата домена ACP.

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

Узлам ACP следует поддерживать возможность обнаружения отказов сертификата ACP и в этом случае переходить к роли кандидата на повторное зачисление в ACP, как описано в параграфе 6.2.5.5. Повторное зачисление.

6.3. Таблица смежности ACP

Чтобы знать, с какими узлами организовывать каналы ACP, каждый узел ACP поддерживает таблицу смежности. Эта таблица содержит сведения о смежных узлах ACP, включая, как минимум, Node-ID (идентификатор узла внутри ACP, см. параграфы 6.11.3 и 6.11.5), интерфейс, через который обнаружен сосед (от GRASP, как описано ниже), адрес IPv6 link-local соседа на данном интерфейсе и сертификат (включая acp-node-name). Узел ACP должен поддерживать эту таблицу смежности, которая служит для определения соседей, с которыми организовано соединение ACP.

Когда следующий узел ACP не является прямым соседом (нет канала к этому узлу), информация в таблице смежности может быть добавлена путём настройки, например, можно указать Node-ID и IP-адрес (см. 8.2. Соединение островков ACP через сети L3 без ACP (удалённые соседи).

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

6.4. Обнаружение соседей с помощью DULL GRASP

Обнаружение незапрошенных локальных каналов (Discovery Unsolicited Link-Local или DULL) GRASP — это ограниченное подмножество GRASP для работы в области незащищённых локальных соединений. Формальное определение приведено в параграфе 2.5.2 [RFC8990]. В ACP применяется 1 экземпляр DULL GRASP для каждого интерфейса L2 на узле ACP для обнаружения кандидатов в соседи ACP, смежных на канальном уровне. Если не внесено изменений правилами, как отмечено выше (п. 2 в разделе 5), естественные интерфейсы (например, физические интерфейсы на физических узлах) следует автоматически инициализировать в состояние, где возможно автоматическое обнаружения ACP, и любые естественные интерфейсы с соседями ACP могут войти в ACP, даже если они в остальном не настроены. Приём пакетов на таких ненастроенных интерфейсах должен ограничиваться так, чтобы сначала работали лишь SLAAC (IPv6 Stateless Address Autoconfiguration [RFC4862]) и DULL GRASP, а затем — только последующая организация защищённых каналов ACP, но не иной ненужный трафик (например, нет других ответчиков транспортного стека IPv6 link-local).

Отметим, что использование группового адреса IPv6 link-local (ALL_GRASP_NEIGHBORS) предполагает необходимость использовать MLDv2 (см. Multicast Listener Discovery Version 2 (MLDv2) for IPv6 [RFC3810]) для анонсирования желания получать пакеты по этому адресу. Иначе DULL GRASP может работать некорректно в присутствии коммутаторов с отслеживанием MLD (Considerations for Internet Group Management Protocol (IGMP) and Multicast Listener Discovery (MLD) Snooping Switches [RFC4541]), которые не поддерживают или не ACP или ACP не включён на них, поскольку эти коммутаторы не будут пересылать пакеты DULL GRASP. Коммутаторы, не поддерживающие отслеживание MLD, должны работать как обычные мосты L2 для групповых пакетов IPv6, чтобы протокол DULL GRASP мог работать.

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

Примечание. Если узел ACP реализует BRSKI для зачисления своего сертификата ACP (A.2. Начальная загрузка BRSKI (ANI)), приведённые выше соображения применимы и к обнаружению GRASP для BRSKI. Каждый экземпляр DULL GRASP для ACP тогда применяется для обнаружения посредников начальной загрузки по протоколу BRSKI, когда у узла нет сертификата домена. Обнаружение соседей ACP выполняется лишь при наличии у узла сертификата. Поэтому узлу никогда не требуется одновременно искать прокси начальной загрузки и соседа ACP.

Узел ACP анонсирует себя возможным партнёрам ACP с помощью цели AN_ACP. Эта цель синхронизации предназначена для лавинной рассылки по одному каналу в сообщении GRASP Flood Synchronization (M_FLOOD). В соответствии со структурой сообщения локатор с адресом IP link-local, номером протокола IP и порта будет распространяться вместе с целью лавинной рассылки. Неформальльный пример сообщения приведён на рисунке 6.

      [M_FLOOD, 12340815, h'fe80000000000000c0011001feef0000', 210000,
        [["AN_ACP", 4, 1, "IKEv2" ],
         [O_IPv6_LOCATOR,
              h'fe80000000000000c0011001feef0000', IPPROTO_UDP, 15000]]
        [["AN_ACP", 4, 1, "DTLS" ],
         [O_IPv6_LOCATOR,
              h'fe80000000000000c0011001feef0000', IPPROTO_UDP, 17000]]
      ]

Рисунок 6. Пример цели GRASP AN_ACP.

Формальное определение CDDL представлено на рисунке 7.

     flood-message = [M_FLOOD, session-id, initiator, ttl,
                      +[objective, (locator-option / [])]]

     objective = ["AN_ACP", objective-flags, loop-count,
                                            objective-value]

     objective-flags = sync-only ; как в [RFC8990]
     sync-only =  4    ; M_FLOOD требует ограничить синхронизацию
     loop-count = 1    ; операциями на локальном канале

     objective-value = method-name / [ method, *extension ]
     method = method-name / [ method-name, *method-param ]
     method-name = "IKEv2" / "DTLS" / id
     extension = any
     method-param = any
     id = text .regexp "[A-Za-z@_$]([-.]*[A-Za-z0-9@_$])*"

Рисунок 7. Определение GRASP AN_ACP.

Поле objective-flags указывает синхронизацию, loop-count имеет значение 1, поскольку это операция link-local.

В приведённом примере рекомендуемый период передачи цели составляет 60 секунд. Значение ttl = 210000 мсек указывает, что цель может кэшироваться узлами ACP даже при потере двух сообщений из трёх в процессе передачи.

Случайное значение session-id служит для предотвращения петель (отличает сообщение от его предшествующего экземпляра). В DULL это поле не имеет смысла, но указано в соответствии со спецификацией GRASP.

Отправитель должен указываться адресом IPv6 link-local на передающем интерфейсе узла ACP. Поле method-name в параметре objective-value является строкой, указывающей протокол, доступный на указанном или предполагаемом локаторе. Это протокол, поддерживаемый узлом для согласования защищённого канала. На рисунке 6 указан протокол IKEv2 для согласования защищённого канала IPsec.

Параметр method-param позволяет передавать зависящие от метода параметры. Эта спецификация не определяет method-param для IKEv2 или DTLS. Значения method-param для этих двух методов, непонятные узлу ACP должны игнорироваться им. Параметр extension позволяет задать независимые от метода параметры. Данная спецификация не задаёт расширений. Непонятные узлу ACP расширения должны игнорироваться им.

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

IKEv2 является фактическим протоколом для согласования соединений IPsec, поэтому GRASP указывает IKEv2, а не IPsec. Указание IPsec могло бы означать использование устаревшей верии IKE (v1) (The Internet Key Exchange (IKE) [RFC2409]). Для IKEv2 в IANA выделен порт 500, но на рисунке 6 кандидат в соседи ACP предлагает согласовать защищённый канал ACP через IKEv2 на порту 15000 (исключительно для демонстрации возможности указания в GRASP номера порта, не выделенного IANA). Для порта UDP в DTLS не задан принятый по умолчанию номер и порт всегда назначается узлом. Детали применения защищённых каналов DTLS приведены в параграфе 6.8.4.

При включении локатора это должен быть O_IPv6_LOCATOR и адрес IPv6 должен совпадать с адресом инициатора (это требования DULL для минимизации DoS-атак третьей стороны).

Заданные этим документом методы защиты каналов используют для objective-value значения IKEv2 и DTLS. Естественный IKEv2 и GRE-IKEv2 не различаются, поскольку согласование происходит исключительно по IKEv2. Узлу, поддерживающему более одного метода для защищённого канала, требуется лавинно рассылать несколько вариантов цели AN_ACP, чтобы каждый метод мог сопровождаться своей опцией locator-option. Для этого можно использовать 1 сообщение GRASP M_FLOOD, как показано на рисунке 6.

Основным назначением DULL GRASP является обнаружение адресов IPv6 link-local кандидатов в партнёры ACP в подсетях. Сигнализация о поддерживаемом варианте защищённого канала предназначена в основном для диагностики, но может потребоваться и для обнаружения, когда у протокола нет общеизвестного транспортного адреса, например, как в случае DTLS.

Отметим, что узел, являющийся одновременно узлом ACP и BRSKI Join Proxy может распространять цель AN_ACP и BRSKI в одном сообщении M_FLOOD, поскольку GRASP допускает в одном сообщении несколько целей. Это может быть непрактично, если операции ACP и BRSKI реализованы в разных программных модулях и/или ASA.

Результатом обнаружения является адрес IPv6 link-local у соседа, а также поддерживаемые им протоколы защищённого канала (и нестандартный порт протокола). Они сохраняются в таблице смежности ACP (6.2.3. Проверка принадлежности к домену ACP), которая затем управляет построением ACP с этим соседом.

Отметим, что в описанную цель DULL GRASP намеренно не включён сертификат ACP узла ACP, хотя это могло быть полезным для диагностики и упрощения защищённого обмена параметрами защиты в протоколах создания безопасного канала ACP (6.8. Протоколы защищённых связей (каналов)). Причина в том, что сообщения DULL GRASP передаются периодически по групповым адресам через подсети IPv6, а включение полного сертификата может приводить к фрагментации групповых пакетов IPv6 DULL GRASP из-за большого размера, что весьма нежелательно.

6.5. Выбор кандидатов в соседи ACP

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

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

6.6. Выбор канала

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

Из вариантов применения очевидно, что не все типы узлов ACP можно и нужно соединять напрямую и не каждый узел поддерживает все возможные механизмы. Например, устройства IoT с ограниченным размером кода могут поддерживать лишь DTLS, поскольку такой код уже применяется ими для сквозной защиты, а недорогие потолочные (in-ceiling) коммутаторы L2 могут поддерживать лишь MacSec (Media Access Control Security, 802.1AE [MACSEC]), поскольку это реализовано в их микросхемах. Только гибким шлюзам может потребоваться поддержка обоих этих механизмов, а может и других. Отметим, что поддержку MacSec не требует ни один из профилей ACP в этой спецификации и MacSec лишь упоминается как интересный протокол для защищённого канала. Отметим также, что модель защиты разрешает и требует проверку подлинности и полномочий в режиме «каждый с каждым» для всех узлов ACP, поскольку для защищённых каналов применяется не только поэтапная, но и сквозная аутентификация.

Для поддержки расширяемого выбора протоколов защищённых каналов без обязательного для реализации протокола (mandatory-to-implement или MTI) узел ACP должен пробовать все поддерживаемые им протоколы защищённого канала ACP, которые анонсированы кандидатом в соседи ACP через параметры GRASP AN_ACP (из называют возможными протоколами защищённого канала ACP).

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

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

  • После того как первое соединение защищённого канала ACP с конкретным адресом партнёра IPv6 пройдёт аутентификацию, оба партнёра знают сертификаты друг друга, поскольку эти сертификаты ACP применяются всеми протоколами защиты канала для взаимной аутентификации. Партнёр с большим Node-ID в AcpNodeName его сертификата ACP принимает роль решающего (Decider), а другой — роль последующего (Follower). Решающий узел выбирает применяемый для защиты канала протокол.

  • Последователь (Follower) становится пассивным и не пытается в дальнейшем инициировать соединения протокола защиты канала ACP с Decider и не считает ошибкой закрытие защитного канала решающим узлом. Decider становится активной стороной, продолжая организацию защищённого канала с последователем. Процесс завершается, когда Decider достигает «лучшего» (с его точки зрения) варианта организации защищённого канала ACP с Follower.

  • Партнёр с acp-address = 0 в своём AcpNodeName принимает роль Follower при взаимодействии с узлом, где acp-address отличен от 0 (отметим, что эта спецификация на задаёт полностью поведение при согласовании защищённого канала ACP для узлов с 0 в поле адреса ACP, задавая совместимость с такими узлами ACP).

В простом примере партнёр ACP Node 1 пытается создать соединение IPsec через IKEv2 с Node 2. Аутентификация IKEv2 завершается успешно. Node 1 имеет меньший адрес ACP и становится Follower, а Node 2 — Decider. IKEv2 может не быть предпочтительным протоколом защитного канала ACP для Node 2 (Decider) и тот продолжит попытки создания защищённого канала с более предпочтительным протоколом (например, DTLS/UDP). Если предпочтительное соединение ACP с Decider успешно, соединение IPsec закрывается. Если у Node 2 нет предпочтения перед IPsec или другие попытки соединения с Node 1 не удаются, Node 2 сохранит соединение IPsec и будет использовать его. Решающему узлу не следует передавать реальные пакеты данных через защищённый канал, пока он не решил его применять. Последователь может задержать привязку защищённого канала ACP к виртуальному интерфейсу ACP, пока не увидит первый пакет данных от Decider (но не более 5 секунд), чтобы избежать ненужной привязки защищённого канала, который будут вскоре разорван решающим узлом. Ниже последовательность этапов в примере показана более подробно и каждый этап помечен в форме [<номер>{:<соединение>}], чтобы легче было понять, к какому из двух соединений относится этап — иницированному узлом Node 1 или узлом Node 2.

[1] Node 1 передаёт сообщение GRASP AN_ACP, анонсируя себя.

[2] Node 2 передаёт сообщение GRASP AN_ACP, анонсируя себя.

[3] Node 2 получает [1] от Node 1.

[4:C1] В результате [3] Node 2 инициирует защищённый канал к Node 1 со своим предпочтительным протоколом. Соединение C1.

[5] Node 1 получает [2] от Node 2.

[6:C2] В результате [5] Node 1 инициирует защищённый канал к Node 2 со своим предпочтением. Соединение C2.

[7:C1] Node 1 и Node 2 аутентифицируют сертификаты друг друга в C1 как действительных партнёров ACP.

[8:C1] В сертификате Node 1 значение ACP Node-ID меньше, чем у Node 2, поэтому Node 1 считает себя последователем (Follower), а Node 2 — решающим (Decider) в соединении C1. Соединение C1 завершено.

[9] Node 1 не предпринимает других попыток соединения с Node 2 (Decider), известным из [2], поскольку он знает из [8:C1] о своей роли последователя.

[10:C2] Node 1 и Node 2 аутентифицируют сертификаты друг друга в соединении C2 (как в [7:C1]).

[11:C2] В сертификате Node 1 значение ACP Node-ID меньше, чем у Node 2, поэтому Node 1 считает себя последователем (Follower), а Node 2 — решающим (Decider) в соединении C2, но C2 и C1 относятся к одной паре узлов и это уже не имеет значения, поскольку роли Decider и Follower уже распределены [8:C1].

[12:C2] Node 2 (Decider) закрывает C1, Node 1 принимает это, поскольку является последователем (из [8:C1]).

[13] Node 2 (Decider) и Node 1 (Follower) начинают обмен данными через соединение C2, которое становится защищённым каналом для ACP.

Все эти согласования происходят в контексте интерфейса L2. Decider и Follower создают соединения ACP между собой на каждом интерфейсе L2 между ними. Автономному узлу недопустимо предполагать, что сосед с тем же адресом L2 или IPv6 link-local на другом интерфейсе L2 является тем же узлом. Это можно определить лишь после проверки сертификата вслед за успешной попыткой организации защищённого соединения.

Решающему узлу не следует подавлять попытки организации конкретного соединения по защищённому каналу ACP на интерфейсе L2 на основании отказа для этого типа защищённого канала ACP с партнёром с тем же сертификатом ACP через другой интерфейс L2 interface. Различаться могут не только поддерживаемые типы защищённого канала ACP на разных интерфейсах L2 одного узла ACP, но и условия ошибок для разных интерфейсов L2. Отказ от такой «оптимизации» попыток соединения может повысить отказоустойчивость при наличии ошибок.

6.7. Проверка кандидата в соседи ACP

Независимо от выбранного протокола защищённого канала подлинность кандидатов в соседи ACP требуется проверять по сертификату домена. Это означает, что любой протокол защищённого канала должен поддерживать аутентификацию по сертификатам, которая позволяет проверить принадлежность к домену ACP, как указано в параграфе 6.2.3. При отказе попытка соединения прерывается и записывается ошибка. Повторные попытки должны дросселироваться. По умолчанию рекомендуется двухкратное увеличения интервала с начальным значением (initial retransmission time или IRT) 10 секунд и максимальным (maximum retransmission time или MRT) — 640 секунд.

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

6.8. Протоколы защищённых связей (каналов)

В этом параграфе описано, как узлы ACP организуют защищённые соединения для данных с автоматически найденными или настроенными партнёрами ACP. В параграфе 6.4 описано автоматическое обнаружение соседей в подсети IPv6, а в параграфе 8.2 — настройка партнёров, которые не являются соседями в подсети IPv6.

В параграфе 6.13.5.2 описано сопоставление защищённых каналов с виртуальными интерфейсами подсети IPv6 в ACP. Простым примером является отображение каждого защищённого канала ACP на свой виртуальный интерфейс ACP «точка-точка» (6.13.5.2.1. Виртуальные интерфейсы ACP «точка-точка»). Когда в одной подсети имеется несколько партнёров ACP, это ведёт к созданию множества виртуальных интерфейсов ACP «точка-точка» в базовую сеть IPv6. Это можно оптимизировать с помощью «множественных» виртуальных интерфейсов ACP (6.13.5.2.2. Виртуальные интерфейсы ACP с множественным доступом), но сложность оптимизации может превысить преимущества.

6.8.1. Общие соображения

За счёт выбора каналов (6.6. Выбор канала) ACP может поддерживать расширяемый набор протоколов защищённой связи, не требующий поддержки одного MTI в масштабе сети. Узлам ACP необходимо реализовать протоколы, нужные лишь для взаимодействия с кандидатами в партнёры, а не со всеми узлами домена ACP. Примеры приведены в параграфе 6.8.5. Профили защищённых каналов ACP.

Уровень защиты на каждом этапе (hop) сети ACP должен быть согласованным для всей сети, чтобы не возникало «слабых звеньев», которые могут стать объектами атак. При взломе защищённого канала на одном соединении он может использоваться для передачи и/или получения пакетов всей сети ACP. Поэтому, несмотря на возможность применять разные протоколы защиты, их минимальный уровень безопасности должен быть сопоставимым.

Протоколы защищённых каналов не обязаны поддерживать произвольную связность сетевого уровня (L3) между партнёрами, но могут пользоваться тем, что стандартным вариантом для защищённых каналов ACP служит смежность L2. Поэтому зависящие от L2 механизмы могут быть приспособлены в качестве протоколов защищённых каналов.

Механизмы L2, такие как радио-технологии со строгим шифрованием или [MACSEC], могут предоставлять эквивалентное шифрование, а протокол защищённой связи ACP может требоваться лишь для проверки принадлежности к домену ACP партнёров и/или устройств и/или вывода ключа из механизма L2. Механизмы, использующие лишь такую базовую защиту L2 для автоматического обнаружения и связи с партнёрами ACP, возможны и желательны для предотвращения дублирования шифрования, но они не заданы этим документом.

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

6.8.2. Общие требования

Аутентификация партнёров в протоколе защищённой связи должна использовать сертификат ACP, как указано в параграфе 6.2.3. Поскольку автообнаружение кандидатов в партнёры ACP через GRASP (6.4. Обнаружение соседей с помощью DULL GRASP), заданное в этом документе, не применяет сертификат ACP соседа, а узлы ACP могут (ещё) не иметь другой связности с сетью для извлечения сертификата, протокол защищённой связи должен применять механизм прямой передачи сертификата, не полагаясь на указанный механизм, такой как передача для сертификата лишь хэш-значения и/или URL.

Протокол защищённой связи должен использовать Forward Secrecy (внутренне или как часть профила протокола защищённой связи).

Поскольку данные (payload) ACP от унаследованных протоколов внутри ACP и рассылаемые лавинно сведения ACP GRASP не шифруются, протоколу защищённого канала ACP нужна конфиденциальность. Симметричное шифрование данных защищённого канала должно применять схемы, считающиеся надёжными с защитой не хуже, чем при ключах размером 256 битов, такие как AES-256. Поддержка NULL-шифрования недопустима.

Протоколы защищённых связей обычно сигнализируют лишь о сертификате конечного элемента (например, сертификате ACP) и всех возможных промежуточных CA для выполнения взаимной проверки подлинности. Привязки доверия (TA) должны быть известны обеим сторонам и пользоваться доверием, поэтому их сертификаты не требуются для взаимной аутентификации. Тем не менее, для использования при организации защищённого канала ACP следует предоставлять возможность включения сертификата TA в сигнализацию для облегчения поиска неполадок (см. 9.1. Диагностика ACP и BRSKI). Включение сертификатов TA может быть неприемлемо в системах, полагающихся на модели защиты, где содержимое сертификатов TA считается конфиденциальным и приемлема лишь передача хэша содержимого. Узлам ACP следует иметь механизм выбора условий передачи сертификата TA в предположении её возможности для конкретного протокола защищённого канала.

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

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

6.8.3. ACP по протоколу IPsec

Узел ACP анонсирует свою способность поддерживать IPsec с согласованием через IKEv2 в качестве защищённого канала ACP, используя objective-value = IKEv2 в цели GRASP AN_ACP.

Применение IPsec и IKEv2 в ACP предписывает профиль с небольшим набором опций из текущих стандартов (Standards Track) применения IPsec (Cryptographic Algorithm Implementation Requirements and Usage Guidance for Encapsulating Security Payload (ESP) and Authentication Header (AH) [RFC8221]) и IKEv2 (Algorithm Implementation Requirements and Usage Guidance for the Internet Key Exchange Protocol Version 2 (IKEv2) [RFC8247]). Эти опции обеспечивают строгие свойства защиты и могут исключать устаревшие и отменённые алгоритмы, поскольку не требуется совместимость с унаследованным оборудованием для защищённых каналов ACP. Любая совместимость с устаревшими версиями расширила бы фронт атак и усложнила реализацию, не обеспечивая преимуществ.

6.8.3.1. Естественная защита IPsec

Узел ACP с естественной поддержкой IPsec должен применять IPsec в туннельном режиме с согласованием через IKEv2 и данными (payload) IPv6 (например, ESP Next Header 41). Для инкапсуляции должны применяться свой и партнерский адреса IPv6 link-local. Заданные вручную ключи недопустимы (см. 6.2. Домен, сертификат и сеть ACP). Селекторы трафика (TS) имеют вид

   TSi = (0, 0-65535, :: - FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF)
   TSr = (0, 0-65535, :: - FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF)

Туннельный режим IPsec требуется потому, что ACP будет маршрутизировать и/или пересылать по защищённым каналам ACP пакеты, полученные от любого другого узла ACP, а не только свои пакеты. В транспортном режиме IPsec (без дополнительной инкапсуляции заголовка в данные ESP) возможно лишь передавать пакеты, созданные самим узлом ACP, поскольку адреса IPv6 в ESP должны совпадать с адресами во внешнем заголовке IPv6.

6.8.3.1.1. RFC 8221 (IPsec/ESP)

Реализации ACP IPsec должны соответствовать [RFC8221] и обновляющим его документам. Приведённые в этом параграфе и выше требования изменяют и переопределяют требования указанного документа.

Заголовок аутентификации IP (Authentication Header или AH) применять недопустимо (не обеспечивается конфиденциальность).

Для требуемых алгоритмов шифрования ESP из раздела 5 в [RFC8221] заданы дополнительные рекомендации:

  • ENCR_NULL AH применять недопустимо (не обеспечивается конфиденциальность);

  • ENCR_AES_GCM_16 является единственным MTI для шифрования ESP в ACP через IPsec/ESP (уже указан как обязательный в [RFC8221]);

  • можно поддерживать ENCR_AES_CBC с AUTH_HMAC_SHA2_256_128 (как алгоритм шифрования ESP) и ENCR_AES_CCM_8, если какой-то алгоритм превосходит ENCR_AES_GCM_16 по производительности, его следует поддерживать;

  • ENCR_CHACHA20_POLY1305 следует поддерживать с производительностью не ниже ENCR_AES_GCM_16, можно поддерживать алгоритм и при более низкой производительности.

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

  • Не задаются требования к взаимодействию с унаследованным оборудованием в защищённых каналах ACP, поэтому достаточно одного алгоритма MTI для IPsec в защищённых каналах ACP, чтобы обеспечить совместимость и применять самые лёгкие реализации.

  • ENCR_AES_GCM_16 является режимом аутентифицированного шифрования со связанными данными (Authenticated Encryption with Associated Data или AEAD), поэтому не требуется дополнительный алгоритм аутентификации ESP, что упрощает требования к MTI для ACP с IPsec.

  • Не задаётся требований к MTI для поддержки ENCR_AES_CBC, поскольку предполагается, что алгоритм ENCR_AES_GCM_16 реализуем в системах с аппаратным ускорением с меньшими затратами и/или большей производительностью, нежели ENCR-AES_CBC.

  • Алгоритм ENCR_CHACHA20_POLY1305 обязателен в [RFC8221], поскольку его целевым применением является резервирование (откат) при обнаружении слабых мест в AES. К сожалению, в настоящее время нет способа автоматически распространить через ACP правило для запрета использования алгоритмов на базе AES, поэтому данное преимущество ENCR_CHACHA20_POLY1305 ещё не может быть полностью реализовано в ACP. В результате алгоритм остаётся лишь рекомендуемым. Замена AES на этот алгоритм с возможным падением производительности может сделать ACP неработоспособной. Поэтому к данному алгоритму предъявляется требование производительности, чтобы он стал эффективным резервом защиты для AES в ACP, как только политика перехода на него или предпочтение станет доступным в среде ACP.

[RFC8221] разрешает ключи размером 128 или 256 битов для AES. Этот документ указывает, что должны поддерживаться лишь 256-битовые ключи AES.

При обновлении [RFC8221] реализации ACP должны будут решить вопрос совместимости с устаревшими системами.

6.8.3.1.2. RFC 8247 (IKEv2)

В [RFC8247] даны базовые рекомендации по обязательным для реализации (MTI) шифрам, проверке целостности, псевдослучайным функциям и механизмам Diffie-Hellman. Эти рекомендации и рекомендации последующих документов применимы и к ACP. Поскольку IKEv2 на защищённых каналах ACP достаточно реализовать в программах плоскости управления, а не специализированных микросхемах (Application-Specific Integrated Circuit или ASIC), а на узлах ACP с поддержкой IKEv2 не предполагается ограничений пространства кода и в имеющихся реализациях IKEv2 предполагается поддержка рекомендаций [RFC8247], этот документ не пытается упростить рекомендации для ACP.

В [IKEV2IANA] приведены имена параметров IANA IKEv2, используемые в тексте.

Узлы ACP, поддерживающие IKEv2, должны соответствовать [RFC8247] с изменениями, представляющими заявление политики, разрешённое [RFC8247].

Для сигнализации цепочки сертификатов ACP (включая TA), как требует параграф 6.8.2, можно применять в IKEv2 содержимое X.509 Certificate — Signature. Это обязательно в соответствии с параграфом 3.6 в [RFC7296].

Узлам ACP следует настроить IKEv2 для использования лишь сертификата ACP и TA при работе в качестве ответчика IKEv2 с адресом IPv6 link-local и номером порта, указанным в анонсах DULL GRASP AN_ACP (см. параграф 6.4).

При получении от партнёра CERTREQ без указания какого-либо из сертификатов TA этого узла ACP, узлу ACP следует игнорировать CERTREQ и продолжить передачу своей цепочки сертификатов, включающей его TA, в соответствии с параграфом 6.8.2. Это не приведёт к успеху взаимной аутентификации, но поможет в диагностике.

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

В IKEv2 узлы ACP идентифицируются по их адресам ACP. Должны применяться идентификационные данные IKEv2 ID_IPv6_ADDR, которые должны содержать адрес ACP. Если партнерский сертификат ACP включает адрес ACP 32HEXDIG в acp-node-name (не 0), адрес в идентификационных данных IKEv2 должен совпадать с ним. В параграфе 6.2.3 приведены дополнительные сведения для случая отсутствия адреса ACP или значения в acp-node-name.

При аутентификации IKEv2 должен применяться метод 14 (Digital Signature) для сертификатов ACP, этот метод может использоваться с сертификатами RSA и ECDSA указанными объектом ASN.1 AlgorithmIdentifier.

Для Digital Signature должен поддерживаться хэш SHA2-512 в дополнение к SHA2-256.

Должен поддерживаться обмен ключами IKEv2 Diffie-Hellman группы 19 (256-битовое случайное значение ECP). Причина этого заключается в том, что ECC обеспечивает уровень безопасности, аналогичный обмену ключами с конечным полем (модульное возведение в степень — MODP), при более коротком ключе, поэтому предпочтительней при отсутствии иных соображений.

6.8.3.2. IPsec с инкапсуляцией GRE

В сетевых устройствах высокопроизводительные виртуальные интерфейсы чаще реализуются на основе инкапсуляции GRE, нежели «естественных» ассоциаций IPsec (без какой-либо инкапсуляции, заданной IPsec). Для таких устройств организация защищённых каналов ACP на основе GRE с защитой IPsec.

Требования для ESP/IPsec/IKEv2 с GRE такие же, как для IPsec (6.8.3.1. Естественная защита IPsec) за исключением согласования транспортного режима и следующего протокола GRE (47). GRE позволяет избежать туннельного режима. Селекторы трафика имеют вид

  TSi = (47, 0-65535, Initiator-IPv6-LL-addr ... Initiator-IPv6-LL-addr)
  TSr = (47, 0-65535, Responder-IPv6-LL-addr ... Responder-IPv6-LL-addr)

Если инициатор и ответчик поддерживают IPsec на основе GRE, это будет предпочтительней естественного режима IPsec, поскольку IKEv2 согласует транспортный режим (как задано профилем IPsec на базе GRE) в отличие от туннельного при естественном IPsec (см. параграф 1.3.1 в [RFC7296]). Трафик IPv6 ACP передаётся через GRE в соответствии с IPv6 Support for Generic Routing Encapsulation (GRE) [RFC7676].

6.8.4. ACP по протоколу DTLS

Этот документ определяет использование ACP через DTLS в предположении, что это, вероятно, первое транспортное шифрование, поддерживаемое некоторыми классами устройств с ограничениями — DTLS обычно применяется в таких устройствах, а IPsec — нет. Пространство кода в таких устройствах может быть ограничено, чтобы поддерживать требования сверх минимальных.

Узел ACP анонсирует свою способность поддерживать DTLS версии 1.2 (Datagram Transport Layer Security Version 1.2 [RFC6347]), совместимую с требованиями этого документа, как протокол защищённого канала ACP в GRASP с помощью objective-value = DTLS в цели AN_ACP (6.4. Обнаружение соседей с помощью DULL GRASP).

Для работы ACP через UDP и DTLS применяется локально заданный порт UDP, анонсируемый кандидату в партнёры как параметр цели GRASP AN_ACP. Этот порт может быть связан с любой новой версией DTLS, если она может согласовать соединение DTLS 1.2 при наличии партнёра, поддерживающего лишь DTLS 1.2.

Все узлы ACP, поддерживающие DTLS как протокол защищённого канала, должны следовать рекомендациям по реализации DTLS и соображениям безопасности из BCP 195 [RFC7525], за исключением версии DTLS. Узлы ACP, поддерживающие DTLS, должны поддерживать DTLS 1.2 и недопустима поддержка более старых версий DTLS.

В отличие от IPsec, не предпринимается попыток упростить требования BCP 195 [RFC7525], поскольку предполагается, что DTLS будет использовать лишь программные реализации, где повторное использование широко распространённых реализаций важнее возможности минимизировать сложности реализаций с аппаратным ускорением, важной для IPsec.

DTLS 1.3 [TLS-DTLS13] совместима с DTLS 1.2 (см. раздел 1 в [TLS-DTLS13]). Реализация DTLS, поддерживающая DTLS 1.2 и DTLS 1.3 соответствует приведённым выше требованиям согласования DTLS 1.2 при наличии партнёра, поддерживающего лишь DTLS 1.2, но использует DTLS 1.3, когда оба партнёра поддерживают эту версию.

Версия 1.2 является MTI для DTLS в этой спецификации по указанным ниже причинам.

  • Имеется обширный опыт применения DTLS 1.2 на широком спектре целевых устройств ACP.

  • Микрокод мелких встраиваемых устройств ACP может долгое время не поддерживать новую версию.

  • В DTLS 1.3 внесены существенные изменения, такие как иной уровень записи, требующий времени на реализацию и развёртывание, особенно на устройствах низкого уровня с ограниченным пространством кода.

  • Обновление имеющегося BCP [RFC7525] для DTLS 1.2 может занять столько же времени, как обретение опыта для более новых версий DTLS.

  • Нет существенных преимуществ DTLS 1.3 над DTLS 1.2, важных в контексте опций ACP для DTLS. Например, повышение производительности сигнализации при организации сессии в DTLS 1.3 не важно для ACP с учётом длительного срока работы защищённых каналов ACP и того, что соединения DTLS организуются в основном на локальном канале (малое значение RTT).

Тем не менее, новые версии DTLS, такие как DTLS 1.3, предъявляют более строгие требования к защите, а стандарты IETF обычно требуют применять последнюю версию стандартных протоколов. Поэтому рекомендуется поддерживать в реализациях ACP все более новые версии DTLS, которые все ещё могут согласовываться в DTLS 1.2.

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

6.8.5. Профили защищённых каналов ACP

Как отмечено в начале параграфа 6.6, не т единого механизма защиты каналов, заданного для всех узлов ACP. Вместо этого данный параграф определяет два профиля ACP — базовый (baseline) и ограниченный (constrained) для узлов ACP которые вносят такие требования.

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

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

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

Узлам ACP требуется указывать набор поддерживаемых механизмов защиты ACP в документации, а также следует объявлять поддерживаемые в соответствии с приведёнными выше требованиями профили.

6.9. GRASP в ACP

6.9.1. GRASP как базовый сервис ACP

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

ACP обеспечивает индивидуальную маршрутизацию IP на основе протокола RPL (6.12. Маршрутизация в ACP).

В ACP не применяется групповая маршрутизация IP и не предоставляются базовые групповые услуги IP (обработка групповых сообщений GRASP link-local описана в параграфе 6.9.2). Вместо этого ACP обеспечивает обнаружение служб со помощью механизмов обнаружения, анонсирования и согласования цели в экземпляре ACP GRASP (службы являются формой цели). Эти механизмы используют поэтапную (hop-by-hop) надёжную лавинную рассылку сообщений GRASP M_DISCOVERY для обнаружения и M_FLOOD — для анонсирования услуг. Более подробно это описано в Приложении A.5. Распространение информации ACP и групповая передача.

6.9.2. ACP как защищённая транспортная подложка для GRASP

В терминологии GRASP [RFC8990] ACP является подложкой защиты и транспорта для экземпляра GRASP, запущенного внутри ACP (ACP GRASP). Это значит, что ACP отвечает за то, что этот экземпляр GRASP передаёт сообщения только через виртуальные интерфейсы ACP GRASP. При каждом добавлении или удалении такого интерфейса ACP в результате создания или закрытия защищённого канала ACP это нужно указать запущенному в ACP экземпляру GRASP. ACP может работать даже при отсутствии активных соседей ACP. Плоскость ACP создаётся при наличии у узла сертификата домена и продолжает существовать, даже когда соседи перестают работать. В таких случаях агенты ASA, использующие экземпляр GRASP на том же узле, по-прежнему должны иметь возможность обнаруживать цели друг друга. Когда ACP не существует, агенты ASA, использующие экземпляр ACP GRASP через API, должны продолжать работу и должны быть способны понимать, что ACP нет и, следовательно, экземпляр ACP GRASP не может работать.

Работа ACP в качестве подложки защиты и транспорта для GRASP показана на рисунке 8.

Индивидуальные сообщения GRASP внутри ACP всегда используют адрес ACP. Адреса link-local из ACP VRF недопустимо применять внутри целей. Индивидуальные сообщения GRASP внутри ACP доставляются через TLS, требования описаны в параграфе 6.1. Требования к использованию TLS. При взаимной аутентификации TLS должна выполняться проверка принадлежности к домену ACP, описанная в параграфе 6.2.3.

Групповые сообщения GRASP link-local нацелены на конкретные виртуальные интерфейсы ACP (6.13.5. Интерфейсы ACP), но ACP передаёт их на виртуальные интерфейсы ACP GRASP, основанные на соединениях TCP с адресами соседей IPv6 link-local через базовый виртуальный интерфейс ACP. Если у виртуального интерфейса ACP GRASP есть не меньше 2 соседей, групповые сообщения GRASP link-local реплицируются во все соединения TCP с соседями.

..............................ACP..............................
.                                                             .
.         /-GRASP-flooding-\         Экземпляр ACP GRASP      .
.        /                  \                                 A
.    GRASP      GRASP      GRASP                              C
.  link-local  индивид.  link-local                           P
.   групповые  сообщения  групповые                           .
.   сообщения     |       сообщения                           .
.      |          |          |                                .
...............................................................
.      v          v          v    ACP security and transport  .
.      |          |          |    substrate for GRASP         .
.      |          |          |                                .
.      |       ACP GRASP     |       - ACP GRASP              A
.      |       loopback-     |         петлевой интерфейс     C
.      |       интерфейс     |       - ACP-cert auth          P
.      |         TLS         |                                .
.   ACP GRASP     |       ACP GRASP  - Виртуальные интерфейсы .
.   subnet1       |       subnet2      ACP GRASP              .
.     TCP         |         TCP                               .
.      |          |          |                                .
...............................................................
.      |          |          |   ^^^ Пользоват.ACP (GRASP/ASA).
.      |          |          |   интерфейсы/адресация ACP     .
.      |          |          |                                .
.      |          |          |                                A
.      | ACP loopback-интерф.|      <- адрес петлевого интерф.C
.      |      ACP-адрес      |       - ACP (global ULA)       P
.    subnet1      |        subnet2  <- Адреса link-local      .
.  link-local     |      link-local  - виртуал. интерф. ACP   .
...............................................................
.      |          |          |   ACP VRF                      .
.      |  RPL-маршрутизация  | виртуальная маршрутизация      .
.      |   /IP-пересылка \   | и пересылка                    A
.      |  /               \  |                                C
.  Пакеты ACP IPv6    Пакеты ACP IPv6                         P
.      |/                   \|                                .
.    IPsec/DTLS        IPsec/DTLS  - ACP-cert auth            .
...............................................................
         |                   |   Плоскость данных
         |                   |
         |                   |     - защищённый канал ACP
     link-local        link-local  - адреса инкапсуляции
       subnet1            subnet2  - интерфейсы плоскости данных
         |                   |
      ACP-Nbr1            ACP-Nbr2

Рисунок 8. ACP как подложка защиты и транспорта для GRASP.


Соединения TCP и TLS для GRASP в ACP используют выделенный IANA порт TCP для GRASP (7017). По сути, предполагается применение транспортного стека TLS для соединений с адресами ACP (например, глобальные адреса) и TCP для соединений с адресами link-local на виртуальных интерфейсах ACP. Последние применяются лишь для лавинной рассылки сообщений GRASP.

6.9.2.1. Обсуждение

Инкапсуляция TCP для сообщений GRASP M_DISCOVERY и M_FLOOD на локальном канале применяется из-за того, что эти сообщения рассылаются в лавинном режиме возможно через несколько интервалов (hop) всем узлам ACP, а один канал даже с временными потерями (например, Wi-Fi или Powerline) может снизить вероятность передачи без потерь так, что приложения захотят повысить частоту отправки этих сообщений. Такое сокращение периода отправки дейтаграмм увеличит трафик и издержки на обработку в ACP по сравнению с надёжным поэтапным (hop-by-hop) повтором передачи, обеспечиваемым TCP без возникновения дубликатов GRASP.

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

Прослушивание и/или подмена скомпрометированным узлом ACP по-прежнему возможны, поскольку в модели ACP и GRASP поставщик и потребитель цели изначально не имеют уникальных сведений (таких, как отождествление) о другой стороне, которые позволили бы различить скомпрометрированных партнёров. Скомпрометированный узел ACP может просто анонсировать цель, фильтровать исходную цель GRASP при участии в MITM-атаке и действовать как посредник прикладного уровня. Это требует от скомпрометированного узла ACP понимания семантики согласования GRASP для выступления в роли посредника без обнаружения, но в среде ACP такая семантика может быть открыта и даже стандартизована.

Соединения GRASP TLS работают также, как любая передача трафика ACP через защищённые каналы ACP. Это ведёт к двойной аутентификации и шифрованию, обеспечивая перечисленные ниже преимущества.

  • Методы защиты канала, такие как IPsec, могут обеспечивать дополнительную защиту от атак (например, атак со сбросом).

  • Метод защиты канала может применять аппаратное ускорение, но выигрыш от этого невелик.

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

6.10. Разделение контекста

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

В классических сетевых системах VRF является одним из логических вариантов реализации ACP. Если это разрешено программной архитектурой системы, логический контейнер или экземпляр виртуальной машины будет предпочтительным для разделения контекста, минимизируя общие компоненты. Контекст для ACP требуется создавать автоматически при начальной загрузке узла. По возможности, его следует защитить от непреднамеренного изменения при настройке конфигурации (плоскости данных).

Разделение контекста повышает уровень защиты, поскольку плоскость ACP недоступна из таблиц маршрутизации и пересылки плоскости данных. Ошибки настройки плоскости данных не будут влиять на ACP.

6.11. Адресация внутри ACP

Описанные выше каналы обычно связывают лишь два соседних узла, а для взаимодействия через несколько узлов (hop) в ACP нужна действительная адресация и маршрутизация в масштабе сети. Каждый узел ACP создаёт петлевой (loopback) интерфейс с уникальным в масштабе сети ACP адресом (префиксом) в контексте ACP (6.10. Разделение контекста). Этот адрес можно применять и в другом виртуальном контексте.

С представленным здесь алгоритмом все узлы в одном субдомене маршрутизации имеют один префикс ULA /48. И наоборот, ULA Global ID из разных доменов вряд ли будут конфликтовать, так что две сети ACP можно объединить, если политика разрешает это. Вопросы слияния доменов рассмотрены в параграфе 10.1. Свойства самовосстановления.

Каналы внутри ACP применяют лишь адреса IPv6 link-local, поэтому каждому узлу ACP нужен лишь один маршрутизируемый адресный префикс.

6.11.1. Фундаментальные концепции автономной адресации

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

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

  • Только шлейфовые адреса. Маршрутизируемые адреса имеют лишь петлевые интерфейсы ACP (возможно, интерфейсы, настроенные для ACP connect, 8.1. ACP Connect), все прочие (виртуальные интерфейсы ACP) используют лишь адреса IPv6 link-local. Применение адресации IPv6 link-local описано в Using Only Link-Local Addressing inside an IPv6 Network [RFC7404].

  • Использование ULA. Для петлевых интерфейсов узлов ACP применяются ULA с установленным (1) битом L (параграф 3.1 в [RFC4193]). Отметим, что случайное хэш-значени для петлевого адреса ACP использует определение из параграфа 6.11.2. Базовая схема адресации ACP, а не из параграфа 3.2.2 в [RFC4193].

  • Нет внешних соединений. Адреса не обеспечивают доступа в Internet. Если узлу нужны внешние соединения, ему следует параллельно применять управляемую традиционным способом систему адресации.

  • Адреса в ACP являются постоянными, а временные адреса, определённые в Temporary Address Extensions for Stateless Address Autoconfiguration in IPv6 [RFC8981], не поддерживаются.

  • Адреса ACP не считаются чувствительными в плане приватности, поскольку узлы ACP не предполагаются в качестве пользовательских хостов, поэтому адреса ACP не указывают конечных пользователей или группы. Все узлы ACP размещаются в одном (возможно, федеративном) административном домене. Для трафика ACP узлы предполагаются хостами-кандидатами или транзитными узлами. Нет транзитных узлов с меньшими правами знать отождествления других хостов в ACP. Поэтому адреса ACP не обязаны быть псевдослучайными, как описано в Security and Privacy Considerations for IPv6 Address Generation Mechanisms [RFC7721]. Поскольку адреса не распространяются недоверенным (не ACP) узлам и остаются внутри домена (доверия), они не считаются объектами атак со сканированием.

В ACP применяется лишь адресация IPv6 по ряду причин, перечисленных ниже.

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

  • Автономные функции не требуют IPv4. Автономные функции и агенты служб — это новые концепции и могут строиться изначально на основе IPv6. Совместимость с прежними версиями не требуется.

  • Протоколам OAM не требуется IPv4. ACP пожет поддерживать протоколы OAM и соответствующие протоколы (SNMP, TFTP, SSH, SCP, RADIUS, Diameter, NETCONF и т. п.) доступны в IPv6. Взаимодействие ACP с OAM на основе IPv4 рассмотрено в [RFC8368].

Дополнительное рассмотрение причин выбора адресации и маршрутизации для ACP приведено в параграфе 6.13.5.1. Петлевые интерфейсы ACP.

6.11.2. Базовая схема адресации ACP

Базовая схема адресации ULA для узлов ACP показана на рисунке 9.

  8      40                     2                     78
+--+-------------------------+------+------------------------------+
|fd| hash(routing-subdomain) | Type |       (sub-scheme)           |
+--+-------------------------+------+------------------------------+

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


Первые 48 битов соответствуют схеме ULA, заданной в [RFC4193], с добавлением поля Type.

fd

Указывает локально определённый адрес ULA.

hash(routing-subdomain)

40-битовое поле ULA Global ID (термин из [RFC4193]) для адреса ACP, передаваемого в acp-node-name сертификата ACP, содержит первые 40 битов хэш-значения SHA-256 субдомена маршрутизации из того же acp-node-name. В примере из параграфа 6.2.2 субдомен маршрутизации — это area51.research.acp.example.com, а ULA Global ID — 89b714f3db.
При создании нового субдомена маршрутизации для имеющейся автономной сети должно выбираться значение rsub, не создающее конфликтов результирующего хэш-значения субдомена маршрутизации с существующими маршрутными субдоменами автономной сети. Это гарантирует отсутствие конфликтов между адресами ACP, созданными регистраторами для разных субдоменов маршрутизации.
Для поддержки расширяемости узлам ACP при нормальной работе не следует предполагать, что ULA Global ID является хэш-значением субдомена маршрутизации. Хэш-функция выполняется лишь в процессе создания сертификата. При использовании BRSKI регистратор BRSKI создаёт registrar acp-node-name в ответ на сообщение EST Certificate Signing Request (CSR) Attributes Request от заявителя.
Организация связности между разными ACP (разные acp-domain-name) выходит за рамки этой спецификации. Если это будет происходить на основе будущих расширений, потребуется выбирать rsub во всех субдоменах маршрутизации этих автономных систем так, чтобы не возникало конфликтов хэш-значений. Например, большая корпорация с приватной привязкой доверия (TA) может создать автономные сети, которые исходно не связаны, с возможностью их последующего объединения. С учётом такой возможности легко выбрать rsub, чтобы не было конфликтов.

Type

Это поле позволяет применять разные субсхемы адресации в соответствии с требованием обновляемости. Назначение и поддержка типов предоставляется IANA.

(sub-scheme)

Субсхема может просто указывать диапазон или набор адресов, выделенных узлу. Это называется диапазоном (набором) адресов ACP и разъяснено для каждой субсхемы ниже.

Причины использования нескольких субсхем адресации и работа с ними описаны в параграфе 6.11.7. Регистраторы ACP и Приложении A.1. Схемы адресного пространства ACP. Сводка субсхем приведена в таблице 1

Таблица 1. Субсхемы адресации.

 

Тип

Имя

Биты F

Z

Биты V

Префикс

0

ACP-Zone

0

1

/127

0

ACP-Manual

1

/64

1

ACP-Vlong-8

0

8

/120

1

ACP-Vlong-16

1

16

/112

2

Резерв на будущее

3

 

Биты F (бит формата, 6.11.5. Субсхемы ACP Vlong (ACP-Vlong-8 и ACP-Vlong-16)) и Z (6.11.4. Субсхема ручной адресации ACP (ACP-Manual)) задают кодирование, как описано ниже. Число битов V указывает размер адресов, выделенных узлу ACP, а префикс указывает размер префикса, анонсируемого узлом ACP в RPL.

6.11.3. Субсхема адресации ACP Zone (ACP-Zone)

Эта субсхема указывается значениями Type = 0 и Z = 0.

                 64                             64
+-----------------+---+---------++-----------------------------+---+
| (базовая схема) | Z | Zone-ID ||           Node-ID               |
|                 |   |         || Registrar-ID |   Node-Number| V |
+-----------------+---+---------++--------------+--------------+---+
         50         1     13            48           15          1

Рисунок 10. Субсхема адресации ACP Zone.


Type

Должно быть 0.

Z

Должно быть 0.

Zone-ID

Значение для зоны сети.

Node-ID

Уникальное значение для каждого узла.
64-битовое поле Node-ID для узла должно быть уникальным в домене ACP и задаётся, как указано ниже.

Registrar-ID (48 битов)

Уникальное для домена значение, указывающее регистратора ACP, назначившего Node-ID для узла. Для этого может применяться 1 или несколько уникальных в домене идентификаторов регистратора ACP (см. параграф 6.11.7.2. Выделение уникального адреса/префикса).

Node-Number

Число, делающее значение Node-ID уникальным. Это могут быть последовательные значения, выделяемые регистратором ACP, который владеет Registrar-ID.

V (1 бит)

Бит виртуализации
0 — указывает саму плоскость (базовая система узла ACP);
1 — указывает необязательный контекст «хоста» узла ACP (см. ниже).

В субсхеме адресации ACP-Zone адрес ACP в сертификате имеет поле V, содержащее только 0.

Набор адресов ACP на узле включает адреса с любыми значениями Zone-ID и V, поэтому никаие два узла в одной плоскости ACP и с одним хэшем субдомена маршрутизации не могут иметь одинаковые Node-ID в субсхема адресации ACP-Zone, отличаясь, например, лишь Zone-ID.

Бит виртуализации (V) в этой субсхеме позволяет легко добавлять ACP в имеющиеся системы, не вызывая проблем в пространстве номеров портов между службами ACP и имеющейся системы. V=0 указывает маршрутизатор ACP (базовая система автономного узла), а V=1 — хост с имеющимися транспортными конечными точками, которые могут конфликтовать с транспортными конечными точками, используемыми маршрутизатором ACP. Хост ACP может, например, иметь виртуальный интерфейс P2P (точка-точка) с адресом с V=0 в качестве маршрутизатора для ACP. В зависимости от устройства программ агентов ASA, выходящего за рамки этой спецификации, он может использовать адрес с V=0 или V=1. Размещение бита V в конце адреса позволяет анонсировать 1 префикс для каждого узла ACP. Например, в сети 20 000 узлов ACP это позволяет избежать 20 000 дополнительных маршрутов в таблице.

Рекомендуется применять только Zone-ID = 0, если это не предназначено для использования в сочетании с практикой частичного или поэтапного внедрения ACP, как описано в параграфе 9.4. Частичное или поэтапное внедрение.

Примечание. Зоны и Zone-ID, заданные здесь, не связаны с зонами и zone_id в IPv6 Scoped Address Architecture [RFC4007]. Адреса зон ACP не ограничены областью действия (т. е. доступны не только внутри зоны, как в [RFC4007]) и доступны из всей плоскости ACP. Идентификатор zone_id является индексом зоны с локальной значимостью на узле [RFC4007], а ACP Zone-ID служит идентификатором для зоны ACP, уникальным в рамках ACP.

6.11.4. Субсхема ручной адресации ACP (ACP-Manual)

                64                             64
+---------------------+---+----------++-----------------------------+
|   (базовая схема)   | Z | Subnet-ID||     Interface Identifier    |
+---------------------+---+----------++-----------------------------+
         50             1    13

Рисунок 11. Субсхема адресации ACP Manual.


Эта субсхема указывается значениями Type = 0 и Z = 1.

Type

Должно быть 0.

Z

Должно быть 1.

Subnet-ID

Настроенный идентификатор подсети.

Interface Identifier

Идентификатор интерфейса в соответствии с [RFC4291].

Эта субсхема указывает назначение подсетей «вручную», когда другие схемы не подходят. Она применяется в основном на подсетей ACP (8.1.1. Контроллер или NMS без поддержки ACP). Этот режим означает, что значение Subnet-ID должно быть быть выделено уже имеющимся, неавтономным механизмом. В каждой сети, применяющей эту субсхему, должно устанавливаться уникальное значение Subnet-ID (если не применяется anycast).

Бит Z служит для различения субсхем Zone и Manual без добавления ещё одного бита в базовую схему, что позволяет субсхемам Vlong (6.11.5. Субсхемы ACP Vlong (ACP-Vlong-8 и ACP-Vlong-16)) иметь 1 дополнительный бит.

Адреса субсхемы Manual не следует использовать в сертификатах ACP. Любому способному строить защищённые каналы ACP узлу, которому политика регистратора разрешает создавать такие каналы, следует получать адрес (префикс) ACP от иной (не ручной) субсхемы адресации ACP. Узел, который не может (не разрешено) участвовать в защищённых каналах ACP, может подключаться к ACP через интерфейсы ACP connect на граничных узлах ACP (8.1. ACP Connect) без создания защищённого канала ACP. В его сертификате ACP должно быть опущено поле acp-address для указания применимости сертификата ACP лишь отличными от ACP защищёнными каналами, такими как сквозные транспортные соединения через ACP или плоскость данных.

Управление адресами подсетей ACP connect выполняется традиционными методами и имеющимися протоколами IPv6 (см. 8.1.3. Автонастройка), поэтому V-биты при адресации узлов ACP не применяются в этой субсхеме.

6.11.5. Субсхемы ACP Vlong (ACP-Vlong-8 и ACP-Vlong-16)

Эта субсхема адресации применяется при значении Type = 1 в базовой схеме.

          50                              78
+---------------------++-----------------------------+----------+
|   (базовая схема)   ||           Node-ID                      |
|                     || Registrar-ID |F| Node-Number|        V |
+---------------------++--------------+--------------+----------+
          50                46         1   23/15          8/16

Рисунок 12. Субсхема адресации ACP Vlong.


В этой субсхеме отсутствует поле Zone-ID (6.11.3. Субсхема адресации ACP Zone (ACP-Zone)), чтобы представлять более крупные сети с плоской маршрутизацией (например, IoT) и 8 421 376 Node-Number (223 + 215). Она также позволяет использовать до 216 (65 536) виртуализованных адресов на узле, которые могут служить для адресации программных компонентов на узле ACP.

Поля похожи на применяемые в субсхеме Zone (6.11.3. Субсхема адресации ACP Zone (ACP-Zone)) с уточнениями.

F

Бит, определяющий формат последующих битов.

V

Биты виртуализации (8 при F=0, 16 при F=1), задаваемые узлом ACP. В адресе ACP сертификата ACP (6.2.2. AcpNodeName в сертификате ACP) все биты V имеют значение 0.

Registrar-ID

Для максимизации Node-Number и V поле Registrar-ID сокращено до 46 битов. Можно применять 1 или несколько идентификаторов регистраторов ACP для домена (см. 6.11.7.2. Выделение уникального адреса/префикса).

Node-Number

Значение Node-Number уникально для каждого узла ACP и может иметь 2 формата — 23 бита при F=0, и 15 при F=1. Для каждого формата Node-Number используется своё пространство номеров.

Формат адреса при F=0 предназначен для узлов ACP «общего назначения» которые обычно имеют ограниченное число (меньше 256) клиентов ACP (ASA и/или автономные функции или унаследованные службы), которым нужны отдельные виртуальные (V) адреса. Адреса с F=1 предназначены для узлов ACP, которые служат краевыми (8.1.1. Контроллер или NMS без поддержки ACP) или имеют большое число клиентов, требующих отдельных виртуальных (V) адресов, например, большие контроллеры SDN с модульной контейнерной архитектурой программ (8.1.2. Программные компоненты).

В субсхеме адресации Vlong адреса ACP в сертификате имеют поле V, заполненное нулями. Адрес ACP для узла может иметь любое значение поля V.

6.11.6. Другие субсхемы адресации ACP

Для определения других субсхем адресации нужно собрать опыт применения описанных здесь схем, которые были разработаны для обеспечения достаточной гибкости при организации ACP в разных ситуациях. Это привело к достаточно гибкому использования адресного пространства. Субсхема Zone предназначена для оптимизированной маршрутизации в больших сетях за счёт резервирования битов для Zone-ID, субсхемы Vlong позволяют выделять 8- или 16-битовые адреса внутри отдельных узлов ACP и оба адресных пространства поддерживают распределенное выделение адресов узлов без координации за счёт резервирования битов для поля Registrar-ID в адресах.

6.11.7. Регистраторы ACP

Регистраторы ACP отвечают за зачисление узлов-кандидатов ACP с сертификатами ACP и соответствующими привязками доверия, а также за включение поля acp-node-name в сертификат ACP. Это поле содержит имя домена ACP и префикс адреса ACP для узла ACP, который должен оставаться неизменным в течение срока жизни узла ACP.

Наличие субсхем адресации ACP позволяет домену ACP иметь несколько распределенных регистраторов ACP, которые не обязаны координировать назначение адресов. Регистраторы ACP могут также служить суб-CA и в этом случае они могут выдавать сертификаты ACP независимо от (общих) TA (кроме обновления своих сертификатов).

Регистраторы ACP являются агентами регистрации PKI (PKI registration authorities или RA), расширенными обработкой связанных с сертификатами ACP полей. Они запрашивают сертификаты для узлов ACP у CA с помощью любого подходящего механизма (это выходит за рамки документа, но этот механизм должен BRSKI для регистраторов ANI). Только узлам, являющимся доверенными в соответствии с указанными здесь требованиями к регистраторам, могут быть предоставлены свидетельства, необходимые для выполнения этой функций RA (такие как свидетельство регистратора ACP для подключения к CA в таком качестве).

6.11.7.1. Использование BRSKI или иных механизмов и протоколов

Регистраторы ACP могут применять любые протоколы и механизмы при условии, что полученный сертификат ACP и сертификаты TA могут использоваться другими членами домена для проверки принадлежности к домену ACP, описанной в параграфе 6.2.3. Проверка принадлежности к домену ACP, и соответствия поля acp-node-name требованиям к адресации ACP, приведённым в трёх следующих параграфах.

Регистратором ACP может быть лицо, принимающее решение о зачислении кандидата в ACP и последующей организации (оркестровке) зачисления сертификата ACP и связанной TA через команды или web-интерфейс на узле-кандидате в ACP и TA для генерации и подписывания сертификата ACP, а также настройки сертификата и TA на узле.

В настоящее время для регистраторов ACP определён лишь протокол BRSKI [RFC8995]. При использовании BRSKI узлы ACP называются узлами ANI, а регистраторы ACP — регистраторами BRSKI или ANI. Спецификация BRSKI не задаёт обработки поля acp-node-name, поскольку правила не зависят от BRSKI, но в равной мере применяются к любым протоколам и механизмам, которые может использовать регистратор ACP.

6.11.7.2. Выделение уникального адреса/префикса

Регистратора ACP недопустимо выделять адресные префиксы ACP узрам ACP по имени acp-node-name, которое может вызывать конфликты с префиксами ACP других узлов ACP в том же домене ACP. Это включает префиксы, выделенные одним регистратором ACP разным узлам ACP, и префиксы, выделенные другими регистраторами ACP для того же домена ACP.

Для выделения уникальных адресов регистратор ACP должен имет 1 или несколько 46-битовых идентификаторов (Registrar-ID), уникальных в домене ACP. назначение Registrar-ID регистраторам ACP может происходить с помощью механизмов OAM в сочетании с некой базой данных и/или оркестровкой выделения.

Регистраторы ACP, работающие на узлах с глобально уникальными адресами EUI7-48 MAC, могут использовать младшие 46 битов этих адресов в качестве уникального Registrar-ID без какой-либо внешней сигнализации и/или настройки (два старших бита V и U, не задаются однозначно, но функциональны). Этот подход привлекателен для распределенных реализаций облегчённых регистраторов ACP без централизованного администрирования. Механизма проверки уникальности MAC-адреса не существует и реализациям следует применять дополнительные внешние (offline) сведения для принятия допущений об уникальности адресов. Это может быть, например, сведения о продукции или микросхемах сетевых адаптеров (Network Interface Controller или NIC), гарантирующие наличие глобально уникального адреса EUI-48 MAC.

Когда устройство-кандидат в ACP (заявитель в BRSKI) зачисляется в домен ACP, регистратору ACP нужно выделить узлу уникальный адрес ACP и обеспечить включение в сертификат ACP поля acp-node-name (6.2.2. AcpNodeName в сертификате ACP) с подобающей информацией — именем домена ACP, адресом ACP и т. д. Если регистратор ACP применяет BRSKI, он сообщает поле ACP acp-node-name заявителю в атрибутах EST CSR (см. параграф 5.9.2 в [RFC8995]).

6.11.7.3. Правила субсхем адресации

Регистратор ACP выбирает для узла-кандидата ACP уникальный префикс адреса из подходящей субсхемы адресации ACP — префикс субсхемы Zone (6.11.3. Субсхема адресации ACP Zone (ACP-Zone)) или Vlong (6.11.5. Субсхемы ACP Vlong (ACP-Vlong-8 и ACP-Vlong-16)). Назначенный префикс адреса ACP, закодированный в поле acp-node-name сертификата ACP, указывает узлу ACP сведения о его адресе ACP. Субсхема адресации задаёт размер префикса — /127 для Zone, /120 или /112 для Vlong. Первый адрес из этого префикса является адресом ACP, а остальные адреса предназначены для иных применений узлом ACP, как описано в параграфах для субсхем Zone и Vlong. Сам префикс адреса ACP передаётся узлом ACP в протокол маршрутизации ACP (6.12. Маршрутизация в ACP) для обеспечения доступности IPv6 через ACP.

Выбор субсхемы адресации и размер префикса Vlong определяется политикой регистратора ACP. Это может быть политика для домена ACP, узла ACP или типа узлов ACP. Например, в BRSKI регистратор ACP знает сертификат IDevID узла-кандидата ACP, который обычно содержит атрибут serialNumber поле субъекта кодирования отличительного имени, которое часто указывает производителя и тип устройства и может служить для управления правилами выбора подходящей субсхемы адресации для узла или класса узлов.

Регистраторам ACP по умолчанию следует выделять адреса субсхемы Zone с Zone-ID = 0.

Регистраторам ACP, знающим сертификат IDevID устройства-кандидата ACP, следует поддерживать выбор субсхемы Zone или Vlong для узлов ACP на основе атрибута serialNumber [X.520] в поле субъекта кодирования отличительного имени в сертификате IDevID например по идентификатору продукции (Product Identifier или PID), который указывает тип продукции, или полному атрибуту serialNumber. PID, например, может указывать узлы, которые позволяют использовать специализированные агенты ASA, требующие несколько адресов, или неавтономные VM для служб и такие узлы могут получать адреса ACP по схеме Vlong.

В простой схеме выделения регистратор ACP постоянно (даже при перезагрузке) помнит используемый идентификатор Registrar-ID и для каждой субсхемы регистрации (Zone с Zone-ID = 0, Vlong с префиксом /112, Vlong с префиксом /120) — следующее значение Node-Number, доступное для выделения, и увеличивает значение Node-Number при следующем зачислении узла ACP. В этой простой схеме выделения регистратор ACP не будет повторно использовать префиксы адресов ACP от узлов ACP, которые больше не используются.

Если регистратор не может запомнить выделенные адреса, необходимо использовать новое значение поля Register-ID в адресах ACP или определять выделенные адреса ACP по доступности узлов ACP, которая может показывать не все узлы ACP. Неотслеживаемые адреса ACP можно вернуть отзывая или не обновляя сертификаты для них и потом использовать эти адреса в новых сертификатах (например, с новым Registrar-ID). Отметим, что такая стратегия может потребовать координации между регистраторами.

6.11.7.4. Сохранение адреса/префикса

Когда сертификат ACP обновляется или его ключи меняются с EST или иным механизмом, адрес (префикс) ACP в поле acp-node-name должен сохраняться за исключением ситуаций, когда проблемы безопасности или нарушения требования к уникальности адресов существуют или предполагаются регистратором ACP.

Адресную информацию ACP следует поддерживать даже при обновлении или смене ключей регистратор ACP не совпадает с зачислившим ранее сертификат ACP (см., например, 9.2.4. Регистраторы ACP с суб-CA). Адресную информацию ACP следует поддерживать также при завершении срока или отказе сертификата ACP (см. 6.2.5.5. Повторное зачисление и 6.2.5.6. Сертификаты с отказом).

6.11.7.5. Дополнительные детали

В параграфе 9.2. Регистраторы ACP приведены дополнительные сведения о регистраторах ACP — требуемые взаимодействия и параметры, обновление и ограничения сертификатов, применение суб-CA и централизованное управление политикой.

6.12. Маршрутизация в ACP

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

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

Протоколом маршрутизации внутри ACP служит RPL [RFC6550], обоснование выбора приведено в Приложении A.4. Выбор протокола маршрутизации (RPL).

Смежность RPL организуется через каналы ACP в одном домене, включая его субдомены маршрутизации, как описано в Приложении A.6. CA, домены и маршрутные субдомены.

6.12.1. Профиль ACP RPL

Далее описан профиль RPL, который узлы ACP должны поддерживать по умолчанию. Формат описания заимствован из [ROLL-APPLICABILITY].

6.12.1.1. Обзор

Информационный пакет RPL (RPL Packet Information или RPI), описанный в параграфе 11.2 [RFC6550], определяет элементы (artifact), требуемые или полезные при пересылке пакетов, маршрутизируемых протоколом RPL. Этот профиль не использует RPI для большей совместимости с аппаратно ускоренными плоскостями пересылки, которые зачастую не поддерживают заголовки Hop-by-Hop, применяемые для RPI, а также для исключения издержек на заголовки RPI в линии и расходов на их добавление и/или удаление.

6.12.1.1.1. Один экземпляр

Чтобы избежать RPI, профиль ACP RPL использует простую таблицу маршрутизации и пересылки на основе префиксов получателей. Для этого в профиле применяется только один экземпляр RPL instanceID. Этот экземпляр instanceID может содержать лишь граф DODAG8, поэтому таблица маршрутизации и пересылки может учитывать лишь 1 класс обслуживания (best effort в направлении первичного NOC/корня) и не может создавать оптимизированные пути маршрутизации для достижения целей задержки или энергопотребления между любой парой узлов.

Такой выбор является компромиссом. Рассмотрим сеть с несколькими NOC в разных местах. Лишь один из этих NOC станет корнем DODAG. Трафик к другим NOC и от них передаётся через DODAG (дерево кратчайших путей) с корнем в первичном NOC. В зависимости от топологии это может оказаться неоптимальным решением с точки зрения задержки и минимизации ресурсов на сетевом пути, но считается приемлемым с учётом того, что трафик ACP включает «только» пакеты управления и поддержки (см. Приложение A.9.4. Усовершенствование RPL).

Использование одного instanceID/DODAG не создаёт критическую точку отказа, поскольку DODAG перенастраивается при обнаружении отказов пересылки в плоскости данны, включая выбор другого корня при отказе основного.

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

6.12.1.1.2. Повторное схождение

В профилях RPL с пакетами RPI (6.12.1.13. Информационный пакет RPL) эти пакеты также служат для запуска повторного схождения (reconvergence) при ошибочной маршрутизации (например, петли), обнаруживаемой из данных RPI. Это помогает минимизировать сигнальный трафик RPL, особенно в сетях без стабильной топологии и с медленными каналами. Профиль ACP RPL вместо этого полагается на быстрое повторное сведение DODAG за счёт распознавания смены состояния канала (down/up) с использованием сигнализации, описанной в параграфе 6.12.1.7. Ремонт DODAG. Поскольку предполагается, что каналы ACP в основном надежны (или имеют защиту от потерь на канальном уровне) и нет описанного в параграфе 6.12.1.7 «растяжения», петли, вызываемые потерей сигнальных пакетов RPL, скорей всего, будут чрезвычайно редкими.

Кроме того, в RPL возможно множество механизмов предотвращения временных петель, которые рекомендуется применять в профиле ACP RPL — объекты DIO (DODAG Information Object) следует передавать 2 или 3 раза для информирования потомков о потере последнего предка. Метод из параграфа 8.2.2.6 в [RFC6550] (Detaching) следует предпочитать методу из параграфа 8.2.2.5 (Poisoning), поскольку он разрешает локальную связность. Узлам следует выбирать несколько предков (по возможности, не менее 3) и передавать DAO параллельно всем родителям.

Неисправные туннели ACP можно быстро обнаруживать с помощью механизмов протокола защищённого канала, таких как обнаружение «мертвых» партнёров в IKEv2. Это может служить заменой функции LLN ETX9, которая не применяется в этом профиле. Об отказе туннеля ACP следует сразу сообщать плоскости управления RPL для выбора другого родителя.

6.12.1.2. Экземпляры RPL

Применяется единственный экземпляр RPL, по умолчанию установлено RPLInstanceID = 0.

6.12.1.3. Режим с сохранением и без сохранения

Для RPL должен поддерживаться режим (Mode of Operation или MOP) 2, «Сохранение режима операций без поддержки групповой передачи» («Storing Mode of Operations with no multicast support). Реализации могут поддерживать режим 3 «… с поддержкой групповой передачи» (… with multicast support) как надмножество режима 2. Корень указывает режим в потоке DIO.

6.12.1.4. Политика DAO

Политика DAO заключается в энергичной (aggressive), упреждающей (proactive) поддержке состояния DAO.

  • Применяется флаг K в незапрошенном DAO для указания замены предшествующих сведений (для DAO-ACK).

  • Такие сообщения DAO повторяются DAO-RETRIES (3) раз с интервалом DAO-ACK_TIME_OUT (256 мсек).

6.12.1.5. Метрика пути

Применяется счётчик интервалов Hop Count в соответствии с Routing Metrics Used for Path Calculation in Low-Power and Lossy Networks [RFC6551]. Отметим, что счётчик нужен лишь для диагностики и не применяется в Objective Function.

6.12.1.6. Предметная функция

Objective Function (OF)

Применяется Objective Function Zero (OF0) (Objective Function Zero for the Routing Protocol for Low-Power and Lossy Networks (RPL) [RFC6552]). Контейнеры метрики не используются.

rank_factor

Определяется скоростью канала — LOW_SPEED_FACTOR (5) для скорости не выше 100 Мбит/с, иначе HIGH_SPEED_FACTOR (1). Это простое ранжирование каналов на «низкоскоростные» или IoT, которые обычно используют скорость не выше 100 Мбит/с, и «инфраструктурные» со скоростями 1 Гбит/с и выше. С учётом того, что выбор пути в ACP основан лишь на достижимости, а не на оптимизации стоимости, не предпринимается попыток «тонкой настройки» пути.
6.12.1.7. Ремонт DODAG

Глобальный ремонт

Предполагается стабильность каналов и рангов (метрики),поэтому не возникает необходимости в периодическом перестроении DODAG. Версия DODAG инкрементируется лишь при катастрофических событиях (например, по команде администратора).

Локальный ремонт

При обнаружении обрыва канала узел ACP передаёт No-Path DAO для всех целей, которые были доступны через этот канал. При восстановлении канала узел ACP проверяет, предоставляет ли этот канал лучшего предка (родителя). Если это так, узел ACP рассчитывает новый ранг и передаёт новое сообщение DIO с анонсом ранга. Затем он передаёт DAO с новым путём к себе.
При использовании виртуальных интерфейсов ACP с множественным доступом, локальный ремонт может напрямую инициироваться прерыванием связи с партнёром (6.13.5.2.2. Виртуальные интерфейсы ACP с множественным доступом).

stretch_rank

Не предоставляется (не растягивается).

Data-Path Validation

Не используется.

Trickle

Не используется.
6.12.1.8. Групповая передача

Групповая передача ещё не применяется, но может быть использована выбранным режимом работы.

6.12.1.9. Безопасность

Защита RPL [RFC6550] на используется, достаточно защиты ACP. Поскольку каналы ACP уже имеют средства защиты конфиденциальности и целостности, дополнительная защита на уровне RPL была бы избыточной.

6.12.1.10. Коммуникации P2P

Не используются.

6.12.1.11. Настройка адреса IPv6

Каждый узел ACP (узел RPL) анонсирует префикс IPv6, охватывающий адреса, выделенные узлу ACP в AcpNodeName. Размер префикса зависит от субсхемы acp-address — /127 для Zone, /112 или /120 для Vlong (см. параграф 6.11).

Каждый узел ACP должен установить маршрут в «чёрную дыру» (black hole) или null-маршрут, если у него имеется неиспользуемая часть адресного пространства ACP, выделенного ему в AcpNodeName. Это переопределяется более длинными префиксами для интерфейсов в соответствии с фактически используемыми адресами. Например, при наличии у узла адресов ACP-Vlong-8 он устанавливает «черную дыру» /120. Тогда при использовании лишь адреса ACP (первый в диапазоне), например, он установит этот адрес с префиксом /128 на петлевом интерфейсе ACP (6.13.5.1. Петлевые интерфейсы ACP). Ни один из более длинных префиксов не анонсируется в RPL.

Для адресов ACP-Manual на узле ACP, например, в подсетях ACP connect (8.1.1. Контроллер или NMS без поддержки ACP) узел анонсирует префикс подсети /64.

6.12.1.12. Административный параметр

Административное предпочтение (Administrative Preference) (параграф 3.2.6 в [RFC6550], чтобы стать корнем) указывается полем DODAGPreference в сообщении DIO.

      Явно заданный «корень»:  0b100
      Регистратор ACP (по умолчанию):  0b011
      ACP connect (не регистратор):  0b010
      По умолчанию:  0b001
6.12.1.13. Информационный пакет RPL

RPI не требуется в профиле ACP RPL по указанным ниже причинам.

Одной из опций RPI является заголовок заданной источником маршрутизации RPL (Source Routing Header или SRH) (An IPv6 Routing Header for Source Routes with the Routing Protocol for Low-Power and Lossy Networks (RPL) [RFC6554]), который не требуется, поскольку профиль ACP RPL использует режим с сохранением (storing), где каждый узел пересылки (hop) имеет сведения о следующем узле (next-hop) для пересылки.

Упрощённый заголовок RPL Option (The Routing Protocol for Low-Power and Lossy Networks (RPL) Option for Carrying RPL Information in Data-Plane Datagrams [RFC6553]) также не требуется в этом профиле, поскольку применяется 1 экземпляр RPL и проверка пути данных также не производится.

6.12.1.14. Неизвестные получатели

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

Поскольку это требование дополнительно ограничивает функциональность плоскости данных корня RPL, оно не применяется к «обычным» узлам, не настроенным на выполнение специальных функций (т. е. административный параметр из параграфа 6.12.1.12 имеет значение 0b001). Если сеть ACP деградирует до состояния, когда ни один узел не может быть задан корнем, регистратором или узлом ACP connect, возможно, что корень RPL (и ACP в целом) не сможет обнаружить трафик к неизвестным получателям. Однако при отсутствии узлов с административным предпочтением, отличным от 0b001, маловероятна возможность получить диагностические сведения из ACP, поэтому обнаружение трафика к неизвестным получателям в любом случае не будет действенным.

6.13. Общие вопросы ACP

Поскольку каналы по умолчанию организуются между соседями, полученная в результате наложенная сеть использует поэтапное (hop-by-hop) шифрование. Каждый узел расшифровывает входящий трафик ACP и шифрует трафик для своих соседей ACP. Маршрутизация рассмотрена в параграфе 6.12. Маршрутизация в ACP.

6.13.1. Производительность

Этот документ не задаёт требований к производительности реализаций ACP, поскольку они зависят от предполагаемого использования. Ожидается, что полностью автономный узел с широким набором агентов ASA может потребовать высокой производительности пересылки в ACP, например, для телеметрии. Реализации ACP, поддерживающие лишь традиционное применение или стиль SDN, могут выиграть при более низкой производительности ACP, особенно при использовании ACP лишь для критических операций, например, при недоступности плоскости данных. Устройство ACP, заданное этим документом, рассчитано на поддержку широкого спектра вариантов производительности и разрешает программные реализации с потенциально малой производительностью и варианты с высокой производительностью (см. [RFC8368]).

6.13.2. Адресация на защищённых каналах

Для независимости от адресации и маршрутизации плоскости данных в защищённых каналах ACP, найденных GRASP, применяются адреса IPv6 link-local для связи между соседями10.

Чтобы избежать влияния интерфейса и адреса IPv6 (link-local), применяемого для каналов ACP, при настройке плоскости данных, это требуется учитывать при реализации. Если интерфейс IPv6 с адресом link-local используется совместно с плоскостью данных, для него нужно исключить возможность перенастройки или отключения путём настройки конфигурации. Вместо совместного использования интерфейса и адреса IPv6 link-local можно применять отдельный (виртуальный) интерфейс с отдельным адресом IPv6 link-local. Например, интерфейс ACP может работать через отдельный MAC-адрес базового интерфейса L2 (Ethernet). Дополнительные детали и варианты приведены в Приложении A.9.2. Варианты исключения зависимости от плоскости данных IPv6.

Отметим, что другие (не идеальные) реализации могут создавать дополнительные, нежелаемые зависимости от плоскости данных, например, общий код и конфигурация протоколов защищённого канала (IPsec и/или DTLS).

6.13.3. MTU

Значение MTU для защищённых каналов ACP должно задаваться локально на основе MTU базового канала за вычетом издержек на инкапсуляцию в защищённом канале.

Протоколам защищённого канала ACP не требуется определять MTU, поскольку они организуются на основе смежности L2 и значения MTU на обеих сторонах соединения L2 предполагаются согласованными. Расширения ACP, где, например, применяется туннелирование ACP, должны рассмотреть вопрос согласованности MTU. Это проблема туннелей, а не работы ACP через туннель. Транспортные стеки, работающие через ACP, могут применять обычный механизм PMTUD (Path MTU Discovery). Поскольку в ACP надёжность преобладает над производительностью, можно ожидать предпочтения минимального IPv6 MTU (1280 октетов), чтобы избежать ошибок реализации PMTUD и проблем несоответствия MTU на базовых каналах.

6.13.4. Несколько каналов между узлами

Если два узла соединены несколькими каналами, ACP следует организовать через каждый канал, но возможно использование для ACP лишь части каналов. Наличие канала ACP на каждом соединении имеет много преимуществ (например, более быстрое восстановление при отказе соединения) и более точно отражает физическую топологию. Использование части каналов (например, одного) снижает расход ресурсов узла, поскольку для каждого канала ACP нужно сохранять состояние. Схема согласования (6.6. Выбор канала) позволяет решающему узлу (Decider — узел с большим адресом ACP) сбрасывать все каналы ACP кроме желаемых к узлу Follower, а тот не будет пытаться повторить организацию защищённых каналов со своей стороны, пока Decider не появится с неизвестным ранее анонсом GRASP (например, на другом канале или с другим адресом, сообщаемым в GRASP).

6.13.5. Интерфейсы ACP

Концептуально ACP VRF имеет два типа интерфейсов — петлевые (ACP loopback interface), которым назначаются адреса ACP ULA и виртуальные (ACP virtual interface), которые сопоставляются с защищёнными каналами ACP.

6.13.5.1. Петлевые интерфейсы ACP

Для автономных операций ACP, описанных в разделах 6 и 7, узел ACP использует первый адрес из N-битового префикса ACP, выделенного узлу, N = (128 — число битов V в адресе ACP). Этот адрес с префиксом N или больше назначается петлевому (loopback) интерфейсу.

Другие адреса из префикса узел ACP может использовать по своему усмотрению. Автономные операции ACP не требуют дополнительных глобальных адресов IPv6, они могут применяться для агентов ASA и неавтономных функций. Компоненты ACP, которые не полностью автономны, такие как интерфейсы ACP (Рисунок 14), также могут вводить дополнительные глобальные адреса IPv6 на других типах интерфейсов в ACP.

Применение петлевых интерфейсов для глобальных адресов является обычной практикой для маршрутизаторов, например, в соединениях внутреннего BGP (Internal BGP или IBGP) с BGP4 (A Border Gateway Protocol 4 (BGP-4) [RFC1654]) или более ранними версиями протокола. ACP принимает и автоматизирует эту практику.

Петлевой интерфейс для описанного выше применения в ACP — это интерфейс, поведение которого соответствует разделу 4 (второй абзац) Default Address Selection for Internet Protocol Version 6 (IPv6)» [RFC6724]. Пакеты, переданные хостом узла с петлевого интерфейса ведут себя, как будто они «закольцованы» интерфейсом, т. е. они выглядят как переданные loopback-интерфейсом, затем принятые узлом и переданные в направлении адресата. Термин loopback only указывает такое поведение, а не фактическое название типа интерфейса, выбранного в фактической реализации. Петлевым интерфейсом для использования с ACP может быть виртуальной и/или программной конструкцией, не связанной с оборудованием, или аппаратным интерфейсом, работающим в петлевом режиме (loopback mode). Петлевому интерфейсу, используемому для ACP, недопустимо иметь соединения с другими узлами.

Ниже приведён список причин выбора loopback-адресов для ACP, основанный на архитектуре адресации IPv6 и общих проблемах.

  1. Адреса IPv6 назначаются интерфейсам, а не узлам. IPv6 следует модели IPv4 в том, что префикс подсети связывается с одним каналом, см. параграф 2.1 в IP Version 6 Addressing Architecture [RFC4291].

  2. Реализации IPv6 обычно не позволяют назначать один глобальный адрес IPv6 нескольким интерфейсам в одном экземпляре VRF.

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

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

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

  6. Даже при поддержке приложением нескольких адресов партнёра, оно может использовать лишь один адрес в каждый момент для соединения с наиболее распространёнными транспортными протоколами TCP и UDP. Хотя в TCP Extensions for Multipath Operation with Multiple Addresses [RFC6824]/[RFC8684] эта проблема решена, это может быть недостаточно широко реализовано службами OAM в маршрутизаторах.

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

  8. Использовать глобальные адреса для подсетей между узлами не требуется, если эти подсети лишь соединяют маршрутизаторы (как защищённые каналы ACP), поскольку они могут взаимодействовать с удалёнными узлами через свои глобальные loopback-адреса. Поэтому назначение глобальных адресов для этих внешних подсетей расточительно для адресного пространства, а также без нужды увеличивает размер таблиц маршрутизации и пересылки, что крайне нежелательно, особенно для ACP, поскольку здесь требуется минимизировать на уровне узла издержки ACP VRF.

  9. По этим причинам субсхемы адресации ACP не рассматривают адреса ACP для подсетей, соединяющих узлы ACP.

Отметим, что в Segment Routing Architecture [RFC8402] введён термин Node-SID для указания сегментов префикса IGP, идентифицирующих конкретный маршрутизатор, например, на loopback-интерфейсе. Префикс петлевого адреса ACP можно по аналогии называть идентификатором узла ACP (ACP Node Identifier).

6.13.5.2. Виртуальные интерфейсы ACP

Любая защищённая связь ACP с другим узлом ACP сопоставляется с виртуальным интерфейсом одним из описанных ниже способов. Это не зависит от выбранного протокола защиты (IPsec, DTLS, иной стандартный или нестандартный протокол).

Отметим, что все приведённые здесь соображения предполагают защищённые связи «точка-точка». Отображения множественных защищённых связей, такие как The Group Domain of Interpretation [RFC6407], выходят за рамки документа.

6.13.5.2.1. Виртуальные интерфейсы ACP «точка-точка»

В этом варианте каждый защищённый канал ACP отображается на свой виртуальный интерфейс «точка-точка». Если физическая подсеть имеет более двух узлов с поддержкой ACP (в одном домене), такой подход к реализации ведёт к полносвязной (full mesh) сети виртуальных интерфейсов ACP между узлами.

Когда протокол защищённого канала видит, что партнёр не работает, ему следует сообщить о разрыве связи для запуска восстановления RPL DODAG (6.12.1.7. Ремонт DODAG).

6.13.5.2.2. Виртуальные интерфейсы ACP с множественным доступом

При более совершенном подходе ACP создаёт один виртуальный интерфейс ACP с множественным доступом для всех защищённых каналов ACP к поддерживающим ACP узлам, доступным через одну базовую (физическую) подсеть. Групповые пакеты IPv6 link-local, переданные на виртуальный интерфейс ACP с множественным доступом, реплицируются в каждый защищённый канал ACP, сопоставленный с этим интерфейсом. Индивидуальный пакет IPv6, направленный на виртуальный интерфейс ACP с множественным доступом, передаётся в защищённый канал ACP, относящийся к соседу ACP, который является next hop в таблице пересылки ACP, используемой для адресата пакета.

Когда протокол защищённого канала видит, что партнёр по защищённому каналу, отображенному на виртуальный интерфейс ACP с множественным доступом, не работает, ему следует сообщить о разрыве связи для запуска восстановления RPL DODAG (6.12.1.7. Ремонт DODAG).

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

Узлы ACP должны выполнять стандартные операции IPv6 через виртуальные интерфейсы ACP, включая SLAAC [RFC4862] для назначения адреса IPv6 link-local виртуальному интерфейсу ACP и ND (Neighbor Discovery for IP version 6 (IPv6) [RFC4861]) для определения адреса IPv6 link-local сопоставленного с защищённым каналом ACP, отображённым на виртуальный интерфейс ACP. Это не зависит от типа виртуального интерфейса ACP.

Рекомендуется применять оптимистическое обнаружение дубликатов адресов (Optimistic Duplicate Address Detection или DAD) в соответствии с Optimistic Duplicate Address Detection (DAD) for IPv6 [RFC4429], поскольку вероятность дубликатов между узлами ACP крайне мала, поскольку адрес может формироваться из глобально уникального идентификатора, назначенного локально (например, EUI-48 или EUI-64, см. ниже).

Узлы ACP могут снижать число групповых пакетов IPv6 link-local от ND за счёт определения адреса IPv6 link-local для соседа по защищённому каналу ACP из других источников, таких как адрес отправителя в групповых сообщениях RPL, с отказом от передачи сообщений Neighbor Solicitation.

Адрес IPv6 link-local виртуального интерфейса ACP можно вывести из подходящего локального источника, например адреса EUI-48 или EUI-64 на узле. Недопустима зависимость этого от чего-либо, что может подвергнуться атаке из плоскости данных, например, от адреса IPv6 link-local базового физического интерфейса, который может быть атакован через SLAAC, или параметров заголовка инкапсуляции защищённого канала, которые не защищены.

Адрес канального уровня для виртуального интерфейса ACP — это адрес, применяемый для базового интерфейса, через который организован защищённый туннель (обычно адрес Ethernet). Поскольку индивидуальные пакеты IPv6, отправляемые виртуальному интерфейсу ACP, передаются не по адресу получателя на канальном уровне, в в защищённый канал ACP, поле адреса канального уровня следует игнорировать при получении, запоминая вместо него защищённый канал ACP из которого было получено сообщение.

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

Следует также сравнивать виртуальные интерфейсы «точка-точка» и с множественным доступом в плане эффективности лавинной рассылки групповых сообщений link-local.

Рассмотрим ЛВС с 3 соседями — Алиса, Боб и Кэрол. Пусть ACP GRASP Алисы хочет передать групповое сообщение GRASP link-local Бобу и Кэрол. Если ACP у Алисы эмулирует ЛВС как виртуальные интерфейсы «точка-точка» (один для Боба, второй для Кэрол), ACP GRASP Алисы будет передавать две копии групповых сообщения GRASP — одну Бобу, другую Кэрол. Если ACP Алисы эмулирует ЛВС как многоточечный виртуальный интерфейс, ACP GRASP Алисы будет передавать этому интерфейсу 1 пакет, а многоточечный виртуальный интерфейс ACP будет реплицировать пакет в каждый защищённый канал (Бобу и Кэрол). Результат в обоих случаях одинаков. Различие возникает, когда Боб и Кэрол получают пакеты. Если они используют виртуальные интерфейсы ACP «точка-точка», их экземпляр GRASP будет пересылать пакет от Алисы друг другу как часть процедуры лавинной рассылки GRASP. Эти пакеты не нужны и будут отброшены GRASP при получении как дубликаты (по GRASP Session ID). Если же ACP Боба и Кэрол эмулируют виртуальный интерфейс с множественным доступом, дублирования не будет, поскольку процедура лавинной рассылки GRASP не реплицирует пакеты в интерфейс, откуда пакет принят.

Отметим, что групповые сообщения GRASP link-local не передаются напрямую как групповые сообщения IPv6 link-local UDP виртуальным интерфейсам ACP, а вместо этого передаются виртуальным интерфейсам ACP GRASP, которые размещаются над виртуальными интерфейсами ACP для добавления надёжности TCP групповым сообщениям GRASP link-local. Тем не менее, эти виртуальные интерфейсы ACP GRASP выполняют такую же репликацию сообщений и так же влияют на лавинную рассылку (6.9.2. ACP как защищённая транспортная подложка для GRASP).

RPL поддерживает операции и корректное построение таблиц маршрутизации в подсетях с множественным доступом без широковещания (non-broadcast multi-access или NBMA). Такие системы широко применяются для радиодоступа. При использовании подсетей NBMA недопустимо представлять их виртуальными интерфейсами ACP с множественным доступом, поскольку реплики групповых сообщений IPv6 link-local не будут доставлены всем соседям в сети NBMA, что приведёт к отказу лавинной рассылки сообщений GRASP. Взамен каждый защищённый канал ACP с таким интерфейсом должен представляться как виртуальный интерфейс ACP «точка-точка» (A.9.4. Усовершенствование RPL).

Нужно соблюдать осторожность при создании виртуальных интерфейсов ACP с множественным доступом для защищённых каналов ACP между узлами ACP в разных доменах или субдоменах маршрутизации. Например, если будущие междоменные правила ACP определить как «одноранговые» (peer-to-peer) это упростит создание виртуальных интерфейсов ACP «точка-точка» для таких междоменных защищённых каналов.

7. Поддержка ACP на коммутаторах и портах L2 (нормативный)

7.1. Зачем? (преимущества ACP на коммутаторах L2)

ANrtr1 ------ ANswitch1 --- ANswitch2 ------- ANrtr2
          .../   \                   \  ...
ANrtrM ------     \                   ------- ANrtrN
                   ANswitchM ...

Рисунок 13. Топология с коммутаторами L2 ACP.


Рассмотрим большую ЛВС L2 с маршрутизаторами ANrtr1 — AnrtrN, соединёнными через некую топологию коммутаторов L2. Примерами могут служить сети больших организаций с ядром L2, сети IoT или широкополосные сети агрегирования, где часто применяется многоуровневая топология с коммутацией L2.

Если используемый в ACP протокол обнаружения работает на уровне подсети, каждый маршрутизатор ACP будет видеть все прочие маршрутизаторы ACP в ЛВС как соседей и образуется полносвязная (full mesh) сеть каналов ACP. Если все или часть коммутаторов AN автономны и применяют тот же протокол обнаружения, они также войдут в полносвязную сеть.

Полная связность соединений ACP может создавать проблемы для расширения. Число защищённых связей в протоколах защищённых каналов вряд ли сможет произвольно увеличиваться, особенно при использовании аппаратного ускорения операций шифрования и расшифровки. Другие операции ACP (такие как маршрутизация) также потребуют расширения с ростом числа прямых соседей ACP. Маршрутизатора ACP с 4 физическими интерфейсами достаточно в ЛВС с сотнями соседей, подключённых через коммутаторы. Введение такого нового, непредсказуемого фактора масштабирования усложняет поддержку ACP на произвольных платформах в произвольных средах.

Можно легко обеспечить предсказуемые требования к росту числа соседей ACP, если в аналогичной топологии коммутаторы L2 с поддержкой ACP могут ограничить рассылку сообщений обнаружения, чтобы маршрутизаторы и коммутаторы ACP находили лишь физически подключённые коммутаторы ACP L2 в качестве кандидатов в соседи ACP. При наличии такого механизма обнаружения ACP и защищённые связи будут расширяться пропорционально числу физических интерфейсов, а не числу потенциальных соседей, «подключённых к ЛВС», и топология ACP будет соответствовать физической топологии, что иногда может быть полезно для операций управления или ASA.

Пусть в приведённом выше примере ANswitch1 и ANswitchM поддерживают ACP, а ANswitch2 не поддерживает. Желаемая топология ACP будет получаться при наличии у ANrtr1 и ANrtrM соединения ACP лишь с ANswitch1 и полносвязных соединениях ACP между ANswitch1, ANrtr2 и AnrtrN. ANswitch1 также имеет соединения ACP с ANswitchM, а ANswitchM — с кем-либо, расположенным за ним.

7.2. Как? (на уровне порта L2 DULL GRASP)

Для поддержки ACP на коммутаторах L2 или коммутирующих портах L2 устройства L3, необходимо, чтобы эти порты L2 для реализации ACP выглядели как интерфейсы L3. В первую очередь это связано с созданием отдельного экземпляра/домена DULL GRASP для каждого такого порта L2. Поскольку GRASP имеет выделенный групповой адрес IPv6 link-local (ALL_GRASP_NEIGHBORS), этого достаточно, чтобы все пакеты для этого адреса извлекались на уровне порта и передавались данному экземпляру DULL GRASP. Аналогично, групповые пакеты IPv6 link-local, переданные экземпляром DULL GRASP, должны отправляться лишь в на порт L2 для этого экземпляра DULL GRASP (вместо лавинной рассылки через все порты VLAN, к которой относится порт).

Когда порты/интерфейсы, через которые предполагается работа ACP в понимающем ACP коммутаторе L2 или маршрутизирующем устройстве L2/L3, являются портами моста L2, пакеты на адрес ALL_GRASP_NEIGHBORS недопустимо передавать между ними. При использовании отслеживания MLD, ему должна быть запрещена передача через мост (bridging) пакетов для группового адреса IPv6 ALL_GRASP_NEIGHBORS.

На гибридных коммутаторах L2/L3 одному интерфейсу L3 VLAN назначается множество портов L2. С упомянутыми выше расширениями для DULL GRASP плоскость ACP может просто работать на интерфейсах L3 VLAN, поэтому не требуется дополнительной (аппаратной) пересылки для работы ACP на портах L2. Это обеспечивается тем, что протоколы защищённых каналов ACP используют лишь индивидуальные пакеты IPv6 link-local и эти пакеты будут передаваться корректному порту L2 в направлении партнёра логикой VLAN на устройстве.

Этого достаточно при организации виртуальных интерфейсов ACP P2P для каждого партнёра ACP. Когда желательно создать виртуальные интерфейсы ACP с множественным доступом (параграф 6.13.5.2.2), требуется объединять не все защищённые каналы ACP на одном интерфейсе L3 VLAN, а только каналы на одном порту L2.

При использовании тегов VLAN описанная выше логика применяется лишь к пакетам GRASP без тегов. Для обнаружения соседей ACP через GRASP следует принимать и передавать пакеты без тегов VLAN. В гибридных коммутаторах L2/L3, каждая сеть VLAN будет создавать смежности ACP лишь через порты, где нет тегов VLAN.

В результате простая логика заключается в том, что защищённые каналы ACP будут работать через те же интерфейсы L3, которые имеются в плоской сети с мостами (bridged) через все маршрутизаторы, но полной связности каналов ACP не возникает и соседями становятся лишь узлы ACP, подключённые по защищённым каналам через порт L2, поскольку работа DULL GRASP разделена по портам.

Например, на рисунке 13 ANswitch1 может запустить отдельные экземпляры DULL GRASP на портах к ANrtr1, ANswitch2 и AnswitchI, даже если эти три порта в плоскости данных будут в той же сети VLAN (ЛВС) и выполнять коммутацию L2 между этими портами. ANswitch1 будет выполнять между этими портами маршрутизацию ACP L3.

Описание в предыдущем абзаце специально предназначено для иллюстрации того, что на гибридных устройствах L3/L2, распространённых в корпоративных сетях, IoT и широкополосном агрегировании извлечение пакета GRASP происходит лишь 1 раз (по адресу Ethernet), равно как вставка группового пакета GRASP link-local на порт L2, которая работает с портами L2 на уровне аппаратной пересылки. Остальные операции относятся полностью к плоскости управления ACP и организации защищённых каналов через интерфейс L3. Предполагается, что это упростит поддержку ACP на уровне портов L2 в таких гибридных устройствах.

В устройства без смешения портов/интерфейсов L2 и интерфейсов L3 (для завершения транспортных соединений) детали реализации могут отличаться. Логичней и проще рассматривать и использовать каждый порт L2 как отдельную подсеть L3 для всех операций ACP. Тот факт, что для ACP нужна лишь групповая и индивидуальная передача IPv6 link-local, должен максимально упростить поддержку ACP на устройствах L2 любого типа.

Общей проблемой ACP в сетях с коммутацией L2 является взаимодействие с протоколом связующего дерева (Spanning Tree Protocol или STP). Без дополнительного усовершенствования L2 плоскость ACP будет работать лишь через активную топологию STP и при изменении дерева работа ACP будет прерываться с повторным схождением. В идеале партнёрство ACP следует организовывать лишь через порты, которые заблокированы в STP, чтобы работа ACP не зависела от STP и могла продолжаться при изменении топологии STP, когда повторное схождение может быть достаточно долгим. Описанных выше простых вариантов для этого недостаточно.

8. Поддержка элементов, не понимающих ACP (нормативный раздел)

8.1. ACP Connect

8.1.1. Контроллер или NMS без поддержки ACP

ACP может применяться системами управления, такими как контроллеры или хосты NMS, для подключения к устройствам (или иным типам узлов). Для этого хосту NMS нужен доступ в ACP. Плоскость ACP — это наложенная сеть с самозащитой, по умолчанию предоставляющая доступ лишь доверенным автономным системам. Поэтому традиционные (не ACP) не имеют по умолчанию NMS доступа в ACP, как и другие внешние узлы.

Если хост NMS не является автономным, т. е. не поддерживает автономного согласования ACP, его можно ввести в ACP путём явной настройки. Для поддержки соединений со смежными устройствами, не являющимися узлами ACP, узлу ACP следует поддерживать ACP connect (иногда называется автономным соединением autonomic connect).

ACP connect — это настроенный на уровне интерфейса обход для подключения доверенных узлов, не относящихся к ACP. Узел ACP, на котором настраивается ACP connect, называется краевым узлом ACP. Через ACP connect плоскость ACP становится доступной для узлов не-ACP (таких, как системы NOC) без поддержки на нихх обнаружения или организации защищённых каналов ACP. Это называют естественным (native) доступом в ACP, поскольку для систем NOC интерфейс выглядит как обычный сетевой интерфейс без защищённого канала ACP, инкапсулирующего трафик.

                    «Естественная» плоскость данных (без ACP)
                                          .
+--------+       +----------------+       .        +-------------+
| Узел   |       |Краевой узел ACP|       .        |             |
| ACP    |       |                |       v        |             |
|        |-------|...[ACP VRF]....+----------------|             |+
|        |   ^   |.               |                |Устройст. NOC||
|        |   .   | .[Data Plane]..+----------------| «хосты NMS» ||
|        |   .   |  [          ]  | .         ^    |             ||
+--------+   .   +----------------+  .        .    +-------------+|
             .                        .       .     +-------------+
             .                        .       .
  «Естественная» плоскость данных     .   «Естественная» (без шифрования)
    + ACP с автосогласованием         .   «подсеть ACP connect»
      и шифрованием                   .
                                    Интерфейс ACP connect 
                                    например, «VRF ACP native» (config)

Рисунок 14. ACP Connect.


ACP connect влияет на безопасности, все системы и процессы, подключённые через ACP connect, получают доступ ко всем узлам ACP в плоскости ACP без дополнительной аутентификации. Таким образом, интерфейс ACP connect и подключённые к нему системы NOC должны контролироваться или защищаться физически. По этой причине описанные здесь механизмы явно не включают опций, позволяющих подключить маршрутизатор не-ACP через интерфейс ACP с маршрутизацией внутрь ACP.

Наличие физического контроля и/или защиты означает, что злоумышленники не могут получить доступ к физическому устройству, поддерживающему граничный узел ACP, физическим интерфейсам и каналам ACP, а также физическим устройствам, поддерживающим NOC. В простом случае граничный узел ACP и устройство NOC размещаются в помещении с контролируемым доступом, таком как NOC, куда злоумышленники попасть не могут.

Интерфейс ACP обеспечивает исключительный доступ только к плоскости ACP. Этого может быть недостаточно для многих хостов NMS. Им потребуется второй интерфейс «плоскости данных» вне ACP для связи между хостом NMS и администраторами, службами Internet или для прямого доступа к плоскости данных. В документе Using Autonomic Control Plane for Stable Connectivity of Network OAM [RFC8368] более подробно рассмотрены способы интеграции ACP в смешанную среду NOC.

На интерфейсе ACP connect следует использовать адрес/префикс IPv6 из субсхемы Manual (6.11.4. Субсхема ручной адресации ACP (ACP-Manual)), позволяющий оператору настроить, например, лишь Subnet-ID и автоматически получить оставшуюся часть адреса/префикса. Не следует использовать префикс, который маршрутизируется за пределы ACP, чтобы адреса чётко указывали, используются ли они внутри ACP.

Префикс ACP connect для подсетей должен распространяться краевым узлом ACP в протокол маршрутизации ACP (RPL). Хост NMS должен подключаться к префиксам из таблицы маршрутизации ACP через интерфейс ACP connect. В простом случае, где ACP использует лишь 1 префикс ULA и все подсети ACP имеют охватываемые им префиксы, хост NMS может полагаться на [RFC6724] для определения маршрутов с наибольшим совпадением префикса к разным своим интерфейсам, ACP и плоскости данных. С [RFC6724] хост NMS будет выбирать интерфейс ACP connect для всех адресов из ACP, поскольку любые адресаты в ACP будут давать максимальное совпадение с адресом интерфейса ACP. Если интерфейс ACP connect хоста NMS использует иной префикс или в ACP применяется несколько префиксов ULA, хосту NMS потребуются (статические) маршруты к интерфейсам ACP для этих префиксов.

Когда краевой узел ACP получает пакет от интерфейса ACP connect, он должен пересылать пакет в ACP лишь при наличии в нем адреса отправителя IPv6 от этого интерфейса (это иногда называют пересылкой по обратному пути -Reverse Path Forwarding или RPF). Это правило фильтрации можно изменить административно. Расширение доступности узлов не-ACP таким способом может создавать проблемы безопасности для ACP.

Для ограничения влияния ACP connect на безопасность поддерживающим такой интерфейс узлам следует реализовать механизм защиты, позволяющий настраивать и/или использовать интерфейсы ACP лишь на узлах, явно предназначенных для такого развёртывания (физически защищённые места, такие как NOC). Например, регистратор может запретить возможность включения ACP connect на устройствах в процессе зачисления и это можно будет изменить лишь при повторном зачислении (A.9.5. Назначение роли).

Граничным узлам ACP следует иметь опцию настройки для запрета пакетов с заголовками RPI (6.12.1.13. Информационный пакет RPL) через интерфейс ACP connect. Эти заголовки выходят за рамки профиля RPL в данной спецификации, но могут применяться в будущих расширениях.

8.1.2. Программные компоненты

В предыдущем параграфе предполагалось, что краевой узел ACP и устройства NOC являются разными физическими устройствами, а интерфейс ACP является физическим сетевым соединением. Здесь рассматривается случай, когда эти компоненты являются программами на одном физическом устройстве.

Механизм ACP connect может служить для соединения ACP не только с внешними физическими системами (хосты NMS), но и с приложениями, контейнерами, виртуальными машинами. На практике одним из возможных путей решения проблем безопасности внешнего интерфейса ACP connect является совместное размещение краевого узла ACP и хоста NMS, сделав один контейнером или виртуальной машиной внутри другого. В этом случае незащищённая внешняя подсеть ACP становится внутренней виртуальной подсетью на том же устройстве. В конечном итоге это ведёт к созданию хоста NMS с полной поддержкой ACP при минимальном воздействии на программную архитектуру хоста NMS. Такой подход не ограничивается хостами NMS и может также применяться к устройствам, содержащим одну или несколько виртуальных сетевых функций (VNF), — внутренней виртуальной подсети, соединяющей out-of-band-интерфейсы VNF с краевым маршрутизатором ACP (VNF).

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

Такое «внутреннее» применение ACP connect не следует считать обходом, поскольку в этом случае можно организовать корректную модель безопасности — не требуется полагаться на непроверяемые внешние механизмы защиты, как в случае с внешними хостами NMS. Вместо этого может выполняться организация (оркестровка) ACP, виртуальных подсетей и программных компонентов доверенными программами, которые можно считать частью ANI (или даже расширенной ACP). Эти программные компоненты отвечают за обеспечение доступа к виртуальной подсети лишь доверенных программных компонентов, а к виртуальной подсети ACP и плоскости данных — ещё более доверенные (поскольку через них возможны утечки между ACP и плоскостью данных). Такое доверие можно организовать, например, в помощью криптографии, такой как подписи программных пакетов.

8.1.3. Автонастройка

Краевым узлам ACP, хостам NMS и программным компонентам, предназначенным, как описано выше, для соединения через виртуальные интерфейсы, следует поддерживать SLAAC [RFC4862] в подсети ACP connect и автоматическую настройку маршрутов в соответствии с Default Router Preferences and More-Specific Routes [RFC4191].

Краевой узел ACP действует как маршрутизатор для ACP в подсети ACP connect, предоставляя настраиваемый (автоматически) префикс для подсети ACP connect и создаваемые (автоматически) маршруты из ACP к хостам NMS и/или программным компонентам. Краевой узел ACP использует опцию маршрутной информации (Route Information Option или RIO) из [RFC4191] для анонсирования агрегированных префиксов для адресных префиксов ACP (с номинальными сроками действия RIO). Кроме того, краевой узел ACP применяет RIO для анонсирования принятого по умолчанию маршрута (::/0) со сроком действия 0.

Эти RIO позволяют подключать хосты типа C с ACP через подсеть ACP connect на одном интерфейсе и другую сеть (плоскость данных или сеть NMS) на том же или другом интерфейсе хоста типа C, полагаясь на маршрутизаторы, отличные от краевого узла ACP. RIO гарантируют, что эти хосты будут маршрутизировать краевому ACP узлу лишь префиксы, применяемые в ACP.

Хосты типа A и B игнорируют RIO и будут считать узел ACP своим маршрутизатором по умолчанию для всех адресатов. Этого достаточно, когда хосту типа A или B нужно лишь соединение с ACP, но не с другими сетями. Подключение хоста типа A или B к ACP и другим сетям требует явной настройки маршрута для префикса ACP на хосте или комбинированном интерфейсе ACP и плоскости данных на краевом узле ACP (8.1.4. Комбинированный интерфейс ACP и плоскости данных (VRF Select)).

Агрегированный префикс означает, что краевому узлу ACP нужно анонсировать лишь префикс ULA /48, используемый в ACP, а не фактические маршруты /64 (сбсхема Manual), /127 (субсхема Zone), /112 мом /120 (субсхема Vlong ) реальных узлов ACP. Если интерфейсы ACP настроены с отличными от ULA префиксами, эти префиксы невозможно агрегировать без дополнительной настройки политики на краевом узле ACP. Это объясняет приведённую выше рекомендацию применять префиксы ACP ULA для интерфейсов ACP connect для сокращения списка префиксов, анонсируемых через [RFC4191] хостам NMS и программным компонентам.

Краевой узел ACP с адресом ACP Vlong может выделять подсети из скоего префикса /112 или /120 интерфесам ACP connect для исключения необходимости неавтономной настройки и/или предоставления адресных префиксом таким интерфейсам ACP connect.

8.1.4. Комбинированный интерфейс ACP и плоскости данных (VRF Select)

Использование двух физических и/или виртуальных подсетей (и интерфейсов) для хостов NMS (8.1.1. Контроллер или NMS без поддержки ACP) или программ (8.1.2. Программные компоненты) может казаться усложнённым, например, с унаследованными хостами NMS, поддерживающими лишь 1 интерфейс IP, или недостаточным для поддержки хостов типа A или B [RFC4191] (8.1.3. Автонастройка).

Для обеспечения единой подсети ACP и плоскости данных узлу ACP требуется демультиплексировать пакеты от хостов NMS в ACP VRF и плоскость данных. Это иногда называют выбором VRF (VRF select). Если адреса ACP VRF не перекрываются с адресами IPv6 в плоскости данных (перекрытия следует избегать), эта функция может использовать адрес получателя IPv6. Проблема состоит в выборе адреса источника на хостах NMS в соответствии с [RFC6724].

                        Комбинированный интерфейс ACP и плоскости данных
                                                .
     +--------+       +--------------------+    .   +--------------+
     | Узел   |       |ACP Edge No         |    .   | Хосты NMS    |
     | ACP    |       |                    |    .   | / Программы  |
     |        |       |  [ACP  ].          |    .   |              |+
     |        |       | .[VRF  ] .[VRF   ] |    v   | «Адрес ACP»  ||
     |        +-------+.         .[Select].+--------+ "Адреса      ||
     |        |   ^   | .[Data ].          |        |  плоскости   ||
     |        |   .   |  [Plane]           |        |  данных»     ||
     |        |   .   |  [     ]           |        +--------------+|
     +--------+   .   +--------------------+         +--------------+
                  .
«Естественная» плоскость данных + ACP с автосогласованием и шифрованием

Рисунок 15. VRF Select.


Рассмотрим простой случай, где ACP использует лишь 1 префикс ULA, а префикс ACP IPv6 для комбинированного интерфейса ACP и плоскости данных охватывается этим префиксом ULA. Краевой узел ACP анонсирует префикс ACP IPv6 и 1 или несколько префиксов для плоскости данных. Без дополнительной настройки правил на хостах NMS, они могут выбрать свои адреса ACP как адреса отправителя для получателей ULA в плоскости данных в соответствии с правилом 8 (раздел 5 в [RFC6724]). Краевой узел ACP может передать пакет плоскости данных, но адрес отправителя из ACP не следует применять для плоскости данных и обратные пакеты могут не прийти. Если ACP передаёт несколько префиксов ULA или не являющийся ULA префикс ACP, выбор адреса отправителя становится более проблематичным.

С раздельными подсетями ACP connect и плоскости данных, а также анонсами префиксов [RFC4191], которые маршрутизируются через интерфейс ACP будет применяться выбор адреса отправителя по правилу 5 (адрес выходного интерфейса) из раздела 5 в [RFC6724], чтобы указанные выше проблемы не возникали даже в более сложных случаях множества префиксов ULA и других (не-ULA) префиксов в таблице маршрутизации ACP.

Чтобы достичь такого же поведения с комбинированным интерфейсом ACP connect и плоскости данных, краевой узел ACP должен вести себя как два отдельных маршрутизатора на интерфейсе — один (маршрутизатор/адрес) IPv6 link-local для достижимости ACP, другой — для достижимости плоскости данных. Анонсы маршрутизаторов (Router Advertisement или RA) для обоих описаны в параграфе 8.1.3 — для ACP анонсируется префикс ACP с опцией префикса [RFC4191], маршрутизируемой через ACP, и нулевым сроком действия для отмены этого next hop как принятого по умолчанию маршрутизатора. Для плоскости данных анонсируются префиксы вместе с параметрами принятого по умолчанию маршрутизатора плоскости данных.

В результате выбор адреса источника по правилу 5.5 из раздела 5 в [RFC6724] может приводить к корректному поведению выбора адреса источника хостами NMS без дополнительной настройки, что и при отдельных интерфейсах ACP connect и плоскости данных на хосте. Как указано в правиле 5.5 из раздела 5 в [RFC6724], это может происходить лишь потому, что от хостов IPv6 не требуется отслеживать информацию next-hop. Если хост NMS не делает этого, предпочтительным методом подключения будут раздельные интерфейсы ACP connect и плоскости данных. Хостам, реализующим First-Hop Router Selection by Hosts in a Multi-Prefix Network [RFC8028], следует (вместо может) реализовать правило 5.5 из раздела 5 в [RFC6724], поэтому для хостов предпочтительно поддерживать [RFC8028].

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

8.1.5. Использование GRASP

GRASP можно и следует применять на интерфейсах ACP connect, особенно в архитектурно корректных решениях, когда протокол служит для подключения программ (например, ASA или унаследованных приложений NMS) к ACP.

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

Различия в безопасности заключаются в том, что криптографическая защита каналов ACP заменяется требованием физической защиты и/или контроля сетевых соединений между краевым узлом ACP и NMS или другим хостом, доступным через интерфейс ACP (см. 8.1.1. Контроллер или NMS без поддержки ACP).

При использовании комбинированного интерфейса ACP и плоскости данных, нужно следить, чтобы краевые узлы ACP пересылали лишь сообщения GRASP, принятые от программ или хостов NMS и предназначенные для домена ACP GRASP. В настоящее время не определено подложки для защиты и транспорта GRASP помимо ACP, поэтому не задано, какие программы и хосты NMS могут участвовать в двух разных доменах GRASP через одну подсеть (домены ACP и плоскости данных). Сейчас предполагается, что все пакеты GRASP на комбинированном интерфейсе ACP и плоскости данных относятся к домену GRASP ACP. В них следует использовать адреса ACP IPv6 для программ и хостов NMS. Адреса IPv6 link-local программ и хостов NMS (для сообщений GRASP M_DISCOVERY и M_FLOOD) предполагаются относящимися к пространству адресов ACP.

8.2. Соединение островков ACP через сети L3 без ACP (удалённые соседи)

Не все узлы в сети могут поддерживать ACP. Если между узлами ACP имеются устройства L2, не поддерживающие ACP, плоскость ACP будет работать через них, поскольку она основана на IP. Однако автономное обнаружение соседей ACP через DULL GRASP предназначено лишь для работы через соединения L2, а этого недостаточно для создания соединений ACP через устройства L3 без поддержки ACP.

8.2.1. Настроенный удалённый сосед ACP

На узле ACP удалённые соседи задаются явно. Параметры такого «соединения» показаны ниже в форме ABNF. Синтаксис не является нормативным (нет стандарта для настройки) лишь иллюстрирует параметры, указывая необязательные.

     connection = method "," local-addr "," remote-addr [ "," pmtu ]
     method =    "any"
                / ( "IKEv2" [ ":" port ] )
                / (  "DTLS"  [ ":"  port ] )
     port = 1*DIGIT
     local-addr  = [ address  [ ":" vrf  ] ]
     remote-addr =   address
     address =  "any"
                / IPv4address / IPv6address  ; Из [RFC5954]
     vrf = system-dependent ; Имя VRF для локального адреса

Рисунок 16. Параметры для удалённых соседей ACP.

Явная настройка удалённого партнёра в соответствии ABNF обеспечивает все сведения для организации защищённого канала без организации туннеля к партнёру и запуска DULL GRASP в нем. Конфигурация включает все параметры, которые иначе пришлось бы передавать через DULL GRASP — локальный адрес, удалённый (партнерский) локатор и метод. Отличия от локального обнаружения через DULL GRASP перечислены ниже.

  • Адреса могут быть IPv4 или IPv6 и обычно являются глобальными динамическими адресами.

  • Можно указать VRF (где находится local-addr) для организации соединения. Если параметр vrf не задан, предполагается принятый по умолчанию экземпляр VRF на узле. В DULL GRASP под VRF подразумевается интерфейс, через который работает DULL GRASP.

  • Если для локального адреса задано значение any, используемый при организации безопасного канала локальный адрес определяется выбором адреса источника ([RFC6724] для IPv6). На стороне ответчика прослушиваются все адреса узла в выбранном экземпляре VRF.

  • Указание порта нужно лишь для методов, где порт не задан по умолчанию (например, DTLS).

  • Если для удалённого адреса задано значение any, соединение будет лишь ответчиком. Это концентратор (hub), который может использоваться несколькими удалёнными партнёрами для одновременного соединения без необходимости знать и настраивать адреса. Примером служит сайт-хаб для сайтов-лучей, доступных через Internet.

  • Параметр pmtu следует делать настраиваемым, чтобы преодолеть проблемы и ограничения определения MTU для пути (Path MTU Discovery или PMTUD).

  • IKEv2/IPsec для удалённых партнёров следует поддерживать необязательные процедуры для работы через NAT (NAT Traversal или NAT-T).

8.2.2. Туннельный удалённый сосед ACP

Между удалёнными партнёрами ACP задаётся имеющийся туннель IP-in-IP, GRE и т. п., а представляющие туннель виртуальные интерфейсы настраиваются для поддержки ACP (ACP enable). Это активирует адреса IPv6 link-local и DULL для туннеля. В результате туннель служит для обычного обнаружения кандидата в соседи ACP по смежности L2 с помощью DULL и защищённый канал организуется, как описано выше.

Для туннелируемого удалённого соседа ACP нужны 2 инкапсуляции — настроенный туннель и защищённый канал в этом туннеле. Это делает механизм менее желательным, нежели настройка удалённого партнёра. Преимуществом туннеля является простота реализации, поскольку не требуется менять функциональность ACP, просто работа выполняется через виртуальный (туннельный) интерфейс вместо естественного. Туннель может обеспечивать PMTUD, а защищённый канал не делает этого. Туннельный механизм может не работать через некоторые межсетевые экраны, а защищённому каналу они не мешают.

Туннелирование с незащищённой инкапсуляцией в среднем повышает риск MITM-атак «на понижение (downgrade) в пути. В таких случаях MITM фильтрует пакеты для всех вариантов защищённого канала ACP, кроме наименее защищённых, чтобы атаковать их. Узлам ACP, поддерживающим туннельное соседство, следует обеспечивать настройку туннельных интерфейсов для ограничения или явного выбора протоколов защищённого канала ACP (если узел ACP поддерживает более одного такого протокола).

8.2.3. Заключение

Удалённые соседи менее «нерушимы» нежели смежные по L2 соседи ACP, использующие адреса link-local, поскольку они зависят от операций плоскости данных, таких как маршрутизация и глобальная адресация. Тем не менее, эти варианты могут быть очень важны для развёртывания ACP, особенно при необходимости соединять «островки» через Internet. Реализациям следует поддерживать хотя бы туннельных соседей ACP через протокол GRE, который сегодня представляется наиболее распространенным для туннелей между маршрутизаторами.

9. Операции ACP (информационный раздел)

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

  • В параграфе 9.1 описаны рекомендуемые возможности диагностики узлов ACP оператором.

  • В параграфе 9.2 приведено общее описание требований к работе регистратора ACP, параметров конфигурации и конкретных аспектов, влияющих на выбор варианта развёртывания. Рассмотрена модель, где регистраторы ACP имеют свой суб-CA для более распределенного варианта развёртывания регистраторов ACP, а также даны рекомендации по централизованному управлению правилами работы регистраторов ACP.

  • В параграфе 9.3 описано предлагаемое поведение узла ACP и операционные интерфейсы (опции настройки) для управления ACP в так называемых устройствах зелёного (не настроенные ранее) и коричневого (заранее настроенные) поля.

Рекомендации и предложения этого раздела основаны на опыте эксплуатации с коммерчески доступными предстандартными реализациями ACP.

9.1. Диагностика ACP и BRSKI

Хотя ACP и ANI в целом устраняют многие ошибки ручной настройки за счёт автоматизации, важно обеспечить хорошую диагностику и для них. Базовая стандартизованная диагностика требует поддержки моделей (YANG), представляющих полное состояние (авто)настройки и работы для всех компонентов: GRASP, ACP и применяемой ими инфраструктуры, такое как TLS/DTLS, IPsec, сертификаты, TA, время, VRF и т. д. Это необходимо, но недостаточно.

Простое представление состояний компонентов не позволяет операторам быстро предпринимать действия, пока они не понимают, как интерпретировать данные, что может означать необходимость глубокого понимания всех компонентов и их взаимодействий в ACP/ANI. Поддержка диагностики должна помогать быстро получить ответы на ожидаемые вопросы операторов, такие как: «ACP работает корректно?» или «Почему нет соединения ACP с известным соседом?». В современных подходах к управлению сетями логика ответов на такие вопросы чаще всего встроена в централизованные программы диагностики, использующие упомянутые выше модели данных. Хотя такой подход возможен для использующих ANI компонентов, его недостаточно для диагностики самих ANI, как указано ниже.

  • Для разработки логики выявления общих проблем нужен опыт работы с компонентами ANI. Определение своего анализа каждой системой управления неэффективно.

  • При некорректной работе ANI удалённая диагностика может стать недоступной из-за отсутствия связности. Поэтому в ANI следует иметь локально доступные средства диагностики на самих узлах.

  • Некоторые операции сложно или невозможно контролировать в реальном масштабе времени, например, проблемы с начальной загрузкой в сети при отсутствии возможности подключить локальную диагностику. Поэтому важно определить, как собрать (log) диагностику локально для последующего извлечения. В идеале такие записи должны быть энергонезависимыми, чтобы они сохранялись при отключении питания, например, когда устройство, которое не удалось запустить автоматически (zero-touch) передаётся для диагностики в более подходящее место.

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

Вопрос. Может ли ACP воспринимать соединения от соседей?

  • Проверяется корректность настройки рабочего состояния ACP/ANI (9.3. Включение и отключение ACP и ANI).

  • Выглядит ли системное время правдоподобным? Может быть это устанавливаемое по умолчанию время в результате отказа батареи в часах? Проверка сертификатов зависит от корректности времени.

  • Есть ли на узле ключевой материал, такой как сертификаты домена, TA и т. п.?

  • Если ключевого материала нет и ANI включена, проверяется состояние BRSKI (не детализировано в примере).

  • Проверяется действительность сертификата домена.

    • Проверяется ли сертификат в TA?

    • Сертификат не отозван?

    • Была ли успешна последняя попытка получить CRL (актуальны ли сведения CRL)?

    • Действителен ли сертификат? Начало действия сертификата в прошлом, а завершение в будущем?

    • Есть ли в сертификате корректно сформированное поле acp-node-name?

  • Удалось ли создать ACP VRF?

  • Включена ли ACP на одном или нескольких интерфейсах, которые включены и работают?

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

Вопрос. Почему узел не создал работающее соединение ACP с соседом по интерфейсу?

  • Интерфейс физически активен? У него есть адрес IPv6 link-local?

  • На интерфейсе разрешена плоскость ACP?

  • Удаётся ли передать сообщения DULL GRASP на интерфейс? (Есть ли ошибки канального уровня?)

  • Принимаются ли сообщение DULL GRASP на интерфейсе? Если нет, проблемы могут быть связаны с промежуточными устройствами L2, плохо отслеживающими MLD. Следует провести диагностику, например, устройства MLD, запрашивающего адрес IPv6 и MAC.

  • Видна ли цель ACP в каком-либо сообщении DULL GRASP от интерфейса? Диагностика поддерживаемых методов защиты канала.

  • Известен ли MAC-адрес соседа с целью ACP? Если нет, проверяется состояние SLAAC/ND.

  • Когда была последняя попытка организовать защищённый канал ACP к соседу?

  • Если такая попытка была неудачно проверяются указанные ниже условия.

    • Один из участников закрыл соединение из-за отказа при проверке сертификата принадлежности к домену?

    • Если соединение закрыл сосед, нужна диагностика протокола защиты канала.

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

      • У соседей нет общего протокола защиты канала (это невозможно при соответствии данной спецификации, требующей поддержки IPsec).

      • Проверка сертификата принадлежности к ACP (6.2.3. Проверка принадлежности к домену ACP) завершилась отказом?

        • Сертификат соседа на подписан напрямую или опосредовано одной из точек TA. Выполняется диагностика TA it (сожно узнать, кому принадлежит устройство).

        • Сертификат соседа относится к другому домену (или домена в нем нет). Проверяется acp-domain-name и, возможно, другие сведения из сертификата.

        • Сертификат соседа отозван или не может быть аутентифицирован OCSP.

        • Срок действия сертификата соседа истёк или ещё не начался.

    • Есть ли другие проблемы соединения, например IKEv2/IPsec, DTLS?

Вопрос. Работает ли ACP по защищённым каналам корректно?

  • Есть ли один или несколько активных соседей ACP с защищёнными каналами?

  • Работает ли RPL для ACP?

  • Есть ли в таблице маршрутизации ACP принятый по умолчанию маршрут к корню?

  • Есть ли маршрут для каждого прямого соседа ACP, недоступного через виртуальный интерфейс ACP к корню?

  • Работает ли ACP GRASP?

  • Кэширована ли хотя бы одна цель SRV.est (для поддержки обновления сертификатов)?

  • Есть ли в кэше хотя бы одна цель регистратора BRSKI (если BRSKI поддерживается)?

  • Нормально ли работает BRSKI-прокси на всех интерфейсах, где работает ACP?

Эти списки не являются полными, но они иллюстрируют принцип и возможность наличия разных проблем, начиная от обычных операций (сосед в другом домене ACP) и заканчивая проблемами поддержки свидетельств (срок действия сертификатов), явными защитными действиями (отзыв) или неожиданными проблемами связности (промежуточное оборудование L2). Показана возможность диагностики ANI путём пассивного наблюдения за рабочим состоянием компонентов, включая историю, кэширование и/или учёт событий. Для надёжной диагностики этого может быть недостаточно.

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

  1. BRSKI не позволяет соседнему устройству идентифицировать сертификат IDevID у заявителя. Это может делать лишь выбранный регистратор BRSKI, но распространение сведений о нежелательных заявителях узлам от регистраторов BRSKI может быть затруднено.

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

«Заинтересованная смежная сторона» всегда может определить сертификат IDevID заявителя BRSKI, действуя как посредник или регистратор BRSKI. Поэтому сертификат IDevID заявителя BRSKI не предназначен для защиты, его можно запросить и он не передаётся без запроса (как в LLDP), чтобы другие наблюдатели в сети могли определить, кто является «заинтересованной смежной стороной».

9.1.1. Диагностика партнёра по защищённому каналу

При взаимной проверке подлинности сертификатов не требуется явно передавать сертификаты TA, поскольку для проверки цепочки сертификации достаточно их хэш-значений. При организации защищённого канала ACP это ведёт к ограничению диагностики в случае отказа из-за несоответствия TA. Поэтому параграф 6.8.2 рекомендует включать сертификат TA в сигнализацию защищённого канала. Следует делать это без изменения протоколов защищённой связи, применяемых ACP. В [RFC7296] это не упоминается, но и не запрещено.

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

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

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

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

9.2. Регистраторы ACP

Как описано в параграфе 6.11.7. Регистраторы ACP, механизм адресации ACP предназначен для облегчённых, распределенных и некоординируемых регистраторов ACP, предоставляющих адресные префиксы ACP узлам-кандидатам в ACP путём зачисления их по сертификатам ACP в домен ACP с помощью подходящего механизма и/или протокола (не обязательно автоматизированного). В этом параграфе приведено неформальное описание деталей и вариантов для регистраторов ACP.

9.2.1. Взаимодействие регистраторов

В этом параграфе обсуждаются и обобщаются взаимодействия с другими элементами, требуемые регистратором ACP.

В простых экземплярах сети ACP не требуется центрального компонента NOC, помимо TA. Обычно это корневой CA. Можно установить 1 или некоординируемых самостоятельно регистраторов ACP с описанным ниже взаимодействием.

Для оркестровки автоматического зачисления узлов кандидатов в ACP регистратор ACP может полагаться на ACP и применять прокси для доступа к узлу-кандидату, что позволяет обойтись минимальными, имеющимися настроенными (заранее) сетевыми службами на узле-кандидате. BRSKI определяет BRSKI-прокси, который можно приспособить для разных протоколов, которые заявители и/или узлы-кандидаты ACP могут применять, например, BRSKI через CoAP (Constrained Application Protocol) или посредничество для NETCONF.

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

При неавтономном зачислении сначала нужно настроить плоскость данных между регистратором ACP и узлом-кандидатом в ACP. Это включает регистратор ACP и узел-кандидат. Затем можно использовать любой подходящий протокол между регистратором и узлом-кандидатом для обнаружения другой стороны с последующим соединением и зачислением (настройкой) кандидата в ACP по сертификату ACP. Например, для этого может служить протокол NETCONF Zero Touch (Secure Zero Touch Provisioning (SZTP) [RFC8572]). BRSKI с дополнительными механизмами обнаружения тоже подходит для узлов-кандидатов, пытающихся зачислить себя в ACP через сеть без поддержки ACP, например, Internet.

Когда узел-кандидат в ACP, такой как заявитель BRSKI, использует защищённую начальную загрузку, он не будет доверять конфигурации и/или зачислению через сеть, пока ему не представлен ваучер (A Voucher Artifact for Bootstrapping Protocols [RFC8366]) подтверждающий подлинность сети в части владения узлом. Регистратору ACP потребуется метод получения такого ваучера через сеть или иным путём (offline) от агентства MASA (Manufacturer Authorized Signing Authority). Протоколы BRSKI и NETCONF Zero Touch имеют возможность предоставления ваучера узлу-кандидату в ACP.

Регистратор ACP может применять EST для отзыва сертификатов ACP и/или выступать как точка распространения CRL. Узлу, оказывающему такие услуги, не нужно выполнять (начальное) зачисление, но от него требуется описанная выше связность, как от регистратора ACP (через ACP с узлами ACP и через плоскость данных с TA и иными источниками CRL).

9.2.2. Параметры регистратора

Взаимодействия регистраторов ACP, описанные в параграфах 6.11.7 и 9.2.1, зависят от указанных ниже параметров.

  • URL для TA и свидетельства, чтобы регистратор ACP мог разрешить TA подписывать сертификаты узлов ACP.

  • Имя домена ACP.

  • Registrar-ID для использования. По умолчанию это может быть MAC-адрес регистратора ACP.

  • Следующие пригодные Node-ID для субсхем Zone (Zone-ID 0) и Vlong (/112 и /120) при восстановлении. Эти идентификаторы нужны лишь при восстановлении после отказа. Могут потребоваться иные механизмы для запоминания идентификаторов в резервном месте или восстановления от известных узлов ACP.

  • Правила предоставления сертификатов (например, сертификата домена) узлам-кандидатам ACP на основе сертификата IDevID как в BRSKI. Регистратор ACP может создавать «белые» или «черные» списки на основе атрибута serialNumber [X.520] в поле кодирования субъекта отличительного имени в его сертификате IDevID.

  • Правила выбора типа адресного префикса для устройства-кандидата ACP, вероятно на основе тех же данных.

  • Для BRSKI или иного механизма с ваучерами — параметры для определения способа извлечения ваучеров для конкретного типа защищённой загрузки узла-кандидата в ACP (например, MASA URL), пока эти сведение не получены автоматически, например, из сертификата IDevID узла-кандидата в ACP (как задано в BRSKI).

9.2.3. Отзыв и ограничения сертификатов

Когда узел ACP обновляет сертификат и/или меняет его ключи, он в конечном итоге может сделать это через другого регистратора (например, сервер EST), нежели тот, от которого был получен сертификат ACP, например, по причине ухода того регистратора ACP. Регистратор ACP, через которого выполнено обновление или смена ключей, по умолчанию доверяет acp-node-name из текущего сертификата ACP узла ACP и поддерживает эту информацию, чтобы узел ACP сохранял свой адресный префикс ACP. При обновлении или смене ключей через EST текущий сертификат ACP узла ACP указывается в процессе согласования TLS. Этому простому сценарию присущи два ограничения.

  1. Регистратор ACP не может напрямую назначать сертификаты узлам, поэтому нуждается в действующем подключении к TA.

  2. Восстановление от скомпрометированного регистратора ACP затруднено. При компрометации регистратора ACP он может внедрить, например, конфликтующее значение acp-node-name и таким образом создать возможность атаки других узлов ACP через протоколо маршрутизации ACP.

Даже при обнаружении такого злонамеренного регистратора ACP решение проблемы может быть сложным из-за того, что потребуется идентифицировать все ложные сертификаты ACP, выданные через скомпрометированного регистратора ACP. Без дополнительного централизованного отслеживания выданных сертификатов это невозможно.

9.2.4. Регистраторы ACP с суб-CA

В ситуации, когда любое из двух указанных выше ограничений является проблемой, регистраторы ACP могут также быть суб-CA. Это снимает необходимость подключения к TA при каждом зачислении узла ACP и снижает потребность в подключении такого регистратора ACP к TAЮ требуя её лишь для обновления своего сертификата. Регистратор ACP будет применять свой (суб-CA) сертификат при зачислении и подписывании сертификатов узлов ACP, поэтому потребуется лишь отозвать сертификат суб-CA скомпрометированного регистратора ACP. Можно также дождаться завершения срока действия сертификата суб-CA и не обновлять его, когда этот срок достаточно короток.

Поскольку при проверке принадлежности к домену ACP проверяется цепочка доверия для сертификата ACP узла ACP, это включает и проверку сертификата подписи, который является скомпрометированным и/или отозванным сертификатом суб-CA. Поэтому включить в домен ACP узел ACP, зачисленный скомпрометированным и обнаруженным регистратором ACP, не получится.

Узлы ACP, зачисленные скомпрометированным регистратором ACP, автоматически не смогут организовать каналы ACP и обновить сертификат домена ACP через EST, поэтому вернутся в состояние кандидата в ACP и будут пытаться получить новый сертификат ACP от регистратора ACP, например, через BRSKI. В результате регистраторы ACP со связанным суб-CA упрощают изоляцию и решение проблем со скомпрометированными регистраторами.

Отметим, что регистраторы ACP с функциональностью суб-CA могут также более легко контролировать срок действия сертификатов ACP, поэтому могут служить как инструмент создания краткосрочных сертификатов и больше не полагаться на CRL, тогда как сертификаты этих суб-CA могут быть более долгосрочными и отзываемыми через CRL.

9.2.5. Централизованное управление политикой

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

  • Решение о включении узла-кандидата ACP в домен ACP. Это может быть решением, которое не нужно принимать заранее, чтобы политика для атрибута serialNumber в поле субъекта кодирования отличительного имени могла быть загружена в каждый регистратор ACP. Может оказаться лучше решать этот вопрос в реальном масштабе времени, включая возможное участие человека в NOC.

  • Отслеживание всех зачисленных узлов ACP и сведений об их сертификатах, например, для поддержки отзыва сертификатов отдельных узлов ACP.

  • Потребность в более гибких правилах в отношении типа адресного префикса и даже конкретного префикса, назначаемого узлу-кандидату в ACP.

Эти и другие операции можно было бы упростить введением централизованной системы управления политикой (Policy Management System или PMS) и смены поведения регистраторов ACP, чтобы они запрашивали у PMS любые решения о политике в процессе зачисления узлов-кандидатов в ACP и/или обновления сертификатов узлов ACP (например, выделяемый префикс ACP). Точно так же регистратор ACP будет сообщать PMS любую соответствующую информацию о смене состояния, например, при успешном зачислении сертификата на узле-кандидате ACP.

9.3. Включение и отключение ACP и ANI

Как для ACP, так и для BRSKI требуется достаточная работоспособность интерфейсов для поддержки передачи и приёма их пакетов. В узлах, где интерфейсы по умолчанию включены (например, без настройки конфигурации), как в большинстве коммутаторов L2, поведение будет меняться не столь сильно, как в большинстве устройств L3 (например, маршрутизаторов), где интерфейсы по умолчанию отключены. Однако почти во всех сетевых устройствах настройка конфигурации с физическим отключением интерфейсов ведёт к нарушению работы ACP.

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

9.3.1. Фильтрация пакетов, не относящихся к ACP/ANI

Всякий раз, когда в этом документе упоминается включение интерфейса для ACP (или BRSKI), требуется лишь разрешение интерфейсу передавать и принимать данные, необходимые для работы ACP (или BRSKI), но не иные пакеты данных. Если плоскость данных явно не настроена и не разрешена, все пакеты, не требуемые для ACP/BRSKI, следует фильтровать на входе и выходе.

Протоколы BRSKI и ACP требуют на интерфейсах лишь операции IPv6 link-local и DULL GRASP. Операции IPv6 link-local означают минимальную сигнализацию для автоматического назначения адреса IPv6 link-local и взаимодействия с соседями через него — SLAAC [RFC4862] и ND [RFC4861]. Когда устройство является заявителем BRSKI, оно может также требовать на интерфейсе соединений TCP/TLS с посредниками BRSKI. При наличии у интерфеса ключевого материала и работе ACP требуется поддержка пакетов DULL GRASP и пакетов, необходимых для механизмов организации защищённых каналов, например, пакетов IKEv2 и IPsec ESP или DTLS по адресу IPv6 link-local соседа ACP на интерфейсе. Нужны также пакеты TCP/TLS для функций BRSKI-прокси при поддержке BRSKI.

9.3.2. Состояние admin down

В большинстве сетевых устройств интерфейсы имеют хотя бы два состояния — up (включён) и down (отключён). Имена состояний могут зависеть от конкретного устройства, например, down иногда называют shutdown, а up — no shutdown. Состояние down отключает все операции интерфейса на физическом уровне. Состояние up разрешает на интерфейсе работу всех возможных служб L2/L3 и может автоматически включать некоторые службы. Чаще всего операциями L2/L3 оправляют те или иные опции на уровне узла или интерфейса, но все они становятся доступными лишь в состоянии интерфейса, отличном от down. Поэтому самым простым способом деактивировать на интерфейсе все операции L2/L3 является перевод интерфейса с состояние down. Физическое отключение интерфейса во многих случаях является побочным эффектом, но иногда может быть важно само по себе (9.3.2.2. Быстрое распространение состояний и диагностика).

Распространённой проблемой при удалённом управления является прерывание оператором или контроллером SDN своей связности с уделенным узлом через конфигурацию, влияющую на настройку управляющего соединения с этим узлом. Плоскости ACP, как таковой, не следует иметь выделенной конфигурации, кроме упомянутого выше включения ACP на узлах с заранее настроенной плоскостью данных (brownfield). Это исключает конфигурации, не способные различать ACP и плоскость данных как источники ошибок в настройке, которые будут влиять на ACP, даже будучи нацеленными лишь на плоскость данных. Единственным распространенным типом команд, которые имеют такой побочный эффект, являются команды административного отключения интерфейса — down. Когда такая команда применяется к интерфейсу, через который ACP обеспечивает доступ для удалённого управления, это разрывает управляющее соединение через ACP, как отмечено выше, поскольку команда down обычно влияет на физический уровень,а не только на службы плоскости данных.

Для обеспечения устойчивости ACP/ANI к таким ошибкам оператора этот документ рекомендует разделить состояние down на admin down, где работа на физическом уровне сохраняется и ACP/ANI могут использовать интерфейс, и physical down. Существующие down-конфигурации будут отображаться на состояние admin down, которое имеющиеся службы L2/L3 не будут отличать от физического отключения. Для блокировки передачи и приёма каких-либо пакетов данных можно автоматически организовать фильтрацию пакетов, как описано в параграфе 9.3.1.

Примером трафика ANI (но не ACP), который следует разрешать даже в состоянии admin down, является трафик зачисления BRSKI между заявителем и посредником BRSKI.

Для перевода в состояние physical down при необходимости могут быть введены дополнительные опции (см. ниже). Эти опции следует снабжать дополнительными проверками для снижения риска ввода команд, приводящих к прерыванию работы ACP без автоматического восстановления. Примеры проверок включают запрет ввода опции из управляющего соединения (NETCONF/SSH), проходящего через сам интерфейс (не отключить себя) или применение опции после дополнительного подтверждения.

В последующих параграфах рассмотрены важные аспекты введения состояния admin down.

9.3.2.1. Безопасность

Интерфейсы отключают физически (или оставляют в принятом по умолчанию состоянии down) из соображений безопасности. Описанное выше состояние admin down также обеспечивает высокий уровень безопасности, поскольку оно разрешает лишь операции ACP/ANI, которые хорошо защищены. В конечном итоге безопасность развёртывания зависит от того, является ли admin down приемлемой заменой физическому отключению.

Необходимость доверять защите операций ACP/ANI нужно сравнивать с эксплуатационными преимуществами. Рассмотрим типовой пример клиентского оборудования (customer premises equipment или CPE), установленного там, где нет специалиста по сетям. Пользовательские порты устройств находятся в состоянии physical down, если явно не задано иное. В случае ошибочной конфигурации восходящее соединение (uplink) может быть некорректно подключено к этому порту. Устройство оказывается отключённым от сети и диагностика со стороны сети становится невозможной. Если же все порты находятся в состоянии admin down, плоскость ACP (но не плоскость данных) по-прежнему будет формироваться автоматически. Диагностика с сетевой стороны становится возможной и действия оператора могут восстановить работу uplink-порта или передать на сайт инструкцию по подключению через иной порт. С точки зрения безопасности атаковать можно лишь ACP/ANI, поскольку все прочие функции фильтруются на интерфейсе admin down.

9.3.2.2. Быстрое распространение состояний и диагностика

Состояние physical down на многих сетевых интерфейсах (например, Ethernet) передаётся другой стороне. Это ведёт к быстрой реакции протокола L2/L3 на той стороне. Состояние admin down будет давать такой же (быстрый) результат.

Насколько известно, перевод интерфейсов в состояние physical down, всегда является результатом действий оператора и никогда не происходит в результате действий автономных служб L2/L3 на узлах. Поэтому одним из вариантов является прекращение зависимости оператора от распространения состояний интерфейсов через канал подсети или физический уровень. Это может оказаться невозможным, когда каждая сторона управляется своим оператором, но в таких случаях маловероятна работа ACP по каналу и перевод интерфейса в состояние physical down остаётся хорошим решением.

В идеале быстрое распространение физического состояния заменяется быстрым распространением программно-управляемого состояния. Например, цель DULL GRASP admin-state можно использовать для автоматической настройки сессии BFD («Bidirectional Forwarding Detection (BFD)» [RFC5880]) между двумя сторонами канала, которая будет распространять состояние up, а не admin down.

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

В параграфе 9.1 описано, как LLDP и диагностику через GRASP можно использовать для диагностики соседей, что может избавить от необходимости применять physical down для такой диагностики, если оба соседа поддерживают ACP/ANI.

9.3.2.3. Диагностика каналов на нижнем уровне

Состояние physical down служит для диагностики проблем на нижних уровнях, когда высокоуровневые службы (например, IPv6) не работают. Канала Ethernet особенно подвержены проблемам с соединениями, если они не поддерживают автоматического определения скорости (10/100/1000 Мбит/с), MDI-X и разъемы (когда интерфейс поддерживает несколько типов среды). Потребность в диагностике на нижних уровнях можно исключить при использовании автоматической настройки каналов. В дополнение к состоянию physical down диагностика на нижних уровнях Ethernet или других интерфейсов включает создание на интерфейсах иных состояний, таких как внутренние и внешние физические петли (loopback) или отключение передачи всех пакетов для отражения при рефлектометрии и/или измерении длины кабеля. Все эти варианты нарушают работу ACP.

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

9.3.2.4. Вопросы энергопотребления

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

9.3.3. Включение ACP и ANI на уровне интерфейса

Опция ACP enable на уровне интерфейса разрешает на нем операции ACP, начиная с автоматического обнаружения соседей ACP через DULL GRASP. Опция ANI enable на уровне интерфейса узла, поддерживающего BRSKI и ACP запускает операции с заявителями BRSKI, когда на узле нет сертификата домена. На узлах ACP/BRSKI может потребоваться поддержка лишь опции ANI enable (без ACP enable).

Если это не переопределено глобальными параметрами конфигурации (параграф 9.3.4), любая из команд ACP enable и ANI (сокращённо ACP/ANI enable») заменят состояние down на интерфейсе состояним admin down.

9.3.4. Какие интерфейсы включать автоматически?

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

Рассмотрим домен ACP из узлов ACP, транзитивно соединённых через естественные интерфейсы. Созданы туннели в плоскости данных между узлами, не являющимися прямыми соседями, и для этих туннелей установлено ACP enable. Протокол ACP RPL видит эти туннели как один интервал пересылки (hop). Маршруты в ACP будут использовать этот интервал как подходящий элемент пути для соединения смежных с туннелем областей. В результате фактические поэтапные (hop-by-hop) пути, используемые для трафика в ACP, могут ухудшаться. Кроме того, корректность пересылки в ACP становится зависимой от корректной пересылки в плоскости данных, включая QoS, фильтрацию и другую защиту на пути, по которому проходит туннель. По этой причине ACP/ANI enable не следует устанавливать автоматически на неестественных интерфейсах.

Если туннель связывает две ранее разделённые области ACP, он явно будет полезен для ACP. Туннель в плоскости данных может работать через узлы без ACP и обеспечивать дополнительную связность для уже подключённой сети ACP. Преимущество такой избыточности в ACP необходимо сопоставлять с проблемами, связанными с плоскостью данных. Если туннель соединяет две раздельные области ACP, сколько туннелей может потребоваться для достаточно надёжного соединения этих областей ACP? Между какими узлами? Это стандартные вопросы организации туннелирования, не связанные с ACP, и для них нет единого автоматизируемого решения. Вместо автоматической установки ACP enable для таких интерфейсов может потребоваться решение, основанное на цели применения неестественного интерфейса, и ACP enable потребуется установить в сочетании с механизмом, который создаёт и настраивает неестественный интерфейс.

В дополнение к явной установке ACP/ANI enable для неестественных интерфейсов требуется также задать стоимость канала ACP RPL, чтобы избежать проблем привлечения в канал излишнего трафика, как описано выше.

Даже естественные интерфейсы могут быть неспособны автоматически выполнять BRSKI или ACP, поскольку они могут требовать дополнительных действий оператора для своей работы. Примеры включают интерфейсы DSL, требующие свидетельств PPPoE (Point-to-Point Protocol over Ethernet), или мобильные интерфейсы, требующие свидетельств с SIM-карты. Какой би механизм ни применялся для обеспечения нужной конфигурации устройства для включения интерфейса, его можно расширить для решения вопроса об установке ACP/ANI enable.

Цель автоматической установки ACP/ANI на (любых) интерфейсах состоит в устранении ненужных «касаний» к узлу, чтобы сделать работу узла максимально близкой к zero-touch в части ACP/ANI. При наличии неизбежных действий, таких как создание и/или настройка неестественного интерфейса или предоставление свидетельств естественному интерфейсу ACP/ANI enable следует добавлять как часть такого действия. Если ошибочное «касание» легко исправить(без создания другого дорогостоящего касания), по умолчанию не следует включать ANI/ACP, а при сложном или дорогом исправлении (например, параметры на SIM-карте, отправленное в далёкое место) следует по умолчанию включать ACP/ANI.

9.3.5. Включение ACP и ANI на уровне узла

Команда на уровне узла ACP/ANI enable [up-if-only] включает ACP или ANI на узле (ANI = ACP + BRSKI). Без этого набора команд все команды ACP/ANI enable на уровне интерфейсов игнорируются. После выполнения команды ACP/ANI будет работать на интерфейсах, гда задано ACP/ANI enable. Установка ACP/ANI enable на уровне интерфейса выполняется автоматически (по умолчанию) или явным действием оператора, как описано в параграфе 9.3.4.

Если использована опция up-if-only поведение интерфейсов с состоянии down не меняется и ACP/ANI будет работать лишь на интерфейсах, где задано ACP/ANI enable и интерфейс находится в состоянии up. При отсутствии этой опции интерфейсы в состоянии down с ACP/ANI enable перейдут в состояние admin down.

9.3.5.1. Узлы с настроенной плоскостью данных

Настроенными (brownfield) узлами называют те, на которых уже настроена плоскость данных.

Глобальное выполнение ACP/ANI enable [up-if-only] на каждом узле является единственной командой, требуемой для создания ACP в сети уже настроенных (brownfield) узлов, когда у них уже есть сертификаты домена. При использовании BRSKI (ANI enable), для предоставления этих сертификатов требуется установить один регистратор BRSKI, который также может служить CA для сети. Это простейший способ запустить ACP/ANI в имеющейся сети.

Необходимость явного включения ACP/ANI особенно важна для узлов brownfield, поскольку иначе обновление программ может внести поддержку ACP/ANI. Автоматическое включение ACP/ANI в сетях, где оператор не желает применять ACP/ANI (скорее просто не слышал об этом) может сильно раздражать оператора, особенно при смене состояния down на admin down.

Автоматическая установка ANI на brownfield-узлах, где оператор не знает о работе BRSKI и MASA может создать серьёзную проблему безопасности, хоть это и маловероятно. Если атакующий может выдать себя за оператора, регистрируясь в таком качестве на узле MASA, или иным путём получить ваучеры, то при достаточном физическом доступе в сеть, чтобы заявители регистрировались у него, злоумышленник сможет получить доступ к ACP и далее через ACP — к плоскости данных. В сетях, где оператор явно разрешает ANI, этого не может случиться, поскольку оператор будет создавать регистратор BRSKI, который обнаружит попытки атак, и оператор настраивал бы свой регистратор с MASA. Узлы, требующие ваучеров владения, не подвержены такой атаке (см. [RFC8995]). Отметим, что при глобальном ACP enable не возникает риска таких атак, поскольку они зависят от какого-либо механизма для предварительного предоставления сертификатов домена устройствам.

9.3.5.2. Заранее не настроенные узлы

Узлами ACP greenfield считаются узлы, которые не имеют предварительной конфигурации и могут использовать начальную загрузку через сеть для присоединения к ACP. Для поддержки таких узлов описанную в документе плоскость ACP нужно объединить с протоколом начальной загрузки и/или механизмом, который будет зачислять узлы с ключевым материалом ACP — сертификатом ACP и TA. Для узлов ANI таим механизмом служит BRSKI.

Когда такой узел включается и обнаруживает отсутствие конфигурации (greenfield), он включает протоколы и/или механизмы начальной загрузки. После зачисления ключевого материала ACP состояние greenfield завершается и запускается ACP. При использовании BRSKI состояние узла отражает это установкой ANI enable при определении состояния greenfield в момент включения питания.

Узлам ACP greenfield, интерфейсы которых при отсутствии ACP будут в состоянии down, следует установить все естественные интерфейсы в состояние admin down и разрешать лишь трафик плоскости данных, требуемый для протоколов и/или механизмов начальной загрузки.

Состояние ACP greenfield завершается зачислением ключевого материала ACP (сертификат и TA) или обнаружением разрешения прервать операции ACP greenfield.

Узлы ACP, поддерживающие работу с нуля (greenfield), могут пожелать обеспечивать совместимость с прежними формами настройки и/или обеспечения, особенно в случаях развёртывания ACP лишь на части узлов. Таким узлам ACP следует наблюдать попытки обеспечения или настройки узла с помощью интерфейсов и/или методов, которые традиционно указывают физическое владение узлом, такие как подключение последовательного или USB-порта для консольного доступа или носителя USB с конфигурацией начальной загрузки. Когда такая операция замечена до завершения зачисления ключевого материала ACP, узлу следует перейти в состояние, в котором он находился бы при запрете ACP/ANI во время загрузки. Это прерывает операции ACP greenfield.

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

Узлам, заявляющим поддержку операций ANI с нуля (greenfield), не следует разрешать параллельно с BRSKI какой-либо протокол или механизм зачисления или начальной загрузки, который допускает доверие при первом использовании (Trust On First Use или TOFU, Opportunistic Security: Some Protection Most of the Time [RFC7435]) через интерфейсы, отличные от тех, которые традиционно показывают физическое владение узлом. Считается, что протоколы и механизмы с опубликованной аутентификацией по имени пользователя и паролю страдают от TOFU. Защита протоколов и механизмов начальной загрузки требованием ваучера [RFC8366] может служить для предотвращения TOFU.

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

9.3.6. Отмена ANI/ACP enable

Отключение ANI/ACP путём отмены (undo) ACP/ANI enable создаёт риск для надёжной работы ACP, если это сделано по ошибке или без соответствующих полномочий. На это можно повлиять с помощью дополнительного (будущего) свойства в сертификате (например, в поле расширения acp-node-name). В развёртывании ANI, предназначенном для удобства, отключение может быть разрешено без дополнительных ограничений. В развёртывании ANI, считающемся критическим, требуется больше проверок. Одним из наиболее контролируемых вариантов был бы запрет этих команд , пока сертификат домена не отозван или его обновление не было отвергнуто. Настройка этого варианта была бы параметром регистраторов BRSKI. Пока узел не получил сертификат домена, для отмены ANI/ACP enable не следует устанавливать дополнительных ограничений.

9.3.7. Заключение

Команды ACP/ANI enable [up-if-only] на уровне узла разрешают работу ACP/ANI. Это автоматически разрешено лишь на устройствах ANI greenfield, в иных случаях требуется явная настройка.

Если опция up-if-only не задана, интерфейсы со включённым ACP/ANI рассматривают состояние down как admin down, а не physical down. В состоянии admin-down все пакеты, не относящиеся к ACP/ANI, фильтруются, но физический уровень продолжает работать для операций ACP/ANI.

(Новые) команды, приводящие к физическому прерыванию (physical down, loopback) интерфейсов с поддержкой ACP/ANI, следует создавать так, чтобы максимально защитить непрерывность или восстановление ACP.

Команды ACP/ANI enable на уровне интерфейса управляют операциями на интерфейсе. Этот режим включён по умолчанию на естественных интерфейсах и настраивается явно на прочих интерфейсах.

Отключение ACP/ANI enable глобально или на уровне интерфейса следует выполнять с дополнительными проверками для предотвращения нежелательных перебоев в работе ACP. Уровень контроля может быть параметром на уровне домена в сертификатах домена.

9.4. Частичное или поэтапное внедрение

Субсхема адресации Zone (параграф 6.11.3) позволяет поэтапно внедрять ACP в сети, где ACP может развёртываться по периметру, но не в ядре, соединяющем эти края. В таких случаях каждая краевая сеть, такая как сеть кампуса или предприятия, имеет отдельную (disjoint) плоскость ACP, которой выделен один или несколько уникальных Zone-ID. Узлы ACP, зарегистрированные в конкретной зоне ACP получают адреса по субсхеме Zone, например, посредством создания для каждой такой зоны одного или нескольких регистраторов ACP с Zone-ID. Все регистраторы для этих зон ACP должны получить сертификаты ACP от CA на основе общего набора TA и общего имени домена ACP.

Эти зоны ACP могут создаваться сначала как отдельные сети без соединений между собой и/или могут быть соединены через сеть ядра без ACP с помощью различных неавтономных методов работы. Например, каждая отдельная зона ACP может иметь краевой узел в форме L3 VPN PE (MPLS или IPv6 L3VPN), где создаётся полная, неавтономная VPN ядра ACP с использованием ACP VRF и обмена маршрутами от этих ACP VRF через неавтономные протоколы маршрутизации VPN.

Хотя такая установка возможна с любой субсхемой адресации ACP, субсхема Zone проще в настройке и расширяема для любых протоколов маршрутизации VPN, поскольку каждой зоне ACP требуется лишь указать один или несколько адресных префиксов /64 зоны ACP в VPN ядра ACP в отличие от маршрутов к каждому узлу ACP, как требуют другие субсхемы адресации ACP.

Отметим, что неавтономная VPN ядра ACP требует дополнительных расширений для распространения сообщений GRASP, когда желательно обнаружение GRASP через зоны. Например, можно создать на каждом граничном маршрутизаторе зоны туннель ACP к концентратору GRASP. Этот концентратор можно реализовать на прикладном уровне и запустить в сети NOC. Он будет распространять анонсы GRASP между зонами ACP и/или генерировать аносы GRASP для служб NOC.

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

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

9.5. Конфигурация и ACP (заключение)

Для ACP нет желательной конфигурации и все параметры, которые нужно настраивать для поддержки ACP, являются ограничениями решения, но они требуются лишь в тех случаях, когда не все компоненты являются автономными. Когда это необходимо, применяются имеющиеся механизмы настройки, такие как CLI или модели данных YANG (The YANG 1.1 Data Modeling Language [RFC7950]). Наиболее важные примеры таких конфигураций указаны ниже.

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

  • Для управления сертификатами нужны функции PKI. Обнаружение таких функций через ACP автоматизировано (6.2.5. Поддержка сертификата и привязки доверия), а их настройка — нет.

  • Когда узлы без поддержки ACP, такие как имеющиеся NMS, нужно физически подключать к ACP, применяемый для подключения узел ACP нужно настроить в соответствии с параграфом 8.1. ACP Connect. Можно также организовать подключение ACP и плоскости данных сети через одно физическое соединение (параграф 8.1.4).

  • Когда начальная загрузка устройств неавтономна, нужна явная настройка для включения ACP (параграф 9.3).

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

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

ACP также обеспечивает дополнительную защиту за счёт применения поэтапного (hop-by-hop) шифрования для таких операций настройки. Некоторые традиционные методы настройки (например, SNMP, TFTP, HTTP) могут не использовать сквозного шифрования и большинство методов настройки со сквозной защитой по-прежнему легко позволяет пассивно наблюдать на процессом настройки (например, транспортные потоки, номера портов, адреса IP).

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

10. Заключение — преимущества (информационный раздел)

10.1. Свойства самовосстановления

ACP поддерживает самовосстановление, как указано ниже.

  • Новые соседи автоматически присоединяются к ACP после успешной проверки и становятся доступными через ACP по их уникальным адресам ULA.

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

  • ACP отслеживает действительность сертификатов партнёров и разрывает защищённые каналы ACP по истечении срока действия сертификата партнёра. Когда используются краткосрочные сертификаты с временем действия порядка периода обновления OCSP/CRL, это позволяет удалять недействительных партнёров (чей сертификат не обновлён) с той же скоростью, что и при использовании OCSP/CRL. Такие же преимущества могут быть достигнуты при использовании CRL/OCSP, периодическом обновлении сведений об отзыве, а также разрыве защищённых каналов, когда (длительный) сертификат партнёра отозван. Однако в целях упрощения от реализаций ACP не требуется поддержка этих усовершенствований.

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

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

Решения ACP с высокой устойчивостью к отказам могут создаваться с использованием регистраторов ACP со встроенными суб-CA, как указано в параграфе 9.2.4. Пока в отделившейся сети имеется один или несколько таких регистраторов ACP, будет продолжаться зачисление новых кандидатов в ACP до завершения срока действия сертификата суб-CA у регистратора ACP. Поскольку адресация ACP основывается на уникальных Registrar-ID, последующее слияние разделённых частей сети не вызовет проблем с адресацией ACP, заданной при разделении.

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

При слиянии двух сетей с разными TA от узлов ACP потребуется доверие к объединению TA. Когда хэш-значения субдоменов маршрутизации различаются, адресация не будет перекрываться. Перекрытие возможно лишь случайно в случае маловероятного совпадения 40-битовых хэш-значений SHA-256 (см. 6.11. Адресация внутри ACP). Отметим, что полные механизмы слияния сетей выходят за рамки этой спецификации.

Для реализаций ACP очень важна способность работать через отключённые административно интерфейсы. При невозможности этого взамен можно запросить у оператора явное переопределение действий по отключению интерфейсов, через которые работает ACP, особенно если известно, что отключение ACP оторвёт оператора от узла. Например, административные действия по отключению могут включать проверку зависимостей, чтобы увидеть, не отключат ли эти действия транспортное соединение в результате (при использовании принятой по умолчанию маршрутизации RPL пересылка пакетов будет симметричной, поэтому это можно проверить фактически).

10.2. Самозащита

10.2.1. Извне

Как указано в разделе 6. Создание ACP (нормативный раздел), ACP работает на основе защищённых каналов между узлами, которые взаимно аутентифицируют друг друга по сертификатам домена. Сами каналы защищены стандартными методами шифрования, такими как DTLS или IPsec, которые обеспечивают дополнительную аутентификацию при создании, целостность и конфиденциальность данных внутри ACP, а также защиту от повторного использования (replay). Атакующий не сможет войти в ACP, пока у него нет действительного сертификата ACP. Злоумышленник в пути без действительного сертификата ACP не сможет внедрить пакеты в ACP, поскольку каналы ACP защищены. Он не сможет и расшифровать трафик ACP без взлома шифрования. Он может лишь пытаться анализировать поведение шифрованного трафика ACP.

Степень влияния скомпрометированных узлов на работу ACP зависит от реализации узлов ACP и их повреждений. Когда атакующий получил лишь административные права для удалённой настройки узлов ACP, он может нарушить работу ACP с помощью одного или нескольких параметров конфигурации, чтобы отключить узел (9.3. Включение и отключение ACP и ANI) или настройки неавтономных опций ACP, если это поддерживается повреждёнными узлами ACP (8. Поддержка элементов, не понимающих ACP (нормативный раздел)). Внедрение или извлечение трафика на повреждённом узле ACP возможно лишь при поддержке этим узлом ACP connect (8.1. ACP Connect) и злоумышленник может контролировать трафик на одном из интерфейсов узла ACP, например, имея физический доступ к узлу ACP.

ACP также служит защитой (за счёт аутентификации и шифрования) для протоколов, связанных с OAM, которые могут не иметь опций защиты стека или в которых реализация или развёртывание опций защиты не удались по причине ограничений производителя, продукции или клиента. Это включает протоколы SNMP (An Architecture for Describing Simple Network Management Protocol (SNMP) Management Frameworks [RFC3411]), NTP [RFC5905], PTP (Precision Time Protocol [IEEE-1588-2008]), DNS (DNS Extensions to Support IP Version 6 [RFC3596]), DHCPv6 (Dynamic Host Configuration Protocol for IPv6 (DHCPv6) [RFC3315]), syslog (The BSD Syslog Protocol [RFC3164]), RADIUS (Remote Authentication Dial In User Service (RADIUS) [RFC2865]), Diameter (Diameter Base Protocol [RFC6733]), TACACS (An Access Control Protocol, Sometimes Called TACACS [RFC1492]), IPFIX (Specification of the IP Flow Information Export (IPFIX) Protocol for the Exchange of Flow Information [RFC7011]), NetFlow (Cisco Systems NetFlow Services Export Version 9 [RFC3954]) и другие. Не все приведённые ссылки указывают на последние версии протоколов, но указанные версии применяются широко.

Защита на основе защищённых поэтапных соединений ACP для этих и других протоколов является лишь временной мерой, конечная цель состоит в сквозном шифровании с использованием сертификата домена и опора на защищённые каналы ACP предназначена прежде всего для надёжной связности без участия пользователя (zero-touch), а не для обеспечения безопасности.

Оставшийся вектор атак включает атаки непосредственно на базовые протоколы ACP напрямую или через отказ в обслуживании. Однако, благодаря построению ACP на основе адресов IPv6 link-local, удалённые атаки из плоскости данных невозможны, поскольку в плоскости данных нет возможностей удалённо передавать пакеты IPv6 link-local. Единственным исключениям являются интерфейсы ACP connect, требующие большей физической защиты. Адреса ULA доступны лишь из контекста ACP и поэтому недостижимы из плоскости данных. Кроме того, протоколы ACP следует реализовать так, чтобы быть устойчивым к атакам и не потреблять избыточных ресурсов даже при атаке.

10.2.2. Изнутри

Модель защиты ACP основана на доверии всех членов группы узлов, имеющих сертификаты ACP одного домена, поэтому атаки со стороны скомпрометированного члена группы создают наибольшие проблемы.

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

Как отмечено выше, для трафика через ACP следует по возможности обеспечивать сквозное шифрование. Это включает трафик GRASP, EST и BRSKI внутри ACP. Такая защита минимизирует MITM-атаки со стороны скомпрометированных членов группы ACP. Такой злоумышленник не может перехватить или изменить коммуникации, но способен фильтровать их, что неизбежно в любых обстоятельствах.

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

10.3. Представление для администратора

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

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

Благодаря самозащите ACP, узлы без поддержки ACP или не имеющие действительного сертификата домена, не могут подключиться к ACP. Это значит, что по умолчанию возможности подключения лишены традиционные контроллеры и NMS. В параграфе 8.1.1. Контроллер или NMS без поддержки ACP описано, как они могут организовать подключение.

11. Вопросы безопасности

Набор узлов ACP с сертификатами ACP из одного домена ACP и включённой функциональностью ACP автоматически «строят себя» — ACP автоматически организуется между соседними узлами ACP. Обеспечивается также самозащита — защищённые каналы ACP аутентифицируются и шифруются. Для этого не требуется настройка.

Свойство самозащиты не включает обхода неавтономных элементов, как описано в разделе 8. Самозащита ACP от внешних и, в меньшей степени, от внутренних атак описана в параграфе 10.2.

Однако безопасность ACP зависит от множества факторов, перечисленных ниже.

  • Использование сертификатов домена зависит от работы поддерживающей инфраструктуры PKI. При её компрометации защита ACP также будет скомпрометирована. Обычно это контролирует администратор сети.

  • Узлы ACP получают свои сертификаты от регистраторов ACP. Регистраторы ACP критически важны для безопасности ACP. Процедуры и протоколы для регистраторов ACP выходят за рамки спецификации, как указано в параграфе 6.11.7.1, заданы лишь требования для сертификатов ACP.

  • Каждый регистратор ACP (для зачисления сертификатов ACP) и сервер ACP EST (для обновления сертификатов ACP) важен для безопасности и его протоколы также важны для защиты. Те и другие должны быть защищены от атак, подобно CA и их протоколам. Враждебный регистратор может зачислить вредоносные узлы в сеть ACP (если CA предоставляет это регистратору) или нарушить маршрутизацию ACP, например, допуская дубликаты адресов ACP на узлах ACP по их сертификатам ACP.

  • Узлы ACP, являющиеся узлами ANI полагаются на BRSKI как протокол для регистраторов ACP. К узлам ACP типа ANI применимы соображения безопасности для BRSKI, обеспечивающего автоматическое, защищённое зачисление сертификатов ACP.

  • BRSKI и, возможно, другие варианты протокола регистратора ACP требуют, чтобы узлы имели IDevID (на основе X.509 v3). IDevID являются опцией регистраторов ACP для безопасного отождествления узлов-кандидатов в ACP, которые следует зачислить в домен ACP.

  • Чтобы IDevID надёжно идентифицировали узлы, которым они назначены, узлы должны (1) использовать аппаратную поддержку, такую как модуль TPM для защиты от извлечения и/или клонирования секретного ключа IDevID и (2) апаратную или программную инфраструктуру для запрета исполнения неразрешённых программ с целью защиты от вредоносного использования IDevID.

  • Как и IDevID, сертификаты ACP должны быть в равной степени защищены от извлечения и других злоупотреблений той же инфраструктурой узла ACP. Эта инфраструктура защиты IDevID и сертификата ACP полезна независимо от применяемого регистратором ACP протокола (BRSKI или иной).

  • Для обновления сертификатов ACP нужна поддержка EST, поэтому соображения безопасности из [RFC7030], связанные с обновлением сертификатов, заменой ключей и обновлением TP применимы и к ACP. Вопросы безопасности EST, отличные от применяемых при взаимной аутентификации сертификатов, не применимы. Не рассматриваются также вопросы безопасности начального развёртывания через EST, за исключением узлов ACP типа ANI, поскольку в BRSKI применяется EST.

  • Вредоносный узел ACP может объявить себя сервером EST через GRASP в ACP, если на узле могут быть выполнены враждебные программы. Поэтому CA следует аутентифицировать только заведомо доверенные серверы EST, такие как узлы с аппаратной защитой от враждебных программ. Когда регистраторы применяют свой сертификат ACP для аутентификации по отношению к CA, атрибут расширенного использования ключей id-kp-cmcRA [RFC6402] позволяет CA определить, что узлу ACP разрешено выступать при зачислении как регистратору ACP. Без такого взаимодействия с CA враждебный сервер EST может привлекать узлы ACP, пытающиеся обновить свой ключевой материал, но они не смогут обновить действительный сертификат ACP. Узел ACP, пытающийся использовать враждебный сервер EST, может после этого обратиться к другому серверу EST и зарегистрировать отказ злонамеренного сервера EST.

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

  • При отсутствии возможности внедрить враждебный код атакующий может исказить настройку узла ACP, поддерживающего функциональность сервера EST, и попытаться настроить вредоносный CA. Это не позволит обновить сертификаты ACP, но может привести к DoS-атаке, если враждебный узел станет сервером EST и заставит узлы ACP пытаться обновить свои сертификаты ACP через повреждённый узел. Этой проблемы можно избежать, если реализация сервера EST может проверять полномочия настроенного CA обновлять сертификаты ACP для узлов. Такая возможность зависит от протокола между сервером EST и CA, который выходит за рамки этого документа.

Атаки на зависимости ACP от PKI и сертификатов можно минимизировать разными аппаратными и программными компонентами, включая TPM для IDevID и сертификатов ACP, запреты на выполнение недоверенных программ, аспекты функциональности сервера EST для ACP избавляющие от повреждений на уровне конфигурации.

Поскольку партнёры выбирают один из взаимно поддерживаемых протоколов защищённого канала ACP с помощью подхода, описанного в параграфе 6.6, организация защищённого канала ACP подвержена MITM-атакам с понижением. Последствия такой атаки могут быть обнаружены с помощью дополнительных механизмов, описанных в Приложении A.9.9. Как вариант, могут быть разработаны новые выбора протокола механизмы защиты канала.

Модель безопасности ACP, заданная в этом документе, рассчитана на использование частной инфраструктуры PKI. TA в приватных PKI обеспечивают защиту от злонамеренно созданных сертификатов ACP при доступе в ACP. Такие атаки могут создавать фиктивные сертификаты ACP с корректными на вид AcpNodeNames, но эти сертификаты не пройдут проверку пути сертификации при контроле принадлежности к домену ACP (п. 2 в параграфе 6.2.3).

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

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

В ACP применяется проверка подлинности и полномочий партнёров по сертификатам ACP. Такая модель защиты необходима для поддержки автономной специализированной связности «каждый с каждым» между узлами ACP. Защита инфраструктуры обеспечивается пошаговой (hop-by-hop) аутентификацией и шифрованием без привлечения третьей стороны. Для любых служб, где подходит эта полностью автономная модель безопасности одноранговых групп (например, для защиты протоколов маршрутизации в плоскости данных), сертификат ACP можно применять без изменений.

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

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

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

Службам верхнего уровня, созданным с применением сертификатов ACP, не следует полагаться лишь на недифференцированную групповую защиту, если другая модель подходит больше или лучше защищена. Например, централизованная настройка сети полагается на модель защиты, где лишь немногим особо доверенным узлам разрешено настраивать плоскость данных узлов сети (CLI, NETCONF). Это можно сделать с помощью сертификатов ACP путём их разделения и введения ролей (A.9.5. Назначение роли).

Операторам и разработчикам программ обеспечения необходимо знать как обеспечения и конфигурация сетевых устройств влияют на возможности оператора и обеспечивающих программ удалённо обращаться к узлам сети. При использовании ACP большинство проблем обеспечения и настройки, вызывающих потери связности для удалённого обеспечения и настройки можно предотвратить (см. раздел 6). Остаётся лишь несколько проблем, таких как явное физическое отключение устройства (9.3.2. Состояние admin down).

Многие аспекты ACP разработаны с учётом безопасности и эти вопросы рассмотрены в тексте документа.

Адреса IPv6, используемые узлами ACP учитываются в сертификате домена для узла, как описано в параграфе 6.2.2. Это позволяет проверить владение партнёром адресом IPv6 при аутентификации соединений по сертификату домена.

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

ACP обеспечивает защищённое, отказоустойчивое автоматическое (zero-touch) обнаружение серверов EST для обновления сертификатов (6.2.5. Поддержка сертификата и привязки доверия).

ACP обеспечивает расширяемую, автоматически настраиваемую поэтапную (hop-by-hop) защиту инфраструктуры ACP путём согласования протоколов поэтапной защиты каналов (6.6. Выбор канала).

Плоскость ACP разработана для минимизации атак извне путём сокращения зависимости от операцией и конфигурации не-ACP (плоскость данных) на узле (6.13.2. Адресация на защищённых каналах).

В сочетании с BRSKI плоскость ACP обеспечивает отказоустойчивое полностью автоматизированное (zero-touch) сетевое решения для краткосрочных сертификатов, которые могут быть обновлены или заново зачислены даже после непреднамеренного истечения срока действия (например, при прерывании связности). См. Приложение A.2.

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

В параграфе 7.2 описан способ реализации маршрутизируемой топологии ACP, работающей, фактически, в большом домене мостов при использовании маршрутизаторов L3/L2, работающих в плоскости данных на уровне L2. В этом случае плоскость ACP гораздо сильнее подвержена атакам других узлов, «крадущих» адреса L2, чем в случае реальной маршрутизации, особенно при включении в сеть мостов недоверенных устройств, таких как хосты. Это общая проблема ЛВС L2. Устройства L2/L3 зачастую уже имеют ту или иную форму защиты портов (port security) для предотвращения этого. Они полагаются на протокол обнаружения соседей (Neighbor Discovery Protocol или NDP) или обучения DHCP для связывания порта или адреса MAC с адресом IPv6 и блокировки адресов отправителей MAC/IPv6 от некорректных портов. Этот тип функций нужно включать для предотвращения DoS-атак, в частности, на ACP. Аналогично экземпляр GRASP DULL должен убедиться, что адрес IPv6 в locator-option соответствует адресу отправителя IPv6 в заголовке пакета DULL GRASP.

12. Взаимодействие с IANA

Этот документ определяет автономную плоскость управления (Autonomic Control Plane).

Для модуля ASN.1 ANIMA-ACP-2020 агентство IANA выделило значение id-mod-anima-acpnodename-2020 = 97 в реестре SMI Security for PKIX Module Identifier (1.3.6.1.5.5.7.0). Для otherName/AcpNodeName агентство IANA выделило значение id-on-AcpNodeName = 10 в реестре SMI Security for PKIX Other Name Forms (1.3.6.1.5.5.7.8).

Агентство IANA зарегистрировало указанные в таблице 2 имена в субреестре GRASP Objective Names реестра GeneRic Autonomic Signaling Protocol (GRASP) Parameters.

Таблица 2. Имена целей GRASP.

 

Название цели

Документ

AN_ACP

RFC 8994 (параграф 6.4)

SRV.est

RFC 8994 (параграф 6.2.5)

 

В этом документе выбран странно выглядящий формат SRV.<service-name>», чтобы эти имена целей соответствовали будущему упрощению реестра целей GRASP. Сегодня каждое имя в реестре целей GRASP должно явно выделяться IANA. Впредь можно будет считать, что этот тип имён целей включается в реестр автоматически для той же службы, для которой регистрируется <service-name> в соответствии с [RFC6335]. Это разъяснение является информационным и не влияет на запрошенную регистрацию.

Агентство IANA создало реестр Autonomic Control Plane (ACP) с субреестром ACP Address Type (Таблица 3).

Таблица 3. Исходные значения субреестра ACP Address Type.

 

Значение

Описание

Документ

0

Субсхемы адресации ACP Zone и ACP Manual

RFC 8994 (параграфы 6.11.3 и 6.11.4)

1

Субсхема адресации ACP Vlong

RFC 8994 (параграф 6.11.5)

2-3

Не выделены

 

Значения в субреестре ACP Address Type представляют собой числа от 0 до 3 в паре с именем (строка). Новые значения должны выделяться по процедуре Standards Action, заданной в Guidelines for Writing an IANA Considerations Section in RFCs [RFC8126].

13. Литература

13.1. Нормативные документы

[IKEV2IANA] IANA, «Internet Key Exchange Version 2 (IKEv2) Parameters», <https://www.iana.org/assignments/ikev2-parameters>.

[RFC1034] Mockapetris, P., «Domain names — concepts and facilities», STD 13, RFC 1034, DOI 10.17487/RFC1034, November 1987, <https://www.rfc-editor.org/info/rfc1034>.

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>.

[RFC3810] Vida, R., Ed. and L. Costa, Ed., «Multicast Listener Discovery Version 2 (MLDv2) for IPv6», RFC 3810, DOI 10.17487/RFC3810, June 2004, <https://www.rfc-editor.org/info/rfc3810>.

[RFC4191] Draves, R. and D. Thaler, «Default Router Preferences and More-Specific Routes», RFC 4191, DOI 10.17487/RFC4191, November 2005, <https://www.rfc-editor.org/info/rfc4191>.

[RFC4193] Hinden, R. and B. Haberman, «Unique Local IPv6 Unicast Addresses», RFC 4193, DOI 10.17487/RFC4193, October 2005, <https://www.rfc-editor.org/info/rfc4193>.

[RFC4291] Hinden, R. and S. Deering, «IP Version 6 Addressing Architecture», RFC 4291, DOI 10.17487/RFC4291, February 2006, <https://www.rfc-editor.org/info/rfc4291>.

[RFC4301] Kent, S. and K. Seo, «Security Architecture for the Internet Protocol», RFC 4301, DOI 10.17487/RFC4301, December 2005, <https://www.rfc-editor.org/info/rfc4301>.

[RFC4861] Narten, T., Nordmark, E., Simpson, W., and H. Soliman, «Neighbor Discovery for IP version 6 (IPv6)», RFC 4861, DOI 10.17487/RFC4861, September 2007, <https://www.rfc-editor.org/info/rfc4861>.

[RFC4862] Thomson, S., Narten, T., and T. Jinmei, «IPv6 Stateless Address Autoconfiguration», RFC 4862, DOI 10.17487/RFC4862, September 2007, <https://www.rfc-editor.org/info/rfc4862>.

[RFC5234] Crocker, D., Ed. and P. Overell, «Augmented BNF for Syntax Specifications: ABNF», STD 68, RFC 5234, DOI 10.17487/RFC5234, January 2008, <https://www.rfc-editor.org/info/rfc5234>.

[RFC5246] Dierks, T. and E. Rescorla, «The Transport Layer Security (TLS) Protocol Version 1.2», RFC 5246, DOI 10.17487/RFC5246, August 2008, <https://www.rfc-editor.org/info/rfc5246>.

[RFC5280] Cooper, D., Santesson, S., Farrell, S., Boeyen, S., Housley, R., and W. Polk, «Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile», RFC 5280, DOI 10.17487/RFC5280, May 2008, <https://www.rfc-editor.org/info/rfc5280>.

[RFC5954] Gurbani, V., Ed., Carpenter, B., Ed., and B. Tate, Ed., «Essential Correction for IPv6 ABNF and URI Comparison in RFC 3261», RFC 5954, DOI 10.17487/RFC5954, August 2010, <https://www.rfc-editor.org/info/rfc5954>.

[RFC6347] Rescorla, E. and N. Modadugu, «Datagram Transport Layer Security Version 1.2», RFC 6347, DOI 10.17487/RFC6347, January 2012, <https://www.rfc-editor.org/info/rfc6347>.

[RFC6550] Winter, T., Ed., Thubert, P., Ed., Brandt, A., Hui, J., Kelsey, R., Levis, P., Pister, K., Struik, R., Vasseur, JP., and R. Alexander, «RPL: IPv6 Routing Protocol for Low-Power and Lossy Networks», RFC 6550, DOI 10.17487/RFC6550, March 2012, <https://www.rfc-editor.org/info/rfc6550>.

[RFC6551] Vasseur, JP., Ed., Kim, M., Ed., Pister, K., Dejean, N., and D. Barthel, «Routing Metrics Used for Path Calculation in Low-Power and Lossy Networks», RFC 6551, DOI 10.17487/RFC6551, March 2012, <https://www.rfc-editor.org/info/rfc6551>.

[RFC6552] Thubert, P., Ed., «Objective Function Zero for the Routing Protocol for Low-Power and Lossy Networks (RPL)», RFC 6552, DOI 10.17487/RFC6552, March 2012, <https://www.rfc-editor.org/info/rfc6552>.

[RFC6553] Hui, J. and JP. Vasseur, «The Routing Protocol for Low-Power and Lossy Networks (RPL) Option for Carrying RPL Information in Data-Plane Datagrams», RFC 6553, DOI 10.17487/RFC6553, March 2012, <https://www.rfc-editor.org/info/rfc6553>.

[RFC7030] Pritikin, M., Ed., Yee, P., Ed., and D. Harkins, Ed., «Enrollment over Secure Transport», RFC 7030, DOI 10.17487/RFC7030, October 2013, <https://www.rfc-editor.org/info/rfc7030>.

[RFC7296] Kaufman, C., Hoffman, P., Nir, Y., Eronen, P., and T. Kivinen, «Internet Key Exchange Protocol Version 2 (IKEv2)», STD 79, RFC 7296, DOI 10.17487/RFC7296, October 2014, <https://www.rfc-editor.org/info/rfc7296>.

[RFC7525] Sheffer, Y., Holz, R., and P. Saint-Andre, «Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS)», BCP 195, RFC 7525, DOI 10.17487/RFC7525, May 2015, <https://www.rfc-editor.org/info/rfc7525>.

[RFC7676] Pignataro, C., Bonica, R., and S. Krishnan, «IPv6 Support for Generic Routing Encapsulation (GRE)», RFC 7676, DOI 10.17487/RFC7676, October 2015, <https://www.rfc-editor.org/info/rfc7676>.

[RFC8174] Leiba, B., «Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words», BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[RFC8221] Wouters, P., Migault, D., Mattsson, J., Nir, Y., and T. Kivinen, «Cryptographic Algorithm Implementation Requirements and Usage Guidance for Encapsulating Security Payload (ESP) and Authentication Header (AH)», RFC 8221, DOI 10.17487/RFC8221, October 2017, <https://www.rfc-editor.org/info/rfc8221>.

[RFC8247] Nir, Y., Kivinen, T., Wouters, P., and D. Migault, «Algorithm Implementation Requirements and Usage Guidance for the Internet Key Exchange Protocol Version 2 (IKEv2)», RFC 8247, DOI 10.17487/RFC8247, September 2017, <https://www.rfc-editor.org/info/rfc8247>.

[RFC8422] Nir, Y., Josefsson, S., and M. Pegourie-Gonnard, «Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS) Versions 1.2 and Earlier», RFC 8422, DOI 10.17487/RFC8422, August 2018, <https://www.rfc-editor.org/info/rfc8422>.

[RFC8446] Rescorla, E., «The Transport Layer Security (TLS) Protocol Version 1.3», RFC 8446, DOI 10.17487/RFC8446, August 2018, <https://www.rfc-editor.org/info/rfc8446>.

[RFC8610] Birkholz, H., Vigano, C., and C. Bormann, «Concise Data Definition Language (CDDL): A Notational Convention to Express Concise Binary Object Representation (CBOR) and JSON Data Structures», RFC 8610, DOI 10.17487/RFC8610, June 2019, <https://www.rfc-editor.org/info/rfc8610>.

[RFC8990] Bormann, C., Carpenter, B., Ed., and B. Liu, Ed., «GeneRic Autonomic Signaling Protocol (GRASP)», RFC 8990, DOI 10.17487/RFC8990, May 2021, <https://www.rfc-editor.org/info/rfc8990>.

[RFC8995] Pritikin, M., Richardson, M., Eckert, T., Behringer, M., and K. Watsen, «Bootstrapping Remote Secure Key Infrastructure (BRSKI)», RFC 8995, DOI 10.17487/RFC8995, May 2021, <https://www.rfc-editor.org/info/rfc8995>.

13.2. Дополнительная литература

[AR8021] IEEE, «IEEE Standard for Local and metropolitan area networks — Secure Device Identity», IEEE 802.1AR, <https://1.ieee802.org/security/802-1ar>.

[CABFORUM] CA/Browser Forum, «Certificate Contents for Baseline SSL», November 2019, <https://cabforum.org/baseline-requirements-certificate-contents/>.

[FCC] FCC, «June 15, 2020 T-Mobile Network Outage Report», A Report of the Public Safety and Homeland Security Bureau Federal Communications Commission, PS Docket No. 20-183, October 2020, <https://docs.fcc.gov/public/attachments/DOC-367699A1.docx>.

[IEEE-1588-2008] IEEE, «IEEE Standard for a Precision Clock Synchronization Protocol for Networked Measurement and Control Systems», DOI 10.1109/IEEESTD.2008.4579760, IEEE 1588-2008, July 2008, <https://standards.ieee.org/standard/1588-2008.html>.

[IEEE-802.1X] IEEE, «IEEE Standard for Local and metropolitan area networks—Port-Based Network Access Control», DOI 10.1109/IEEESTD.2010.5409813, IEEE 802.1X-2010, February 2010, <https://standards.ieee.org/standard/802_1X-2010.html>.

[LLDP] IEEE, «IEEE Standard for Local and metropolitan area networks: Station and Media Access Control Connectivity Discovery», DOI 10.1109/IEEESTD.2016.7433915, IEEE 802.1AB-2016, March 2016, <https://standards.ieee.org/standard/802_1AB-2016.html>.

[MACSEC] IEEE, «IEEE Standard for Local and Metropolitan Area Networks: Media Access Control (MAC) Security», DOI 10.1109/IEEESTD.2006.245590, IEEE 802.1AE-2006, August 2006, <https://standards.ieee.org/standard/802_1AE-2006.html>.

[NOC-AUTOCONFIG] Eckert, T., Ed., «Autoconfiguration of NOC services in ACP networks via GRASP», Work in Progress, Internet-Draft, draft-eckert-anima-noc-autoconfig-00, 2 July 2018, <https://tools.ietf.org/html/draft-eckert-anima-noc-autoconfig-00>.

[OP-TECH] Wikipedia, «Operational technology», October 2020, <https://en.wikipedia.org/w/index.php?title=Operational_technology&oldid=986363045>.

[RFC1112] Deering, S., «Host extensions for IP multicasting», STD 5, RFC 1112, DOI 10.17487/RFC1112, August 1989, <https://www.rfc-editor.org/info/rfc1112>.

[RFC1492] Finseth, C., «An Access Control Protocol, Sometimes Called TACACS», RFC 1492, DOI 10.17487/RFC1492, July 1993, <https://www.rfc-editor.org/info/rfc1492>.

[RFC1654] Rekhter, Y., Ed. and T. Li, Ed., «A Border Gateway Protocol 4 (BGP-4)», RFC 1654, DOI 10.17487/RFC1654, July 1994, <https://www.rfc-editor.org/info/rfc1654>.

[RFC1918] Rekhter, Y., Moskowitz, B., Karrenberg, D., de Groot, G. J., and E. Lear, «Address Allocation for Private Internets», BCP 5, RFC 1918, DOI 10.17487/RFC1918, February 1996, <https://www.rfc-editor.org/info/rfc1918>.

[RFC2315] Kaliski, B., «PKCS #7: Cryptographic Message Syntax Version 1.5», RFC 2315, DOI 10.17487/RFC2315, March 1998, <https://www.rfc-editor.org/info/rfc2315>.

[RFC2409] Harkins, D. and D. Carrel, «The Internet Key Exchange (IKE)», RFC 2409, DOI 10.17487/RFC2409, November 1998, <https://www.rfc-editor.org/info/rfc2409>.

[RFC2865] Rigney, C., Willens, S., Rubens, A., and W. Simpson, «Remote Authentication Dial In User Service (RADIUS)», RFC 2865, DOI 10.17487/RFC2865, June 2000, <https://www.rfc-editor.org/info/rfc2865>.

[RFC3164] Lonvick, C., «The BSD Syslog Protocol», RFC 3164, DOI 10.17487/RFC3164, August 2001, <https://www.rfc-editor.org/info/rfc3164>.

[RFC3315] Droms, R., Ed., Bound, J., Volz, B., Lemon, T., Perkins, C., and M. Carney, «Dynamic Host Configuration Protocol for IPv6 (DHCPv6)», RFC 3315, DOI 10.17487/RFC3315, July 2003, <https://www.rfc-editor.org/info/rfc3315>.

[RFC3411] Harrington, D., Presuhn, R., and B. Wijnen, «An Architecture for Describing Simple Network Management Protocol (SNMP) Management Frameworks», STD 62, RFC 3411, DOI 10.17487/RFC3411, December 2002, <https://www.rfc-editor.org/info/rfc3411>.

[RFC3596] Thomson, S., Huitema, C., Ksinant, V., and M. Souissi, «DNS Extensions to Support IP Version 6», STD 88, RFC 3596, DOI 10.17487/RFC3596, October 2003, <https://www.rfc-editor.org/info/rfc3596>.

[RFC3954] Claise, B., Ed., «Cisco Systems NetFlow Services Export Version 9», RFC 3954, DOI 10.17487/RFC3954, October 2004, <https://www.rfc-editor.org/info/rfc3954>.

[RFC4007] Deering, S., Haberman, B., Jinmei, T., Nordmark, E., and B. Zill, «IPv6 Scoped Address Architecture», RFC 4007, DOI 10.17487/RFC4007, March 2005, <https://www.rfc-editor.org/info/rfc4007>.

[RFC4210] Adams, C., Farrell, S., Kause, T., and T. Mononen, «Internet X.509 Public Key Infrastructure Certificate Management Protocol (CMP)», RFC 4210, DOI 10.17487/RFC4210, September 2005, <https://www.rfc-editor.org/info/rfc4210>.

[RFC4364] Rosen, E. and Y. Rekhter, «BGP/MPLS IP Virtual Private Networks (VPNs)», RFC 4364, DOI 10.17487/RFC4364, February 2006, <https://www.rfc-editor.org/info/rfc4364>.

[RFC4429] Moore, N., «Optimistic Duplicate Address Detection (DAD) for IPv6», RFC 4429, DOI 10.17487/RFC4429, April 2006, <https://www.rfc-editor.org/info/rfc4429>.

[RFC4541] Christensen, M., Kimball, K., and F. Solensky, «Considerations for Internet Group Management Protocol (IGMP) and Multicast Listener Discovery (MLD) Snooping Switches», RFC 4541, DOI 10.17487/RFC4541, May 2006, <https://www.rfc-editor.org/info/rfc4541>.

[RFC4604] Holbrook, H., Cain, B., and B. Haberman, «Using Internet Group Management Protocol Version 3 (IGMPv3) and Multicast Listener Discovery Protocol Version 2 (MLDv2) for Source-Specific Multicast», RFC 4604, DOI 10.17487/RFC4604, August 2006, <https://www.rfc-editor.org/info/rfc4604>.

[RFC4607] Holbrook, H. and B. Cain, «Source-Specific Multicast for IP», RFC 4607, DOI 10.17487/RFC4607, August 2006, <https://www.rfc-editor.org/info/rfc4607>.

[RFC4610] Farinacci, D. and Y. Cai, «Anycast-RP Using Protocol Independent Multicast (PIM)», RFC 4610, DOI 10.17487/RFC4610, August 2006, <https://www.rfc-editor.org/info/rfc4610>.

[RFC4985] Santesson, S., «Internet X.509 Public Key Infrastructure Subject Alternative Name for Expression of Service Name», RFC 4985, DOI 10.17487/RFC4985, August 2007, <https://www.rfc-editor.org/info/rfc4985>.

[RFC5790] Liu, H., Cao, W., and H. Asaeda, «Lightweight Internet Group Management Protocol Version 3 (IGMPv3) and Multicast Listener Discovery Version 2 (MLDv2) Protocols», RFC 5790, DOI 10.17487/RFC5790, February 2010, <https://www.rfc-editor.org/info/rfc5790>.

[RFC5880] Katz, D. and D. Ward, «Bidirectional Forwarding Detection (BFD)», RFC 5880, DOI 10.17487/RFC5880, June 2010, <https://www.rfc-editor.org/info/rfc5880>.

[RFC5905] Mills, D., Martin, J., Ed., Burbank, J., and W. Kasch, «Network Time Protocol Version 4: Protocol and Algorithms Specification», RFC 5905, DOI 10.17487/RFC5905, June 2010, <https://www.rfc-editor.org/info/rfc5905>.

[RFC5912] Hoffman, P. and J. Schaad, «New ASN.1 Modules for the Public Key Infrastructure Using X.509 (PKIX)», RFC 5912, DOI 10.17487/RFC5912, June 2010, <https://www.rfc-editor.org/info/rfc5912>.

[RFC6120] Saint-Andre, P., «Extensible Messaging and Presence Protocol (XMPP): Core», RFC 6120, DOI 10.17487/RFC6120, March 2011, <https://www.rfc-editor.org/info/rfc6120>.

[RFC6241] Enns, R., Ed., Bjorklund, M., Ed., Schoenwaelder, J., Ed., and A. Bierman, Ed., «Network Configuration Protocol (NETCONF)», RFC 6241, DOI 10.17487/RFC6241, June 2011, <https://www.rfc-editor.org/info/rfc6241>.

[RFC6335] Cotton, M., Eggert, L., Touch, J., Westerlund, M., and S. Cheshire, «Internet Assigned Numbers Authority (IANA) Procedures for the Management of the Service Name and Transport Protocol Port Number Registry», BCP 165, RFC 6335, DOI 10.17487/RFC6335, August 2011, <https://www.rfc-editor.org/info/rfc6335>.

[RFC6402] Schaad, J., «Certificate Management over CMS (CMC) Updates», RFC 6402, DOI 10.17487/RFC6402, November 2011, <https://www.rfc-editor.org/info/rfc6402>.

[RFC6407] Weis, B., Rowles, S., and T. Hardjono, «The Group Domain of Interpretation», RFC 6407, DOI 10.17487/RFC6407, October 2011, <https://www.rfc-editor.org/info/rfc6407>.

[RFC6554] Hui, J., Vasseur, JP., Culler, D., and V. Manral, «An IPv6 Routing Header for Source Routes with the Routing Protocol for Low-Power and Lossy Networks (RPL)», RFC 6554, DOI 10.17487/RFC6554, March 2012, <https://www.rfc-editor.org/info/rfc6554>.

[RFC6724] Thaler, D., Ed., Draves, R., Matsumoto, A., and T. Chown, «Default Address Selection for Internet Protocol Version 6 (IPv6)», RFC 6724, DOI 10.17487/RFC6724, September 2012, <https://www.rfc-editor.org/info/rfc6724>.

[RFC6733] Fajardo, V., Ed., Arkko, J., Loughney, J., and G. Zorn, Ed., «Diameter Base Protocol», RFC 6733, DOI 10.17487/RFC6733, October 2012, <https://www.rfc-editor.org/info/rfc6733>.

[RFC6762] Cheshire, S. and M. Krochmal, «Multicast DNS», RFC 6762, DOI 10.17487/RFC6762, February 2013, <https://www.rfc-editor.org/info/rfc6762>.

[RFC6763] Cheshire, S. and M. Krochmal, «DNS-Based Service Discovery», RFC 6763, DOI 10.17487/RFC6763, February 2013, <https://www.rfc-editor.org/info/rfc6763>.

[RFC6824] Ford, A., Raiciu, C., Handley, M., and O. Bonaventure, «TCP Extensions for Multipath Operation with Multiple Addresses», RFC 6824, DOI 10.17487/RFC6824, January 2013, <https://www.rfc-editor.org/info/rfc6824>.

[RFC6830] Farinacci, D., Fuller, V., Meyer, D., and D. Lewis, «The Locator/ID Separation Protocol (LISP)», RFC 6830, DOI 10.17487/RFC6830, January 2013, <https://www.rfc-editor.org/info/rfc6830>.

[RFC7011] Claise, B., Ed., Trammell, B., Ed., and P. Aitken, «Specification of the IP Flow Information Export (IPFIX) Protocol for the Exchange of Flow Information», STD 77, RFC 7011, DOI 10.17487/RFC7011, September 2013, <https://www.rfc-editor.org/info/rfc7011>.

[RFC7404] Behringer, M. and E. Vyncke, «Using Only Link-Local Addressing inside an IPv6 Network», RFC 7404, DOI 10.17487/RFC7404, November 2014, <https://www.rfc-editor.org/info/rfc7404>.

[RFC7426] Haleplidis, E., Ed., Pentikousis, K., Ed., Denazis, S., Hadi Salim, J., Meyer, D., and O. Koufopavlou, «Software-Defined Networking (SDN): Layers and Architecture Terminology», RFC 7426, DOI 10.17487/RFC7426, January 2015, <https://www.rfc-editor.org/info/rfc7426>.

[RFC7435] Dukhovni, V., «Opportunistic Security: Some Protection Most of the Time», RFC 7435, DOI 10.17487/RFC7435, December 2014, <https://www.rfc-editor.org/info/rfc7435>.

[RFC7575] Behringer, M., Pritikin, M., Bjarnason, S., Clemm, A., Carpenter, B., Jiang, S., and L. Ciavaglia, «Autonomic Networking: Definitions and Design Goals», RFC 7575, DOI 10.17487/RFC7575, June 2015, <https://www.rfc-editor.org/info/rfc7575>.

[RFC7576] Jiang, S., Carpenter, B., and M. Behringer, «General Gap Analysis for Autonomic Networking», RFC 7576, DOI 10.17487/RFC7576, June 2015, <https://www.rfc-editor.org/info/rfc7576>.

[RFC7585] Winter, S. and M. McCauley, «Dynamic Peer Discovery for RADIUS/TLS and RADIUS/DTLS Based on the Network Access Identifier (NAI)», RFC 7585, DOI 10.17487/RFC7585, October 2015, <https://www.rfc-editor.org/info/rfc7585>.

[RFC7721] Cooper, A., Gont, F., and D. Thaler, «Security and Privacy Considerations for IPv6 Address Generation Mechanisms», RFC 7721, DOI 10.17487/RFC7721, March 2016, <https://www.rfc-editor.org/info/rfc7721>.

[RFC7761] Fenner, B., Handley, M., Holbrook, H., Kouvelas, I., Parekh, R., Zhang, Z., and L. Zheng, «Protocol Independent Multicast — Sparse Mode (PIM-SM): Protocol Specification (Revised)», STD 83, RFC 7761, DOI 10.17487/RFC7761, March 2016, <https://www.rfc-editor.org/info/rfc7761>.

[RFC7950] Bjorklund, M., Ed., «The YANG 1.1 Data Modeling Language», RFC 7950, DOI 10.17487/RFC7950, August 2016, <https://www.rfc-editor.org/info/rfc7950>.

[RFC8028] Baker, F. and B. Carpenter, «First-Hop Router Selection by Hosts in a Multi-Prefix Network», RFC 8028, DOI 10.17487/RFC8028, November 2016, <https://www.rfc-editor.org/info/rfc8028>.

[RFC8126] Cotton, M., Leiba, B., and T. Narten, «Guidelines for Writing an IANA Considerations Section in RFCs», BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017, <https://www.rfc-editor.org/info/rfc8126>.

[RFC8316] Nobre, J., Granville, L., Clemm, A., and A. Gonzalez Prieto, «Autonomic Networking Use Case for Distributed Detection of Service Level Agreement (SLA) Violations», RFC 8316, DOI 10.17487/RFC8316, February 2018, <https://www.rfc-editor.org/info/rfc8316>.

[RFC8366] Watsen, K., Richardson, M., Pritikin, M., and T. Eckert, «A Voucher Artifact for Bootstrapping Protocols», RFC 8366, DOI 10.17487/RFC8366, May 2018, <https://www.rfc-editor.org/info/rfc8366>.

[RFC8368] Eckert, T., Ed. and M. Behringer, «Using an Autonomic Control Plane for Stable Connectivity of Network Operations, Administration, and Maintenance (OAM)», RFC 8368, DOI 10.17487/RFC8368, May 2018, <https://www.rfc-editor.org/info/rfc8368>.

[RFC8398] Melnikov, A., Ed. and W. Chuang, Ed., «Internationalized Email Addresses in X.509 Certificates», RFC 8398, DOI 10.17487/RFC8398, May 2018, <https://www.rfc-editor.org/info/rfc8398>.

[RFC8402] Filsfils, C., Ed., Previdi, S., Ed., Ginsberg, L., Decraene, B., Litkowski, S., and R. Shakir, «Segment Routing Architecture», RFC 8402, DOI 10.17487/RFC8402, July 2018, <https://www.rfc-editor.org/info/rfc8402>.

[RFC8572] Watsen, K., Farrer, I., and M. Abrahamsson, «Secure Zero Touch Provisioning (SZTP)», RFC 8572, DOI 10.17487/RFC8572, April 2019, <https://www.rfc-editor.org/info/rfc8572>.

[RFC8684] Ford, A., Raiciu, C., Handley, M., Bonaventure, O., and C. Paasch, «TCP Extensions for Multipath Operation with Multiple Addresses», RFC 8684, DOI 10.17487/RFC8684, March 2020, <https://www.rfc-editor.org/info/rfc8684>.

[RFC8739] Sheffer, Y., Lopez, D., Gonzalez de Dios, O., Pastor Perales, A., and T. Fossati, «Support for Short-Term, Automatically Renewed (STAR) Certificates in the Automated Certificate Management Environment (ACME)», RFC 8739, DOI 10.17487/RFC8739, March 2020, <https://www.rfc-editor.org/info/rfc8739>.

[RFC8981] Gont, F., Krishnan, S., Narten, T., and R. Draves, «Temporary Address Extensions for Stateless Address Autoconfiguration in IPv6», RFC 8981, DOI 10.17487/RFC8981, February 2021, <https://www.rfc-editor.org/info/rfc8981>.

[RFC8992] Jiang, S., Ed., Du, Z., Carpenter, B., and Q. Sun, «Autonomic IPv6 Edge Prefix Management in Large-Scale Networks», RFC 8992, DOI 10.17487/RFC8992, May 2021, <https://www.rfc-editor.org/info/rfc8992>.

[RFC8993] Behringer, M., Ed., Carpenter, B., Eckert, T., Ciavaglia, L., and J. Nobre, «A Reference Model for Autonomic Networking», RFC 8993, DOI 10.17487/RFC8993, May 2021, <https://www.rfc-editor.org/info/rfc8993>.

[ROLL-APPLICABILITY] Richardson, M., «ROLL Applicability Statement Template», Work in Progress, Internet-Draft, draft-ietf-roll-applicability-template-09, 3 May 2016, <https://tools.ietf.org/html/draft-ietf-roll-applicability-template-09>.

[SR] Wikipedia, «Single-root input/output virtualization», September 2020, <https://en.wikipedia.org/w/index.php?title=Single-root_input/output_virtualization&oldid=978867619>

[TLS-DTLS13] Rescorla, E., Tschofenig, H., and N. Modadugu, «The Datagram Transport Layer Security (DTLS) Protocol Version 1.3», Work in Progress11, Internet-Draft, draft-ietf-tls-dtls13-43, 30 April 2021, <https://tools.ietf.org/html/draft-ietf-tls-dtls13-43>.

[X.509] ITU-T, «Information technology — Open Systems Interconnection — The Directory: Public-key and attribute certificate frameworks», ITU-T Recommendation X.509, October 2016, <https://www.itu.int/rec/T-REC-X.509>.

[X.520] ITU-T, «Information technology — Open Systems Interconnection — The Directory: Selected attribute types», ITU-T Recommendation X.520, October 2016, <https://www.itu.int/rec/T-REC-X.520>.

Приложение A. Основы и будущее (информационный раздел)

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

A.1. Схемы адресного пространства ACP

Этот документ определяет субсхемы адресации Zone, Vlong, Manual прежде всего для поддержки назначения адресных префиксов через распределенные, потенциально не согласованные регистраторы ACP, как указано в параграфе 6.11.7. Требуется 48/46-битовый идентификатор, чтобы эти регистраторы ACP могли назначать не конфликтующие префиксы адресов. Такое решение не оставляет достаточно битов для одновременной поддержки большого числа узлов (Node-ID), больших префиксов локальных адресов на каждом узле и достаточно большого набора битов для указания зоны маршрутизации. В результате субсхемы Zone и Vlong 8/16 пытаются поддерживать все свойства через раздельные префиксы.

В сетях, предполагающих всегда полагаться на централизованную систему PMS, как описано в параграфе 9.2.5, можно сохранить 48/46-битовые Registrar-ID. Такие вариации механизмов адресации ACP могут быть введены в будущих работах различными способами. При введении нового otherName можно было бы создать несовместимые вариации ACP, где можно изменить каждый аспект устройства ACP, включая выбор адресации. Если вместо этого задать новую субсхему адресации, она может быть совместимой с текущей спецификацией ACP. Такие сведения, как размер префикса зоны и префикса, выделенного самому узлу ACP, можно кодировать в поле расширения acp-node-name.

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

A.2. Начальная загрузка BRSKI (ANI)

BRSKI описывает, как узлы с сертификатом IDevID можно безопасно автоматическим (zero-touch) регистрировать по их сертификату LDevID для поддержки ACP. BRSKI также применяет ACP для поддержки автоматической (zero-touch) начальной загрузки через сети без каких-либо требований к конфигурации транзитных узлов (например, DHCP, пересылка DNS, организация сервера). Это включает ненастроенные в остальном сети, как указано в параграфе 3.2. Поэтому BRSKI в сочетании с ACP обеспечивает защищённое и автоматическое (zero-touch) решения для управления целыми сетями. Узлы, поддерживающие такую инфраструктуру (BRSKI и ACP) зазывают узлами ANI (Autonomic Networking Infrastructure, см [RFC8993]). Узлы, которые не поддерживают сертификат IDevID и имеют лишь (незащищённый) уникальный идентификатор устройства (Unique Device Identifier или UDI) от производителя или узлы, производитель которых не поддерживает MASA могут использовать будущую версию BRSKI со сниженной защитой.

При использовании BRSKI для предоставления сертификата домена (зачисления), регистратор BRSKI (выступающий как расширенный сервер EST) должен включать закодированный в otherName/AcpNodeName адрес ACP и имя домена для зачисляемого узла (заявитель) в свой отклик на запрос атрибутов заявителя EST CSR, обязательный в BRSKI.

CA в сети ACP недопустимо менять otherName/AcpNodeName в сертификатах. Поэтому узлы ACP могут найти свои адреса ACP и домен по этому полю в сертификатах домена как для себя, так и для других узлов.

Применение BRSKI вместе с ACP может дополнительно упростить обслуживание и обновление сертификатов домена. Можно, не полагаясь на CRL, сделать срок действия сертификатов очень коротким, например, в несколько часов. Когда узлу не удаётся подключиться к ACP в течение срока действия сертификата, он не сможет подключиться к ACP для обновления сертификата (просто используя EST), но может обновить его как зачисленный заявитель с истекшим сроком через прокси начальной загрузки BRSKI. Для этого требуется лишь признание регистратором BRSKI просроченных сертификатов домена и выполнение заявителем аутентификации TLS для начальной загрузки BRSKI с использованием сертификата домена, прежде чем вернуться к применению сертификата IDevID для BRSKI. Этот механизм может сделать CRL ненужными, поскольку регистратор BRSKI в сочетании с CA не будет обновлять отозванные сертификаты — потребуется лишь список Do-not-renew (не обновлять) у регистратора BRSKI или CA.

В отсутствие BRSKI или менее защищённых вариантов предоставление сертификатов может включать одно или несколько действий или нестандартную автоматизацию. Производители узлов обычно поддерживают предоставление сертификатов узлам через PKCS #7 (PKCS #7: Cryptographic Message Syntax Version 1.5 [RFC2315]) и могут поддерживать предоставление через фирменные модели по протоколу NETCONF (Network Configuration Protocol (NETCONF) [RFC6241]). Если такие узлы поддерживают NETCONF Zero Touch [RFC8572], это можно комбинировать с автоматическим (zero-touch) предоставлением сертификатов узлам. Однако без эквивалентной интеграции соединений NETCONF через ACP, как в BRSKI, эта комбинация не сможет поддерживать автоматическую начальную загрузку через ненастроенную сеть.

A.3. Выбор протокола обнаружения соседей ACP

В этом приложении обосновывается выбор GRASP DULL в качестве протокола обнаружения смежных на уровне L2 узлов в качестве кандидатов в соседи ACP. Рассматривалиь также варианты GRASP, mDNS, LLDP.

A.3.1. LLDP

LLDP и более ранний протокол Cisco CDP (Cisco Discovery Protocol) являются примерами протоколов обнаружения L2, которые завершают свои сообщения на портах L2. Если бы эти протоколы были выбраны для обнаружения соседей ACP, процесс обнаружения также завершался бы на портах L2. Это помешало бы созданию ACP через коммутаторы без поддержки ACP, поддерживающие LLDP или CDP. LLDP имеет расширения, использующие разные MAC-адреса, и это можно было бы применить для обнаружения в ACP, но требуемая дополнительная стандартизация в IEEE и определение профиля для такого изменённого варианта LLDP показались требующими слишком большой работы по сравнению с преимуществами от использования имеющегося протокола LLDP для этой очень простой задачи.

A.3.2. mDNS и поддержка L2

Протокол Multicast DNS (mDNS) (Multicast DNS [RFC6762]) с записями о ресурсах DNS Service Discovery (DNS-SD) , определёнными в DNS-Based Service Discovery [RFC6763] был основным претендентом на роль протокола обнаружения в ACP. Поскольку протокол основан на групповой адресации IP link-local, он работает на уровне подсети и встречается в коммутаторах L2. Авторы документа не знают реализаций mDNS, завершающих свои сообщения mDNS на портах L2 вместо уровня подсети. При использовании mDNS как протокола обнаружения в ACP на коммутаторе (L3)/L2 с поддержкой ACP, как описано в разделе 7, это потребовалось бы реализовать. Вполне вероятно, что завершение соединений mDNS может применяться только ко всем сообщениям mDNS от такого порта, что затем потребует программной пересылки всех не относящихся к ACP сообщений mDNS для поддержки поддержки прежней функциональности mDNS, не связанной с ACP. Таким образом, добавление поддержки ACP на таких коммутаторах L2 с mDNS может создать проблемы возвращения к прежней функциональности mDNS на этих узлах. С учётом низкой производительности программной пересылки во многих коммутаторах L2, это могло сделать поддержку ACP на таких коммутаторах L2 рискованной.

A.3.3. Почему DULL GRASP?

LLDP не подошёл из-за отмеченных выше проблем, а MDNS не был выбран с учётом приведённых соображений для L2 mDNS и указанных ниже обстоятельств.

Если mDNS ещё нет на узле, его реализация потребует больше работы по сравнению с реализацией DULL GRASP, а если применять имеющуюся реализацию mDNS, вероятно потребуется больший объем кода, нежели для отдельной реализации DULL GRASP или общей реализации DULL GRASP и GRASP в ACP.

A.4. Выбор протокола маршрутизации (RPL)

В этом приложении приведены мотивы выбора RPL (IPv6 Routing Protocol for Low-Power and Lossy Networks [RFC6550]) в качестве принятого по умолчанию (в этой спецификации единственного) протокола маршрутизации для ACP. Выбор и приведённый выше профиль были основаны на предстандартной реализации ACP, успешно развёрнутой в действующих сетях. Требования к маршрутизации в ACP указаны ниже.

  • Самоуправление. Плоскость ACP должна создаваться автоматически, без участия человека, поэтому протокол маршрутизации также должен работать автоматически. RPL является простым протоколом с самоуправления, который не требует зон или областей. Он также самостоятельно настраивается, поскольку конфигурация передаётся как часть протокола (параграф 6.7.6 в [RFC6550]).

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

  • Малое потребление ресурсов. ACP поддерживает традиционную инфраструктуру сети, поэтому работает в дополнение к традиционным протоколам. ACP и особенно протокол маршрутизации должны потреблять немного ресурсов памяти и CPU. В частности, на граничных узлах, где мало таких ресурсов, их потребление следует минимизировать. RPL создаёт дерево DODAG, где основным потребителем ресурсов является корень DODAG. Чем ближе граница сети, тем меньше состояний нужно поддерживать. Это подходит для типового устройства сетей. Кроме того, все изменения ниже общего предка сохраняются ниже родительского узла.

  • Поддержка неструктурированного пространства адресов. В ANI адреса узлов служат идентификаторами и могут назначаться без учёта топологии. Кроме того, узлы могут перемещаться в топологии без смены адреса. Поэтому протокол маршрутизации должен поддерживать неструктурированное пространство адресов. Протокол RPL разработан для мобильных специализированных (ad hoc) сетей без допущений о топологической привязке адресов.

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

  • Расширяемость. Поскольку концепция ANI является новой, вполне вероятны изменения в её работе со временем. RPL позволяет добавлять целевые функции, которые могут менять способ создания деревьев DAG протоколом маршрутизации.

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

  • Отсутствие требования к оптимизации пути. RPL не обязательно рассчитывает оптимальный путь между двумя узлами. Сегодня ACP этого не требует, поскольку работает в основном с нечувствительными к задержкам контурами обратной связи. В будущем могут потребоваться иные схемы оптимизации, но RPL можно расширить (см. выше).

A.5. Распространение информации ACP и групповая передача

Групповая передача IP не применяется в ACP, поскольку в ANI это не требуется и нужно лишь для анонсирования и обнаружения служб. Применение групповой передачи IP потребовало бы разработки решения по автоматической (zero-touch) настройке конфигурации для ASM (Any Source Multicast — исходная форма групповой передачи IP из Host extensions for IP multicasting [RFC1112]), что было бы достаточно сложно и необоснованно. Одним из аспектов сложности, для которого в документах IETF не предпринималось попыток решения, является автоматический выбор маршрутизаторов на роль «точек встречи независимой от протокола групповой передачи в разреженном режиме» (PIM Sparse Mode (PIM-SM) Rendezvous Point (RP), см. Protocol Independent Multicast — Sparse Mode (PIM-SM): Protocol Specification (Revised) [RFC7761]). Другим аспектом сложности является реализация MLD (Using Internet Group Management Protocol Version 3 (IGMPv3) and Multicast Listener Discovery Protocol Version 2 (MLDv2) for Source-Specific Multicast [RFC4604]), PIM-SM и Anycast-RP (Anycast-RP Using Protocol Independent Multicast (PIM) [RFC4610]). Если такие реализации уже имеются в проукции, они скорей всего будут привязаны к ускоренной пересылке, потребляющей аппаратные ресурсы, что сложно оправдать затратами лишь на обнаружение служб.

Будущие агенты ASA могут потребовать высокопроизводительной репликации данных в сети. В этом случае будет оправдано применение групповой передачи IP. Такие ASA могут применять обнаружение служб ACP GRASP и тогда им для репликации потребуется не ASM, а лишь SSM (Source-Specific Multicast for IP [RFC4607]). SSM можно просто включить в плоскости данных (или даже в обновлении ACP) без какой-либо настройки свех включения на всех узлах и для этого нужна лишь простая версия MLD (Lightweight Internet Group Management Protocol Version 3 (IGMPv3) and Multicast Listener Discovery Version 2 (MLDv2) Protocols [RFC5790]).

Протоколы маршрутизации IGP на основе протокола состояния канала (Link State Protocol или LSP) обычно имеют механизм лавинной рассылки информации и такой механизм может служить для лавинной рассылки целей GRASP путём задания их как информации IGP. Это могло бы быть оптимизацией для будущих версий ACP с протоколом маршрутизации на основе LSP. Однако такой механизм не будет легко работать для сообщений GRASP M_DISCOVERY, для которых применяется интеллектуальная (ограниченная) лавинная рассылка не через всю ACP, а лишь узлу, где найден ответчик. Предполагается, что многие будущие службы в ASA будут иметь лишь несколько потребляющих ASA, а для этого метод M_DISCOVERY эффективней лавинной рассылки через весь домен.

Поскольку в ACP применяется RPL, желательным расширением будет использование имеющегося в RPL понятия DODAG (дерево распространения без петель) для повышения эффективности лавинной рассылки GRASP для M_FLOOD и M_DISCOVERY. В параграфе 6.13.5 указано, как это будет полезно для интерфейсов NBMA. В настоящее время это не задано в документе, поскольку ещё не совсем понятно, как будет влиять на лавинную рассылку GRASP время схождения RPL DODAG и сколь сложно будет лавинной рассылке GRASP получить доступ к дереву DODAG.

A.6. CA, домены и маршрутные субдомены

Имеется много решений по установке ACP с подобающим использованием CA, домена и элементов rsub в acp-node-name сертификата домена. Эти варианты обобщены здесь, поскольку они описаны в разных частях документа. Рассмотрены также возможные и желаемые расширения.

Домен ACP — это множество всех узлов ACP которые могут аутентифицировать друг друга, как принадлежащих к одной сети ACP путём проверки принадлежности к домену ACP (6.2.3. Проверка принадлежности к домену ACP). GRASP в ACP работает через все транзитивно соединённые узлы ACP в домене. Элемент rsub в acp-node-name разрешает применение адресов из разных префиксов ULA. Одним из вариантов использования является сведение множества физических сетей, которые исходно разделены и имеют один домен ACP с разными субдоменами маршрутизации, чтобы все узлы могли взаимно доверять сертификатам ACP (независимо от rsub) и могли позднее объединиться в непрерывную сеть ACP. Одним из примеров такого решения является ACP для регионов, соединённых через ядро без поддержки ACP, скажем, по причине отсутствия решения с ACP для маршрутизаторов ядра. Конфигурации ACP connect, определённые в этом документе, могут служить для расширения и соединения этих островков ACP с NOC и слияния в одну плоскость ACP, когда появятся нужные решения для маршрутизаторов ядра.

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

Если нужно создать домена ACP, которым по умолчанию не разрешено соединяться между собой, просто используются разные элементы domain в acp-node-name. Эти элементы могут быть произвольными, в том числе иерархическими — домены example.com и research.example.com будут раздельными, если оба значения указаны в элементах domain в acp-node-name соответствующих сертификатов.

Не требуется иметь разные CA для разных доменов ACP, оператор может предоставлять один CA для подписывания сертификатов множества доменов ACP, которым не разрешено соединяться между собой, поскольку проверка смежности в ACP включает сравнение domain.

Если несколько независимых сетей используют одно имя домена, но в каждой используются свои CA, эти сети не образуют одного домена ACP, поскольку CA различаются. Поэтому не возникает проблемы выбора доменного имени, которое может использовать кто-то ещё. Тем не менее, настоятельно рекомендуется выбирать для доменов имена, которые с большой вероятностью будут уникальны. Рекомендуется использовать доменные имена, содержащие имя домена в DNS, принадлежащего назначающей организации, и уникальный в рамках организации префикс, например, acp.example.com в домене example.com.

A.7. Намерения для ACP

Намерения (Intent) — это компонент архитектуры автономных сетей (Autonomic Networks) [RFC8993], позволяющий операторам задавать правила для сети. Применимость намерений достаточно широка и гибка, возможным применением является лавинная рассылка политики через ACP GRASP и её интерпретация каждым узлом ACP.

Одной из проблем будущих определений для намерений является проблема циклических зависимостей при выражении намерений для самой плоскости ACP. Например, намерения могут указывать желание собрать ACP из всех доменов, имеющих общий родительский домен (не полагаясь на решение rsub для субдоменов маршрутизации, заданное в документе) — узлам ACP из доменов example.com, access.example.com, core.example.com, city.core.example.com следует создать одну плоскость ACP.

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

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

Если домены используют общий CA, они могут изменить настройку ACP, чтобы разрешить соединения ACP между узлами ACP с разными acp-domain-name, но лишь для распространения ограниченных сведений, таких как намерения (Intent), но не для организации полной связности ACP, в частности, не будет маршрутизации RPL и передачи произвольных сведений GRASP, пока правила Intent не позволят делать это через границы доменов.

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

A.8. Адаптация концепций ACP для других сред

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

ACP задаёт применение ULA и вывод префикса по имени домена, чтобы не требовалось выделять адреса для развёртывания ACP. Плоскость ACP будет одинаково работать с любым префиксом IPv6 /48, а не только с ULA. Этот префикс может быть просто параметром регистраторов ACP (например, при использовании BRSKI) для зачисления сертификатов домена вместо вывода регистратором ACP префикса ULA /48 из имени домена автономной сети (AN).

В некоторых решениях уже может быть схема автоматической адресации, выведенная, например, из уникальных идентификаторов устройств (скажем, MAC). В этих случаях выделение адресов через поле адресных сведений ACP, описанное в документе, может быть нежелательно. Сертификат может просто служить для указания домена ACP, а поле адреса можно опустить. Единственное исправление, которое потребуется для оставшегося способа работы ACP, заключается в задании другого элемента в сертификате домена для распределения между двумя партнёрами ролей Decider и Follower при организации защищённого канала. Отметим, что в будущих работах адрес ACP может служить для аутентификации принадлежности адреса устройству. Если применяемый устройством адрес ACP выводится из имеющегося постоянного локального идентификатора (такого как MAC-адрес), будет полезно внести его в сертификат.

ACP определяется как отдельный экземпляр VRF, поскольку предназначена для поддержки хорошо управляемых сетей с широким набором конфигураций. Поэтому надёжная, не нарушаемая настройками связность может быть получена от самой плоскости данных. В решениях, где все функции, влияющие на транзитную связность (включая защиту), автоматизированы, неразрушаемы и устойчивы к отказам, можно было бы исключить потребность ACP быть отдельным экземпляром VRF. Рассмотрим простой пример системы, в которой нет отдельной плоскости данных, а её роль играет ACP. Добавление BRSKI делает её полностью автономной сетью (AN), за исключением того, что не поддерживается автоматическая адресация оборудования. Это можно исправить, добавив решение на основе Autonomic IPv6 Edge Prefix Management in Large-Scale Networks [RFC8992].

TCP/TLS как протоколы, обеспечивающие надёжность и безопасность GRASP в ACP могут не оказаться предпочтительными в сетях с ограничениями. Например, протокол CoAP/DTLS (Constrained Application Protocol) может быть лучше, если он уже применяется, поскольку это снизит размер кода для ACP на устройствах с ограничениями. Поэтапная надёжность для сообщений ACP GRASP может быть обеспечена для поддержки таких протоколов, как DTLS, путём добавления такого же типа согласования, какой определён в этом документе для защищённых каналов ACP. В будущих расширениях ACP для поддержки устройств с ограничениями могут быть созданы сквозные соединения GRASP для выбора их транспортного протокола путём указания поддерживаемых протоколов (например, TLS/DTLS) в параметрах GRASP из цели GRASP, через которую обнаруживается конечная точка.

RPL — протокол маршрутизации в ACP — явно не оптимизирует кратчайшие пути и скорейшее схождение. Варианты ACP могут воспользоваться иным протоколом или разработать усовершенствованные профили RPL.

Такие изменения, как используемый протокол маршрутизации, создание ACP в VRF (как предложено выше) или как фактической плоскости данных, могут автоматически выбираться в реализации для поддержки нескольких вариантов путём их выведения из будущих параметров сертификатов. Параметры в сертификатах следует ограничивать набором, который нужно менять не чаще, чем сертификат обновляется, или обеспечить возможность предоставления этих параметров до активации варианта ACP на узле. С помощью BRSKI это можно сделать, например, в виде дополнительной сигнализации сразу после зачисления сертификата, по-прежнему применяя соединение BRSKI TLS и не задавая дополнительных требований к нему.

Протоколы защиты канала, включая их инкапсуляцию, легко добавляются в решения ACP. Защищённые поэтапные (hop-by-hop) каналы ACP на сетевом уровне легко заменить сквозной защитой в сочетании с другими мерами защиты инфраструктуры. Во всех будущих сетевых OAM следует применять сквозную защиту. При использовании сертификатов домена она не будет зависеть от услуг, предоставляемых защищёнными каналами ACP.

A.9. Дополнительные (будущие) варианты

A.9.1. Автоматическое агрегирование маршрутов

Маршрутизация в ACP в соответствии с этой спецификацией использует лишь стандартный механизм оптимизации маршрутов RPL, например, сохраняя лишь маршруты, не ведущие к корню RPL. Известно, что это работает для сетей с 20000 и более узлов. Автоматическое агрегирование маршрутов для префиксов ULA /48 (при использовании rsub в acp-node-name) и префиксов на основе Zone-ID не предусмотрено. Автоматическое назначение Zone-ID и автоматическое агрегирование моршрутов можно организовать, например, путём настройки границ зоны, анонсирования через GRASP в зоны параметров зон (Zone-ID и префикс ULA /48) и автоматического агрегирования маршрутов на границе зоны. Узлы будут назначать Zone-ID и, возможно, даже префикс /48 на основе анонсов GRASP.

A.9.2. Варианты исключения зависимости от плоскости данных IPv6

Как описано в параграфе 6.13.2, ACP зависит от плоскости данных при адресации IPv6 link-local на интерфейсах. Использование отдельного MAC-адреса для ACP позволяет полностью изолировать ACP от плоскости данных совместимым с этой спецификацией способом. Это также будет идеальным вариантом при использовании виртуализации ввода-вывода с одним корнем (single-root input/output virtualization или SR-IOV, см. [SR]) в реализации ACP, поскольку разные интерфейсы SR-IOV используют свои MAC-адреса.

Если дополнительные адреса MAC недоступны, можно отделить ACP через разные точки демультиплексирования. Один интерфейс подсети может иметь свои интерфейсы IPv6 для ACP и плоскости данных, что позволит разделить их адреса link-local и интерфейс ACP не будет доступен для настройки из плоскости данных. Это тоже совместимо со спецификацией и не препятствует совместимости.

Вариантом, требующим дополнительной спецификации, является применение Ethertype, отличного от 0x86DD (IPv6) при инкапсуляции пакетов IPv6 для ACP. Это похоже на подход, применяемый для аутентификации пакетов IP в [IEEE-802.1X] с использованием Ethertype (0x88A2) расширяемого протокола аутентификации в ЛВС (Extensible Authentication Protocol over Local Area Network или EAPoL) .

Отметим, что в случае узлов ANI приведённые выше соображения применимы в равной степени к инкапсуляции пакетов BRSKI, включая применение GRASP для BRSKI.

A.9.3. ACP API и рабочие модели (YANG)

В будущих работах следует определить модель данных YANG [RFC7950] или внутренние API узлов для мониторинга и управления ACP. В такие модели и API необходимо включить поддержку таблицы смежности ACP (6.3. Таблица смежности ACP) и ACP GRASP.

A.9.4. Усовершенствование RPL

..... США ......              ..... Европа ......

     NOC1                           NOC2
      |                              |
      |           метрика 100        |
    ACP1 --------------------------- ACP2  .
      |                              |     . Ядро
      | метрика 10        метрика 20 |     . WAN
      |                              |     .
    ACP3 --------------------------- ACP4  .
      |           метрика 100        |
      |                              |     .
      |                              |     . Сайты
    ACP10                           ACP11  .

Рисунок 17. Двойной NOC.


Заданный в этом документе профиль RPL создаёт единственный путь через связующее дерево (spanning-tree) к корню (обычно регистратор в NOC). При наличии нескольких NOC маршрутизация к некорневым NOC может быть неоптимальной (Рисунок 17). Предположим, что узел ACP1 становится корнем RPL. Трафик между ACP11 и NOC2 пойдёт через ACP4-ACP3-ACP1-ACP2 вместо ACP4-ACP2, поскольку рассчитанное RPL дерево DODAG и маршруты будут кратчайшими путями к корню RPL. Чтобы преодолеть эти ограничения, можно оптимизировать изменения и/или расширения RPL для нескольких NOC. Это требует использования особенностей (artifact) плоскости данных, включая инкапсуляцию и декапсуляцию IP-in-IP на маршрутизаторах ACP, а также обработку заголовков IPv6 RPI. В качестве варианта можно использовать записи таблицы маршрутизации (Src, Dst).

Лавинная рассылка сообщение ACP GRASP может быть дополнительно ограничена и, следовательно, оптимизирована использованием её лишь на каналах, являющихся частью RPL DODAG.

A.9.5. Назначение роли

ACP connect является явным механизмом «утечки» трафика ACP (например, в NOC). Поэтому возможны угрозы безопасности при использовании ACP connect на скомпрометированных узлах ACP. Одним из простых решений является задание расширения в информационном поле сертификата ACP, указывающего возможность настройки ACP connect на данном узле. Это можно сделать аналогично управлению возможностью узла становиться регистратором.

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

Ещё одна интересная роль, которую можно задать в сертификате, — это узел NOC. Это позволит разрешать некоторые типы соединений (например, OAM TLS) только инициаторам и ответчикам NOC.

A.9.6. Автономный транзит L3

В этой спецификации ACP может организовывать автономную связность лишь через узлы L2 и требует неавтономной настройки для туннелей через узлы L3. В будущих работах следует определить механизмы для автоматического туннелирования ACP через сети L3. Вариант звезды (hub-and-spoke) позволит создавать туннели через Internet в облако или центральный экземпляр ACP. Одноранговый (peer-to-peer) механизм туннелирования будет соединять островки ACP через инфраструктуру L3VPN.

A.9.7. Диагностика

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

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

  2. Вместо LLDP можно определить диагностическую цель DULL GRASP для переноса этих сведений.

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

  4. Следует предоставлять более широкий набор диагностических сведений по защищённым каналам ACP с использованием одноэтапного (single-hop) механизма GRASP или определения топологии в масштабе сети.

A.9.8. Предотвращение и обработка атак от скомпрометированных устройств

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

Если требуется поддерживать основанные на паролях свидетельства для настройки устройств, их недопустимо делать настраиваемыми локально, предоставляя и проверяя их лишь удалённо (через такие протоколы, как RADIUS или Diameter), и не должно быть локальной конфигурации, позволяющей изменить эти механизмы аутентификации. В идеале следует выполнять автоматическую настройку через ACP (см. [NOC-AUTOCONFIG]).

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

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

Без расширений скомпрометированные узлы ACP можно удалить из ACP лишь по мере распространения сведений CRL/OCSP об отзыве или завершении срока (без удаления) краткосрочных сертификатов. Будущие расширения ACP могут, например, использовать лавинное распространение GRASP для инициированных обновления CRL/OCSP или явную индикацию удаления сертификатов домена для скомпрометированных узлов.

A.9.9. Обнаружение атак с понижением на защищённый канал ACP

Ниже описан механизм защиты от атак на понижение без добавления нового специализированного механизма защищённого канала GRASP. Механизм полагается на запуск GRASP после организации протокола защищённого канала для проверки, не был ли организованный вариант защищённого канала результатом MITM-атаки с понижением.

Участники MITM-атаки могут инициировать атаки на снижение версии для защищённого канала ACP путём фильтрации и/или изменения сообщений DULL GRASP и/или фактических пакетов данных в защищённом канале. Например, если в какой-то момент трафик DTLS легче расшифровать, чем трафик IKEv2, MITM-атака может фильтровать все пакеты IKEv2, чтобы вынудить узлы ACP применять DTLS (в предположении, что эти узлы поддерживают DTLS и IKEv2).

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

После организации защищённого канала два партнёра ACP согласуют с помощью принятого (ещё не задан) механизма GRASP протокол защиты канала ACP, который им следует выбрать (в отсутствие MITM-атаки). Это согласование будет указывать опции защищённого канала ACP, анонсированные DULL GRASP каждого из партнёров, затем последует анонс предпочтительного протокола защиты канала от партнёра ACP, ставшего решающим (Decider) при организации канала, т. е. партнёра ACP выбирающего протокол для использования. Если этот выбранный протокол отличается от выбранного фактически, это говорит о наличии MITM-атаки или похожей проблемы (например, межсетевого экрана, препятствующего использованию конкретного протокола). Это обнаружение может обеспечить варианты смягчения последствий, такие как запись в системный журнал и последующие расследования.

Благодарности

Эта работа стала результатом проекта Autonomic Networking компании Cisco Systems, начатого в начале 2010 г. В ACP внесли свой вклад и идеи множество людей, включая (в алфавитном порядке) Ignas Bagdonas, Parag Bhide, Balaji BL, Alex Clemm, Yves Hertoghs, Bruno Klauser, Max Pritikin, Michael Richardson, Ravi Kumar Vadapalli. Отдельная благодарность Brian Carpenter, Elwyn Davies, Joel Halpern и Sheng Jiang за их подробные рецензии.

Большое спасибо Ben Kaduk, Roman Danyliw и Eric Rescorla за их рецензии SEC AD, Russ Housley и Erik Kline за рецензии, а также Valery Smyslov, Tero Kivinen, Paul Wouters, Yoav Nir за обзор параметров IPsec и IKEv2 и способствование в понимании этих и других протоколов защиты. Спасибо Carsten Bormann за помощь в CBOR/CDDL. Комментарии, отзывы и предложение предоставили также Rene Struik, Benoit Claise, William Atwood, Yongkang Zhang.

Участники работы

Все, что связано с GRASP, включая код проверки, текст документа и технические сведения

Brian Carpenter
School of Computer Science
University of Auckland
PB 92019
Auckland 1142
New Zealand
Email: brian.e.carpenter@gmail.com

RPL и все, что связано с BRSKI и начальной загрузкой, включая код проверки, текст документа и технические сведения

Michael C. Richardson
Sandelman Software Works
Email: mcr+ietf@sandelman.ca
URI: http://www.sandelman.ca/mcr/

Выбор и текст о технологии RPL

Pascal Thubert
Cisco Systems, Inc
Building D
45 Allee des Ormes — BP1200
06254 Mougins — Sophia Antipolis
France
Phone: +33 497 23 26 34
Email: pthubert@cisco.com

Адреса авторов

Toerless Eckert (editor)
Futurewei Technologies Inc. USA
2330 Central Expy
Santa Clara, CA 95050
United States of America
Email: tte+ietf@cs.fau.de
 
Michael H. Behringer (editor)
Email: michael.h.behringer@gmail.com
 
Steinthor Bjarnason
Arbor Networks
2727 South State Street, Suite 200
Ann Arbor, MI 48104
United States of America
Email: sbjarnason@arbor.net

Перевод на русский язык

Николай Малых

nmalykh@protokols.ru


1Internet Engineering Task Force — комиссия по решению инженерных задач Internet.

2Internet Engineering Steering Group — комиссия по инженерным разработкам Internet.

3Bootstrapping Remote Secure Key Infrastructure — инфраструктура ключей защиты удалённой загрузки.

4Internet of Things — Интернет вещей.

5Authentication, Authorization, and Accounting — проверка подлинности и полномочий, учёт.

6Man in the middle — атака с перехватом при участии человека.

7Extended Unique Identifier — расширенный уникальный идентификатор.

8Destination-Oriented Directed Acyclic Graph — ориентированный на получателя направленный ациклический граф.

9Low-power and Lossy Network’s Expected Transmission Count — счётчик ожидаемых передач с сети с потерями и слабым питанием.

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

11Опубликовано в RFC 9147. Прим. перев.

Рубрика: RFC | Оставить комментарий

RFC 9002 QUIC Loss Detection and Congestion Control

Internet Engineering Task Force (IETF)                   J. Iyengar, Ed.
Request for Comments: 9002                                        Fastly
Category: Standards Track                                  I. Swett, Ed.
ISSN: 2070-1721                                                   Google
                                                                May 2021

QUIC Loss Detection and Congestion Control

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

PDF

Аннотация

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

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

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

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

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

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

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

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

1. Введение

QUIC является защищенным транспортным протоколом общего назначения, описанным в [QUIC-TRANSPORT]. Этот документ описывает механизмы обнаружения потерь и контроля перегрузок в QUIC.

2. Соглашения и определения

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

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

Ack-eliciting frames — кадры с запросом подтверждения

Все кадры, кроме ACK, PADDING, CONNECTION_CLOSE, считаются запрашивающими подтверждение.

Ack-eliciting packets — пакеты с запросом подтверждения

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

In-flight packets — пакеты в пути

Пакеты считаются находящимися в пути (на лету — in flight), когда они запрашивают подтверждение или содержат кадр PADDING и были переданы, но ещё не подтверждены, не объявлены потерянными и не отброшены со старыми ключами.

3. Устройство машины передачи QUIC

Во всех передачах QUIC используется заголовок на уровне пакета, указывающий уровень шифрования и включающий порядковый номер пакета. Уровень шифрования указывает пространство порядковых номеров, как описано в параграфе 12.3 [QUIC-TRANSPORT]. Номера пакетов в одном пространстве не повторяются в течение работы соединения. Номера передаваемых пакетов монотонно увеличиваются для предотвращения неоднозначности. Допускается пропуск некоторых номеров.

Такой подход избавляет от неоднозначностей при повторной передаче пакета и устраняет в QUIC сложности обнаружения потери пакетов, присущие механизмам TCP.

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

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

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

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

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

4. Важные различия между QUIC и TCP

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

4.1. Раздельные пространства порядковых номеров

QUIC использует своё пространство порядковых номеров для каждого уровня шифрования, за исключением того, что 0-RTT и все варианты ключей 1-RTT находятся в одном пространстве номеров. Раздельные пространства номеров гарантируют, что подтверждения пакетов с одним уровнем шифрования не вызовут ложных повторов пакетов с другим уровнем шифрования. Контроль перегрузок и измерение времени кругового обхода (round-trip time или RTT) являются одинаковыми во всех пространствах номеров.

4.2. Монотонный рост порядковых номеров

TCP объединяет порядок передачи отправителем с порядком приёма получателем, что ведёт к неоднозначности повтора передачи [RETRANSMISSION]. QUIC отделяет порядок передачи от порядка доставки. Номера пакетов указывают порядок передачи а порядок доставки определяется смещением потока в кадрах STREAM.

Номера пакетов QUIC строго возрастают в пространстве номеров и напрямую кодируют порядок отправки. Больший номер означает более позднюю передачу пакета, а меньший — более раннюю. При обнаружении потери пакета с запрашивающими подтверждение кадрами QUIC включает требуемые кадры в новый пакет с новым порядковым номером, устраняя неоднозначность в отношении подтверждаемых пакетов при получении ACK. Это позволяет более точно измерить RTT, легко обнаруживать ложные повторы передачи и возможность повсеместного применения таких механизмов, как Fast Retransmit (ускоренный повтор), на основе лишь номеров пакетов.

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

4.3. Более чёткая эпоха потерь

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

4.4. Неотказуемость подтверждений

Кадры QUIC ACK содержат сведения, аналогичные содержащимся в селективных подтверждениях TCP (Selective Acknowledgment или SACK) [RFC2018]. Однако QUIC не позволяет отозвать подтверждение пакета, что существенно упрощает реализацию обеих сторон и расход памяти у отправителя.

4.5. Больше диапазонов ACK

QUIC поддерживает множество диапазонов ACK в отличие от трёх диапазонов SACK в TCP. В среде с высокими потерями это ускоряет восстановление, предотвращает ложные повторы и гарантирует «продвижение вперёд» без опоры на тайм-ауты.

4.6. Явная корректировка для задержанных подтверждений

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

4.7. Тайм-аут зондов взамен RTO и TLP

QUIC использует тайм-аут проб (probe timeout или PTO, см. параграф 6.2) с таймером на основе расчёта тайм-аута повтора TCP (retransmission timeout или RTO, см. [RFC6298]). QUIC PTO включает максимальную ожидаемую задержку у партнёра вместо фиксированного минимального тайм-аута.

Как алгоритм обнаружения потерь RACK-TLP для TCP [RFC8985], QUIC не сокращает окно перегрузки по истечении PTO, поскольку потеря одного пакета в конце не указывает на постоянную перегрузку. Взамен QUIC сжимает окно перегрузки, когда объявляется сохраняющаяся перегрузка (см. параграф 7.6). Таким способом QUIC предотвращает неоправданное сужение окна перегрузки, избавляясь от потребности в механизмах корректировки, таких как F-RTO (Forward RTO-Recovery) [RFC5682]. Поскольку QUIC не сокращает окно перегрузки по истечении PTO, отправитель QUIC не ограничен в передаче дополнительных пакетов, остающихся в пути по истечении PTO, если окно перегрузки не препятствует. Это происходит, когда отправитель ограничен приложением и PTO истекает. Это более энергичное поведение по сравнению с TCP RTO, когда приложение ограничено, но идентично ему, если нет ограничения.

QUIC позволяет пакетам зондирования временно выходить за пределы окна перегрузки по завершении таймера.

4.8. Минимальное окно перегрузки в 2 пакета

TCP использует минимальное окно перегрузки в 1 пакет. Однако потеря единственного пакета означает, что для восстановления отправитель должен ждать в течение PTO (параграф 6.2), что может быть много больше RTT. Отправка одного пакета с запросом подтверждения также повышает шансы дополнительной задержки при задержке подтверждения получателем.

Поэтому QUIC рекомендует окно перегрузки в 2 пакета. Хотя это повышает нагрузку на сеть, такой выбор считается безопасным, поскольку отправитель будет экспоненциально снижать скорость передачи при возникновении перегрузки (параграф 6.2).

4.9. Пакеты согласования не являются особыми

TCP считает потерю пакета SYN или SYN-ACK сохраняющейся перегрузкой и снижает размер окна перегрузки до одного пакета [RFC5681]. QUIC считает потерю пакета с данными согласования обычной потерей.

5. Оценка RTT

На высоком уровне конечная точка измеряет время между отправкой пакета и его подтверждением как выборку RTT. Конечная точка использует выборки RTT и полученные от партнёра задержки на хосте (см. параграф 13.2 в [QUIC-TRANSPORT]) для статистического описания RTT на сетевом пути. Конечная точка рассчитывает для каждого пути минимальное значение RTT за период времени (min_rtt), экспоненциально взвешенное среднее значение (smoothed_rtt) и среднее отклонение (variation) наблюдаемых выборок RTT (rttvar).

5.1. Генерация выборок RTT

Конечная точка создаёт выбору RTT при получении кадра ACK, соответствующего двум условиям:

  • наибольший подтверждённый порядковый номер недавно подтверждён;

  • хотя бы один из недавно подтверждённых пакетов запрашивал подтверждение (ack-eliciting).

Выборка RTT (latest_rtt) определяется временем с момента отправки подтверждённого пакета с наибольшим номером

   latest_rtt = ack_time - send_time_of_largest_acked

Выборка RTT создаётся с использованием лишь подтверждённого пакета с наибольшим номером в полученном кадре ACK. Это обусловлено тем, что партнёр сообщает задержку подтверждения в кадре ACK лишь для пакета с наибольшим номером. Хотя сообщённая задержка не применяется при измерении RTT, она используется для корректировки выборки RTT в последующих расчётах smoothed_rtt и rttvar (параграф 5.3).

Для предотвращения множественной выборки RTT на один пакет кадр ACK не следует использовать для обновления оценок RTT, если он не является новым подтверждением подтверждённого пакета с наибольшим номером.

Выборку RTT недопустимо создавать при получении кадра ACK который не подтверждает хотя бы один пакет ack-eliciting. Партнёр обычно не передаёт кадр ACK, пока приняты лишь пакеты не требующие подтверждения. Поэтому кадр ACK с подтверждениями лишь не запрашивающих подтверждения пакетов может включать произвольно большое значение ACK Delay. Игнорирование таких кадров ACK предотвращает усложнение последующих расчётов smoothed_rtt и rttvar.

Отправитель может создавать несколько выборок RTT в течение RTT, когда получает в течение этого интервала несколько кадров ACK. Как отмечено в [RFC6298], это может приводить к неадекватной истории smoothed_rtt и rttvar. Обеспечение достаточной истории оценки RTT требует дальнейшего исследования.

5.2. Оценка min_rtt

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

В качестве min_rtt должно устанавливаться значение latest_rtt из первой выборки RTT. Значение min_rtt должно быть меньшим из min_rtt и latest_rtt (параграф 5.1) среди всех других измерений.

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

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

Конечным точкам следует устанавливать в min_rtt новейшую выборку RTT после возникновения устойчивой перегрузки. Это предотвращает периодическое объявление сохраняющейся перегрузки при увеличении RTT, а также позволяет сбрасывать оценки min_rtt и smoothed_rtt после серьёзных нарушения в сети (см. параграф 5.3).

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

5.3. Оценка smoothed_rtt и rttvar

Значение smoothed_rtt указывает экспоненциально взвешенное скользящее среднее значение выборки RTT конечной точкой, в rttvar — вариации в выборках RTT с использованием среднего отклонения.

В расчёте smoothed_rtt используются выборки RTT после их корректировки на основе задержки подтверждения. Эти задержки извлекаются из поля ACK Delay в кадрах ACK, как описано в параграфе 19.3 [QUIC-TRANSPORT]. Партнёр может сообщать о задержках подтверждения, превышающих max_ack_delay у него при согласовании (параграф 13.2.1 в [QUIC-TRANSPORT]). Для учёта этого конечной точке следует игнорировать max_ack_delay, пока согласование не подтверждено, как указано в параграфе 4.1.2 [QUIC-TLS]. Когда это произойдёт, такие большие задержки подтверждения вероятно не будут повторяться. Следовательно, конечная точка может использовать задержки подтверждения, не ограничивая их значением max_ack_delay и избегая ненужной переоценки RTT.

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

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

  • может игнорировать задержку подтверждения для пакетов Initial, поскольку эти подтверждения партнёр не задерживает (параграф 13.2.1 в [QUIC-TRANSPORT]);

  • следует игнорировать max_ack_delay у партнёра, пока согласование не подтверждено;

  • должна использовать меньшее из значений задержки подтверждения и max_ack_delay у партнёра после подтверждения согласования;

  • недопустимо вычитать задержку подтверждения из RTT , если это даёт значение меньше min_rtt (это ограничивает недооценку smoothed_rtt при ошибках партнёра.).

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

Подобно [RFC6298], значения smoothed_rtt и rttvar рассчитываются в соответствии с приведённым ниже описанием.

Конечная точка инициализирует измеритель RTT в процессе организации соединения и при его сбросе во время переноса соединения (см. параграф 9.4 в [QUIC-TRANSPORT]). До того как выборки RTT для нового пути станут доступны или при сбросе измерителя этот измеритель инициализируется с использованием начального RTT (см. параграф 6.2.2). Значения smoothed_rtt и rttvar инициализируются, как показано ниже (kInitialRtt содержит исходное значение RTT).

   smoothed_rtt = kInitialRtt
   rttvar = kInitialRtt / 2

Выборки RTT для сетевого пути записываются в latest_rtt (см. параграф 5.1). При первой выборке RTT после инициализации измеритель сбрасывается с использованием этой выборки. Это обеспечивает исключение истории прошлых измерений. Пакеты, переданные по другому пути, не учитываются в выборке RTT на текущем пути, как указано в параграфе 9.4 [QUIC-TRANSPORT]. При первой выборке RTT после инициализации значения smoothed_rtt и rttvar устанавливаются, как показано ниже.

   smoothed_rtt = latest_rtt
   rttvar = latest_rtt / 2

При последующих выборках RTT значения smoothed_rtt и rttvar вычисляются в соответствии с псевдокодом.

   ack_delay = decoded acknowledgment delay from ACK frame
   if (handshake confirmed):
     ack_delay = min(ack_delay, max_ack_delay)
   adjusted_rtt = latest_rtt
   if (latest_rtt >= min_rtt + ack_delay):
     adjusted_rtt = latest_rtt - ack_delay
   smoothed_rtt = 7/8 * smoothed_rtt + 1/8 * adjusted_rtt
   rttvar_sample = abs(smoothed_rtt - adjusted_rtt)
   rttvar = 3/4 * rttvar + 1/4 * rttvar_sample

6. Обнаружение потерь

Отправители QUIC используют подтверждения для обнаружения потери пакетов и PTO для гарантии получения подтверждений (см. параграф 6.2). В этом разделе приведено описание алгоритмов.

Если пакет потерян транспорту QUIC требуется восстановить потерю, например, путём повторной передачи данных, отправки обновлённого кадра или отбрасывания кадра (см. параграф 13.3 в [QUIC-TRANSPORT]). Обнаружение потерь происходит раздельно в каждом пространстве номеров в отличие от измерения RTT и контроля перегрузки, поскольку те являются свойствами пути, а обнаружение потерь связано с доступностью ключей.

6.1. Обнаружение на основе подтверждений

Обнаружение потерь на основе подтверждения реализует дух механизмов TCP Fast Retransmit [RFC5681], Early Retransmit [RFC5827], Forward Acknowledgment [FACK], восстановление потерь SACK [RFC6675] и RACK-TLP [RFC8985]. В этом параграфе представлен обзор реализации этих алгоритмов в QUIC.

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

  • Пакет не подтверждён, находится в пути и был послан до подтверждённого пакета.

  • Пакет был передан на kPacketThreshold пакетов раньше подтверждённого пакета (параграф 6.1.1) или достаточно давно (параграф 6.1.2).

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

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

6.1.1. Порог по пакетам

Рекомендуемое для начального порога разупорядочения пакетов (kPacketThreshold) значение 3 выбрано на основе опыта обнаружения потерь TCP [RFC5681] [RFC6675]. Для сохранения сходства с TCP реализациям не следует использовать порог меньше 3 [RFC5681].

В некоторых сетях разупорядочение пакетов может быть более сильным, что ведёт к ложному обнаружению потерь отправителем. Кроме того, разупорядочение пакетов в QUIC встречается чаще, чем в TCP, поскольку элементы сети, способные наблюдать и менять порядок пакетов TCP, не могут делать этого для QUIC, так как номера пакетов QUIC зашифрованы. Алгоритмы, повышающие порог разупорядочения после ложного обнаружения потерь (такие как RACK [RFC8985]), оказались полезными в TCP и предполагается, что они будут не менее полезны в QUIC.

6.1.2. Порог по времени

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

   max(kTimeThreshold * max(smoothed_rtt, latest_rtt), kGranularity)

Если пакеты, переданные до подтверждённого пакета с наибольшим номером, ещё не могут быть объявлены потерянными, таймер следует установить на оставшееся время. Использование max(smoothed_rtt, latest_rtt) защищает от двух случаев:

  • последняя выборка RTT меньше сглаженного RTT (возможно из-за разупорядочения, когда подтверждение пошло по более короткому пути);

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

Рекомендуемый порог по времени (kTimeThreshold) составляет 9/8 RTT, рекомендуемая дискретность таймера (kGranularity) — 1 мсек.

Примечание. TCP RACK [RFC8985] задаёт несколько больший порог, эквивалентный 5/4. Опыт работы с QUIC показывает, что порог 9/8 подходит лучше.

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

6.2. Тайм-аут для зондов

Тайм-аут зондирования (Probe Timeout или PTO) вызывает отправку одной или двух пробных дейтаграмм, когда запросившие подтверждение пакеты не подтверждаются в течение ожидаемого интервала или сервер не может проверить адрес клиента. PTO позволяет восстанавливать соединение после потери «хвостовых» пакетов или подтверждений.

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

Завершение отсчёта таймера PTO не говорит о потере пакета и по этому событию недопустимо считать ранее неподтвержденные пакеты потерянными. При получении повторного подтверждения обнаружение потерь продолжается в соответствии с порогами для числа пакетов и времени, как описано в параграфе 6.1.

Алгоритм PTO в QUIC реализует функции алгоритмов Tail Loss Probe [RFC8985], RTO [RFC5681] и F-RTO для протокола TCP [RFC5682]. Расчёт тайм-аута основан на интервале TCP RTO [RFC6298].

6.2.1. Расчёт PTO

При передаче запрашивающего подтверждение пакета отправитель устанавливает таймер PTO

   PTO = smoothed_rtt + max(4*rttvar, kGranularity) + max_ack_delay

Интервал PTO задаёт время, в течение которого отправитель должен ждать подтверждения переданного пакета. Это время включает оценку RTT в сети (smoothed_rtt), вариации оценки (4*rttvar) и max_ack_delay для учёта максимального времени, на которое получатель может задержать отправку подтверждения.

При установке PTO для пространств номеров пакетов Initial или Handshake, для max_ack_delay при расчёте PTO принимается значение 0, поскольку ожидается немедленное подтверждение этих пакетов получателем (см. параграф 13.2.1 в [QUIC-TRANSPORT]).

Интервал PTO должен быть не меньше kGranularity во избежание немедленного завершения отсчёта.

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

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

Отправителю следует перезапускать таймер PTO при каждой отправке или подтверждении запросившего подтверждение пакета, а также при отбрасывании ключей Initial или Handshake (параграф 4.9 в [QUIC-TLS]). Это гарантирует установку PTO на основе последней оценки RTT и для нужного пространства номеров пакетов.

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

Такое экспоненциальное снижение скорости передачи отправителя важно, поскольку последовательные PTO могут быть вызваны потерей пакетов или подтверждений из-за серьёзной перегрузки. Даже при наличии в сети (in flight) пакетов из нескольких пространств номеров экспоненциальное увеличение PTO выполняется во всех пространствах для предотвращения чрезмерной нагрузки на сеть. Например, тайм-аут в пространстве номеров Initial удваивает продолжительность ожидания в пространстве номеров Handshake.

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

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

6.2.2. Согласование и новые пути

Возобновляемые в той же сети соединения могут использовать финальное сглаженное значение RTT из прежнего соединения в качестве начального RTT. Если прежнего значения RTT нет, в качестве начального RTT RTT следует устанавливать значение 333 мсек. Это ведёт к согласованию, начинающегося с PTO в 1 секунду, как рекомендовано для начального RTO в TCP (см. раздел 2 в [RFC6298]).

Соединение может использовать задержку между передачей PATH_CHALLENGE и приёмом PATH_RESPONSE для установки начального RTT (см. kInitialRtt в Приложении A.2) на новом пути, но не следует считать её выборкой RTT.

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

6.2.2.1. До проверки адреса

Пока сервер не проверил адрес клиента на пути, объем передаваемых им данных ограничен троекратным размером принятых данных, как указано в параграфе 8.1 [QUIC-TRANSPORT]. Если дополнительные данные не могут быть переданы, таймер PTO на сервере недопустимо активировать, пока не будут получены дейтаграммы от клиента, поскольку пакеты, передаваемые для PTO, учитываются в пороге антиусиления.

При получении сервером дейтаграммы от клиента порог антиусиления повышается и сервер сбрасывает таймер PTO. Если после этого таймер PTO будет установлен на прошлое время, он считается сработавшим сразу же. Это предотвращает передачу пакетов 1-RTT до пакетов, которые критически важны для согласования. В частности, это может происходить, когда сервер воспринимает 0-RTT, но не может подтвердить адрес клиента.

Поскольку сервер может быть заблокирован до приёма новых дейтаграмм от клиента, ответственность за отправку этих дейтаграмм ложится на клиента, пока у него не будет уверенности в том, что сервер завершил проверку его адреса (см. раздел 8 в [QUIC-TRANSPORT]). Т. е. клиент должен установить таймер PTO, если он не получил подтверждения какого-либо из своих пакетов Handshake и согласование не подтверждено (см. параграф 4.1.2 в [QUIC-TLS]), даже при отсутствии находящихся в пути пакетов. При срабатывании PTO клиент должен передать пакет Handshake при наличии ключей Handshake, в противном случае он должен передать пакет Initial в дейтаграмме UDP, содержимое (payload) которой не меньше 1200 байтов.

6.2.3. Ускоренное завершение согласования

При получении пакета Initial с дубликатом данных CRYPTO сервер может предположить, что клиент не получил все данные CRYPTO, переданные в пакетах Initial, или оценка RTT клиентом слишком мала. При получении клиентом пакетов Handshake или 1-RTT до обретения ключей Handshake он может предположить, что некоторые или все пакеты Initial от сервера были потеряны.

Чтобы ускорить завершение согласования в таких условиях, конечная точка может ограниченное число раз за соединение передать пакет с неподтвержденными данными CRYPTO до завершения PTO с учётом ограничений проверки адреса (параграф 8.1 в [QUIC-TRANSPORT]). Выполнения этого не более 1 раза для каждого соединения достаточно для быстрого восстановления при потере одного пакета. Конечная точка, всегда повторяющая пакеты в ответ на получение пакета, который она не может обработать, рискует создать бесконечный обмен пакетами.

Конечные точки могут также объединять пакеты (см. параграф 12.2 в [QUIC-TRANSPORT]), чтобы каждая дейтаграмма запрашивала хотя бы одно подтверждение. Например, клиент может объединить пакет Initial, содержащий кадры PING и PADDING, с пакетом данных 0-RTT, а сервер может объединить пакет Initial, содержащий кадр PING, с одним или несколькими пакетами в своей первой отправке.

6.2.4. Отправка пакетов зондирования

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

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

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

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

У отправителя может не быть новых или уже отправленных данных для передачи. Рассмотрим в качестве примера последовательность событий: новые данные приложения переданы в кадре STREAM, эти данные сочтены потерянными, повторены в новом пакете, а затем исходна передача была подтверждена. Когда нет данных для передачи, отправителю следует передать PING или другой кадр с запросом подтверждения в одном пакете, снова запуская таймер PTO.

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

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

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

6.3. Обработка пакетов Retry

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

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

Клиент может рассчитать RTT до сервера как интервал между отправкой первого пакета Initial и получением пакета Retry или Version Negotiation. Клиент может установить это значение вместо принятого по умолчанию начального RTT.

6.4. Отбрасывание ключей и состояние пакета

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

Конечные точки останавливают передачу и приём пакетов Initial после начала обмена пакетами Handshake (см. параграф 17.2.2.1 в [QUIC-TRANSPORT]). В этот момент отбрасывается состояние восстановления для находящихся в пути пакетов Initial.

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

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

7. Контроль перегрузки

В этом документе описано контроллер перегрузок на стороне отправителя QUIC, похожий на TCP NewReno [RFC6582]. Сигналы, предоставляемые протоколом QUIC для контроля перегрузок являются базовыми и предназначены для разных механизмов на стороне отправителя, который в одностороннем порядке может выбрать другой механизм, например CUBIC [RFC8312]. При использовании отправителем иного механизма, выбранный контроллер должен соответствовать рекомендациям параграфа 3.1 в [RFC8085].

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

Контроллер перегрузки работает на уровне пути, поэтому передаваемые по другому пути пакеты не влияют на контроллер текущего пути, как описано в параграфе 9.4 [QUIC-TRANSPORT]. Описанный в документе алгоритм задаёт и применяет окно перегрузки в контроллере, выраженное в байтах. Конечной точке недопустимо передавать пакеты, если это сделает значение bytes_in_flight (см. Приложение B.2) больше окна перегрузки, за исключением случаев отправки пакета по тайм-ауту PTO (см. параграф 6.2) или при входе в режим восстановления (см. параграф 7.3.2).

7.1. Явное указание перегрузки

Если для пути подтверждено явное уведомление о перегрузке (Explicit Congestion Notification или ECN) [RFC3168] [RFC8311], QUIC считает код CE3 в заголовке IP сигналом перегрузки. Этот документ задаёт реакцию конечных точек на увеличение полученного от партнёра значения ECN-CE (см. параграф 13.4.2 в [QUIC-TRANSPORT]).

7.2. Начальное и минимальное окно перегрузки

QUIC начинает каждое соединение в режиме замедленного старта с установкой начального значения окна перегрузки. Конечным точкам следует устанавливать начальное окно перегрузки в 10 максимальных размеров дейтаграмм (max_datagram_size), при этом ограничивая окно значением 14720 байтов или удвоенным размером максимальной дейтаграммы. Это соответствует анализу и рекомендациям [RFC6928], увеличивая предельный размер с учётом 8-байтового заголовка UDP вместо 20-байтового заголовка TCP. Если максимальный размер дейтаграмм меняется в процессе работы соединения, начальное окно перегрузки следует пересчитать в соответствии с изменением. Если максимальный размер дейтаграмм уменьшается для завершения согласования, окно перегрузки следует установить в соответствии с новым значением начального окна перегрузки.

До проверки адреса клиента сервер может быть дополнительно ограничен пределом антиусиления, как описано в параграфе 8.1 [QUIC-TRANSPORT]. Хотя предел антиусиления может препятствовать полному использованию окна перегрузки и замедлять расширение этого окна, он не влияет на окно перегрузки напрямую.

Минимальным окном перегрузки является меньшее из значений окна перегрузки, которое может быть установлено в ответ на потерю, рост полученного от партнёра значения ECN-CE или сохраняющуюся перегрузку. Рекомендуется удвоенное значение max_datagram_size.

7.3. Состояния контроля перегрузки

Контроллер перегрузок NewReno, описанный в этом документе, имеет 3 состояния, показанных на рисунке 1.

             Новый путь или      +------------+
        сохраняющаяся перегрузка |Замедленный |
       (O)---------------------->|   старт    |
                                 +------------+
                                       |
                            Потеря или |
                           рост ECN-CE |
                                       v
+------------+    Потеря или     +------------+
| Предотвращ.|    рост ECN-CE    |   Период   |
| перегрузки |------------------>| восстановл.|
+------------+                   +------------+
          ^                            |
          |                            |
          +----------------------------+
           Подтверждение пакета передано
             в процессе восстановления

Рисунок 1. Смена состояний контроля перегрузок.


Эти состояния и переходы между ними описаны в последующих параграфах.

7.3.1. Замедленный старт

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

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

7.3.2. Восстановление

Отправитель NewReno входит в период восстановления при обнаружении потери пакета или росте полученного от партнёра значения ECN-CE. Отправитель, уже находящийся в периоде восстановления, остаётся в нем без входа заново. При входе в период восстановления отправитель должен установить для порога замедленного старта половину размера окна перегрузки при обнаружении потери. Для окна перегрузки должно быть установлено сниженное значение порога замедленного старта при выходе из периода восстановления.

Реализация может сократить окно перегрузки сразу после входа в период восстановления или с помощью других механизмов, таких как пропорциональное снижение скорости (Proportional Rate Reduction [PRR]), для более постепенного сокращения. Если окно перегрузки сокращается сразу же, перед сокращением может быть передан 1 пакет. Это ускоряет восстановление, если потерянный пакет передаётся повторно, и похоже на TCP, как описано в разделе 5 [RFC6675].

Период восстановления направлен на ограничение сокращения окна перегрузки один раз за период кругового обхода. Поэтому в период восстановления окно перегрузки не сокращается в ответ на новые потери и рост ECN-CE. Период восстановления заканчивается и отправитель переходит в режим предотвращения перегрузки, когда подтверждаются пакеты, переданные в период восстановления. Это несколько отличается от определения восстановления в TCP, которое завершается при подтверждении сегмента, с потери которого восстановления началось [RFC5681].

7.3.3. Предотвращение перегрузки

Отправитель NewReno находится в режиме предотвращения перегрузки все время, когда окно перегрузки не меньше порога замедленного старта и нет периода восстановления. Отправитель в этом режиме использует аддитивное увеличение и мультипликативное сокращение (Additive Increase Multiplicative Decrease или AIMD), которое должно ограничить расширение окна перегрузки величиной не более размера одной максимальной дейтаграммы для каждого подтверждённого окна перегрузки. Отправитель переходит из режима предотвращения перегрузки в период восстановления при потере пакета или росте полученного от партнёра значения ECN-CE.

7.4. Игнорирование потери нерасшифровываемых пакетов

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

7.5. Тайм-аут зондирования

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

7.6. Сохраняющаяся перегрузка

Когда отправитель констатирует потерю всех пакетов в течение достаточно долгого интервала, считается, что в сети наблюдается сохраняющаяся (постоянная) перегрузка.

7.6.1. Продолжительность

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

   (smoothed_rtt + max(4*rttvar, kGranularity) + max_ack_delay) *
       kPersistentCongestionThreshold

В отличие от расчёта PTO в параграфе 6.2, эта продолжительность включает max_ack_delay безотносительно к пространству номеров, где были отмечены потери. Эта продолжительность позволяет отправителю передать до фиксации сохраняющейся перегрузки (включая отклик на завершение PTO) столько пакетов, сколько разрешено для TCP с Tail Loss Probes [RFC8985] и RTO [RFC5681].

Большее значение kPersistentCongestionThreshold делает отправителя менее восприимчивым к сохраняющейся перегрузке в сети, что может привести к избыточной передаче в перегруженную сеть. Слишком малое значение может приводить к неоправданному решению о сохраняющейся перегрузке, снижающему скорость передачи у отправителя. Для kPersistentCongestionThreshold рекомендуется значение 3, обеспечивающее поведение, близкое к поведению отправителя TCP, объявляющего RTO после двух TLP.

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

7.6.2. Фиксация сохраняющейся перегрузки

Отправитель констатирует сохраняющуюся перегрузку после приёма подтверждения, если объявлены потерянными 2 пакета с запросом подтверждения и выполняются указанные ниже условия:

  • во всех пространствах номеров не подтверждён ни один из пакетов, переданных между этими 2 пакетами;

  • время между отправкой этих 2 пакетов больше продолжительности постоянной перегрузки (параграф 7.6.1);

  • при отправке этих двух пакетов имелась предыдущая выборка RTT.

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

Период постоянной перегрузки недопустимо начинать, пока не сделана хотя бы одна выборка RTT. До первой выборки RTT отправитель активирует таймер PTO на основе начального значения RTT (параграф 6.2.2), которое может быть существенно больше фактического RTT. Требование предшествующей выборки RTT предотвращает фиксацию сохраняющейся перегрузки отправителем на основании слишком малого числа пакетов.

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

Когда объявлена сохраняющаяся перегрузка, окно перегрузки у отправителя должно сокращаться до минимального размера (kMinimumWindow), как в реакции отправителя TCP на RTO [RFC5681].

7.6.3. Пример

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

   smoothed_rtt + max(4*rttvar, kGranularity) + max_ack_delay = 2
   kPersistentCongestionThreshold = 3

Рассмотрим приведённую в таблице 1 последовательность событий

Таблица 1.

Время

Действие

t=0

Передан пакет 1 (данные приложения)

t=1

Передан пакет 2 (данные приложения)

t=1,2

Получено подтверждение пакета 1

t=2

Передан пакет 3 (данные приложения)

t=3

Передан пакет 4 (данные приложения)

t=4

Передан пакет 5 (данные приложения)

t=5

Передан пакет 6 (данные приложения)

t=6

Передан пакет 7 (данные приложения)

t=8

Передан пакет 8 (PTO 1)

t=12

Передан пакет 9 (PTO 2)

t=12,2

Получено подтверждение пакета 9

Пакеты 2 — 8 объявляются потерянными, когда приходит подтверждение пакета 9 в момент t = 12,2. Период перегрузки рассчитывается как время между самым старым и самым новым потерянными пакетами 8 — 1 = 7. Продолжительность сохраняющейся перегрузки составляет 2 * 3 = 6. Поскольку порог был достигнут и ни один пакет между самым старым и самым новым потерянными пакетами не был подтверждён, считается, что в сети сохраняется перегрузка.

Хотя в примере показан тайм-аут PTO, он не требуется для обнаружения сохраняющейся перегрузки.

7.7. Темп передачи

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

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

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

   rate = N * congestion_window / smoothed_rtt

Можно также задать скорость межпакетным интервалом в единицах времени

   interval = ( smoothed_rtt * packet_size / congestion_window ) / N

Использование небольшого (но не меньше 1) значения N (например, 1,25) гарантирует, что изменения RTT не будут приводить к неполному использованию окна перегрузки.

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

Одной из возможных стратегий управления темпом является применение алгоритма «текущего ведра» (leaky bucket), объем которого ограничен максимальным размером пиков, а скорость вытекания задаётся приведённой функцией.

7.8. Неполное использование окна перегрузки

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

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

8. Вопросы безопасности

8.1. Сигналы потерь и перегрузки

Обнаружение потерь и контроль перегрузки основаны на сигналах, таких как задержка, потери, маркировка ECN, от неаутентифицированных объектов. Злоумышленник может заставить конечные точки снизить скорость передачи, манипулируя этими сигналами путём отбрасывания пакетов, изменения задержки на пути или подмены кодов ECN.

8.2. Анализ трафика

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

8.3. Неверная маркировка ECN

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

Отправитель может обнаружить подавление сведений, случайно помечая передаваемые пакеты маркером ECN-CE. Если для пакета, переданного с маркировкой ECN-CE, не сообщается о наличии маркера CE при его подтверждении, отправитель может отключить ECN для пути, не устанавливая коды ECT в последующих пакетах для этого пути [RFC3168].

Сообщение о дополнительных маркерах ECN-CE вынудит отправителя снизить скорость передачи, что похоже на эффект анонсирования сниженного порога управления потоком данных, поэтому не даёт каких-либо преимуществ.

Конечные точки сами выбирают контроллер перегрузки. Контроллеры реагируют на сведения о ECN-CE снижением скорости, но отклики могут различаться. Маркировку можно считать эквивалентом потери [RFC3168], но возможны и другие отклики, например, [RFC8511] или [RFC8311].

9. Литература

9.1. Нормативные документы

[QUIC-TLS] Thomson, M., Ed. and S. Turner, Ed., «Using TLS to Secure QUIC», RFC 9001, DOI 10.17487/RFC9001, May 2021, <https://www.rfc-editor.org/info/rfc9001>.

[QUIC-TRANSPORT] Iyengar, J., Ed. and M. Thomson, Ed., «QUIC: A UDP-Based Multiplexed and Secure Transport», RFC 9000, DOI 10.17487/RFC9000, May 2021, <https://www.rfc-editor.org/info/rfc9000>.

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>.

[RFC3168] Ramakrishnan, K., Floyd, S., and D. Black, «The Addition of Explicit Congestion Notification (ECN) to IP», RFC 3168, DOI 10.17487/RFC3168, September 2001, <https://www.rfc-editor.org/info/rfc3168>.

[RFC8085] Eggert, L., Fairhurst, G., and G. Shepherd, «UDP Usage Guidelines», BCP 145, RFC 8085, DOI 10.17487/RFC8085, March 2017, <https://www.rfc-editor.org/info/rfc8085>.

[RFC8174] Leiba, B., «Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words», BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.

9.2. Дополнительная литература

[FACK] Mathis, M. and J. Mahdavi, «Forward acknowledgement: Refining TCP Congestion Control», ACM SIGCOMM Computer Communication Review, DOI 10.1145/248157.248181, August 1996, <https://doi.org/10.1145/248157.248181>.

[PRR] Mathis, M., Dukkipati, N., and Y. Cheng, «Proportional Rate Reduction for TCP», RFC 6937, DOI 10.17487/RFC6937, May 2013, <https://www.rfc-editor.org/info/rfc6937>.

[RETRANSMISSION] Karn, P. and C. Partridge, «Improving Round-Trip Time Estimates in Reliable Transport Protocols», ACM Transactions on Computer Systems, DOI 10.1145/118544.118549, November 1991, <https://doi.org/10.1145/118544.118549>.

[RFC2018] Mathis, M., Mahdavi, J., Floyd, S., and A. Romanow, «TCP Selective Acknowledgment Options», RFC 2018, DOI 10.17487/RFC2018, October 1996, <https://www.rfc-editor.org/info/rfc2018>.

[RFC3465] Allman, M., «TCP Congestion Control with Appropriate Byte Counting (ABC)», RFC 3465, DOI 10.17487/RFC3465, February 2003, <https://www.rfc-editor.org/info/rfc3465>.

[RFC5681] Allman, M., Paxson, V., and E. Blanton, «TCP Congestion Control», RFC 5681, DOI 10.17487/RFC5681, September 2009, <https://www.rfc-editor.org/info/rfc5681>.

[RFC5682] Sarolahti, P., Kojo, M., Yamamoto, K., and M. Hata, «Forward RTO-Recovery (F-RTO): An Algorithm for Detecting Spurious Retransmission Timeouts with TCP», RFC 5682, DOI 10.17487/RFC5682, September 2009, <https://www.rfc-editor.org/info/rfc5682>.

[RFC5827] Allman, M., Avrachenkov, K., Ayesta, U., Blanton, J., and P. Hurtig, «Early Retransmit for TCP and Stream Control Transmission Protocol (SCTP)», RFC 5827, DOI 10.17487/RFC5827, May 2010, <https://www.rfc-editor.org/info/rfc5827>.

[RFC6298] Paxson, V., Allman, M., Chu, J., and M. Sargent, «Computing TCP’s Retransmission Timer», RFC 6298, DOI 10.17487/RFC6298, June 2011, <https://www.rfc-editor.org/info/rfc6298>.

[RFC6582] Henderson, T., Floyd, S., Gurtov, A., and Y. Nishida, «The NewReno Modification to TCP’s Fast Recovery Algorithm», RFC 6582, DOI 10.17487/RFC6582, April 2012, <https://www.rfc-editor.org/info/rfc6582>.

[RFC6675] Blanton, E., Allman, M., Wang, L., Jarvinen, I., Kojo, M., and Y. Nishida, «A Conservative Loss Recovery Algorithm Based on Selective Acknowledgment (SACK) for TCP», RFC 6675, DOI 10.17487/RFC6675, August 2012, <https://www.rfc-editor.org/info/rfc6675>.

[RFC6928] Chu, J., Dukkipati, N., Cheng, Y., and M. Mathis, «Increasing TCP’s Initial Window», RFC 6928, DOI 10.17487/RFC6928, April 2013, <https://www.rfc-editor.org/info/rfc6928>.

[RFC7661] Fairhurst, G., Sathiaseelan, A., and R. Secchi, «Updating TCP to Support Rate-Limited Traffic», RFC 7661, DOI 10.17487/RFC7661, October 2015, <https://www.rfc-editor.org/info/rfc7661>.

[RFC8311] Black, D., «Relaxing Restrictions on Explicit Congestion Notification (ECN) Experimentation», RFC 8311, DOI 10.17487/RFC8311, January 2018, <https://www.rfc-editor.org/info/rfc8311>.

[RFC8312] Rhee, I., Xu, L., Ha, S., Zimmermann, A., Eggert, L., and R. Scheffenegger, «CUBIC for Fast Long-Distance Networks», RFC 8312, DOI 10.17487/RFC8312, February 2018, <https://www.rfc-editor.org/info/rfc8312>.

[RFC8511] Khademi, N., Welzl, M., Armitage, G., and G. Fairhurst, «TCP Alternative Backoff with ECN (ABE)», RFC 8511, DOI 10.17487/RFC8511, December 2018, <https://www.rfc-editor.org/info/rfc8511>.

[RFC8985] Cheng, Y., Cardwell, N., Dukkipati, N., and P. Jha, «The RACK-TLP Loss Detection Algorithm for TCP», RFC 8985, DOI 10.17487/RFC8985, February 2021, <https://www.rfc-editor.org/info/rfc8985>.

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

Здесь рассматривается пример реализации механизмов обнаружения потерь, описанных в разделе 6. Приведённый псевдокод лицензируется как компоненты кода (см. «Авторские права»).

A.1. Отслеживание переданных пакетов

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

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

A.1.1. Поля переданных пакетов

packet_number

Номер передаваемого пакета.

ack_eliciting

Логический параметр, указывающий для пакета запрос подтверждения. Значение true указывает, что отправитель ждёт подтверждения, хотя партнёр может задержать отправку кадра ACK с этим подтверждением на время до max_ack_delay.

in_flight

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

sent_bytes

Число переданных в пакете байтов без учёта заголовков UDP и IP, но с учётом кадрирования QUIC.

time_sent

Время передачи пакета.

A.2. Константы

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

kPacketThreshold

Максимальное разупорядочение пакетов для фиксации потери пакета по достижению этого порога. В параграфе 6.1.1 рекомендовано значение 3.

kTimeThreshold

Максимальное время разупорядочения пакетов по достижению которого пакет считается потерянным. Задаётся в интервалах RTT. В параграфе 6.1.2 рекомендовано значение 9/8.

kGranularity

Дискретность таймера, зависящая от системы. В параграфе 6.1.2 рекомендовано значение 1 мсек.

kInitialRtt

Значение RTT, использованное перед выборкой RTT. В параграфе 6.2.2 рекомендовано значение 333 мсек.

kPacketNumberSpace

Перечисляемый тип для трёх пространств номеров пакетов.

   enum kPacketNumberSpace {
     Initial,
     Handshake,
     ApplicationData,
   }

A.3. Переменные

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

latest_rtt

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

smoothed_rtt

Сглаженное значение RTT для соединения, рассчитанное в соответствии с параграфом 5.3.

rttvar

Вариации RTT, рассчитанные в соответствии с параграфом 5.3.

min_rtt

Минимальное значение RTT за период времени без учёта задержки подтверждения, как указано в параграфе 5.2.

first_rtt_sample

Время первой выборки RTT.

max_ack_delay

Максимальное время, на которое получатель намерен задерживать подтверждения для пакетов из пространства номеров Application Data, определяемое одноимённым транспортным параметром (параграф 18.2 в [QUIC-TRANSPORT]). Отметим, что фактическое значение ack_delay в полученном кадре ACK может быть больше из-за запаздывания таймеров, нарушения порядка и потери пакетов.

loss_detection_timer

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

pto_count

Число фактов передачи PTO без получения подтверждения.

time_of_last_ack_eliciting_packet[kPacketNumberSpace]

Время передачи последнего пакета с запросом подтверждения.

largest_acked_packet[kPacketNumberSpace]

Наибольший номер, подтверждённый на данный момент в пространстве номеров пакетов.

loss_time[kPacketNumberSpace]

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

sent_packets[kPacketNumberSpace]

Привязка номеров пакетов в определённом пространстве к информации о них (см. Приложение A.1).

A.4. Инициализация

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

   loss_detection_timer.reset()
   pto_count = 0
   latest_rtt = 0
   smoothed_rtt = kInitialRtt
   rttvar = kInitialRtt / 2
   min_rtt = 0
   first_rtt_sample = 0
   for pn_space in [ Initial, Handshake, ApplicationData ]:
     largest_acked_packet[pn_space] = infinite
     time_of_last_ack_eliciting_packet[pn_space] = 0
     loss_time[pn_space] = 0

A.5. Отправка пакета

Информация о пакете сохраняется после его передачи. Параметры OnPacketSent подробно описаны в Приложении A.1.1, а псевдокод приведён ниже.

   OnPacketSent(packet_number, pn_space, ack_eliciting,
                in_flight, sent_bytes):
     sent_packets[pn_space][packet_number].packet_number =
                                              packet_number
     sent_packets[pn_space][packet_number].time_sent = now()
     sent_packets[pn_space][packet_number].ack_eliciting =
                                              ack_eliciting
     sent_packets[pn_space][packet_number].in_flight = in_flight
     sent_packets[pn_space][packet_number].sent_bytes = sent_bytes
     if (in_flight):
       if (ack_eliciting):
         time_of_last_ack_eliciting_packet[pn_space] = now()
       OnPacketSentCC(sent_bytes)
       SetLossDetectionTimer()

A.6. Приём дейтаграммы

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

   OnDatagramReceived(datagram):
     // Если эта дейтаграмма снимает блокировку сервер, 
     // активируется таймер PTO для предотвращения блокировки.
     if (server was at anti-amplification limit):
       SetLossDetectionTimer()
       if loss_detection_timer.timeout < now():
         // Выполняется PTO, если отсчёт таймера завершился, 
         // пока применялся порог антиусиления.
         OnLossDetectionTimeout()

A.7. Приём подтверждения

При получении кадра ACK он может заново подтверждать любое число пакетов. Псевдокод OnAckReceived и UpdateRtt приведён ниже.

   IncludesAckEliciting(packets):
     for packet in packets:
       if (packet.ack_eliciting):
         return true
     return false

   OnAckReceived(ack, pn_space):
     if (largest_acked_packet[pn_space] == infinite):
       largest_acked_packet[pn_space] = ack.largest_acked
     else:
       largest_acked_packet[pn_space] =
           max(largest_acked_packet[pn_space], ack.largest_acked)

     // DetectAndRemoveAckedPackets находит пакеты, которые недавно
     // подтверждены и удаляет их из sent_packets.
     newly_acked_packets =
         DetectAndRemoveAckedPackets(ack, pn_space)
     // Нечего делать при отсутствии недавно подтверждённых пакетов.
     if (newly_acked_packets.empty()):
       return

     // Обновление RTT при недавнем подтверждении наибольшего номера,
     // если недавно получено хотя бы одно запрошенное подтверждение.
     if (newly_acked_packets.largest().packet_number ==
             ack.largest_acked &&
         IncludesAckEliciting(newly_acked_packets)):
       latest_rtt =
         now() - newly_acked_packets.largest().time_sent
       UpdateRtt(ack.ack_delay)

     // Обработка сведений ECN (при наличии).
     if (ACK frame contains ECN information):
         ProcessECN(ack, pn_space)

     lost_packets = DetectAndRemoveLostPackets(pn_space)
     if (!lost_packets.empty()):
       OnPacketsLost(lost_packets)
     OnPacketsAcked(newly_acked_packets)

     // Сброс pto_count, пока клиент не уверен, что сервер
     // проверил его адрес.
     if (PeerCompletedAddressValidation()):
       pto_count = 0
     SetLossDetectionTimer()

   UpdateRtt(ack_delay):
     if (first_rtt_sample == 0):
       min_rtt = latest_rtt
       smoothed_rtt = latest_rtt
       rttvar = latest_rtt / 2
       first_rtt_sample = now()
       return

     // min_rtt игнорирует задержку подтверждения.
     min_rtt = min(min_rtt, latest_rtt)
     // Ограничивает ack_delay значением max_ack_delay после 
     // подтверждения согласования.
     if (handshake confirmed):
       ack_delay = min(ack_delay, max_ack_delay)

     // Настройка задержки подтверждения при возможности.
     adjusted_rtt = latest_rtt
     if (latest_rtt >= min_rtt + ack_delay):
       adjusted_rtt = latest_rtt - ack_delay

     rttvar = 3/4 * rttvar + 1/4 * abs(smoothed_rtt - adjusted_rtt)
     smoothed_rtt = 7/8 * smoothed_rtt + 1/8 * adjusted_rtt

A.8. Установка таймера обнаружения потерь

Для обнаружения потерь в QUIC применяется один таймер. Продолжительность отсчёта зависит от режима таймера, который установлен в пакете, и описанных ниже событий. Определённая ниже функция SetLossDetectionTimer показывает, как устанавливается один таймер. Этот алгоритм может устанавливать для таймера время в прошлом, особенно при позднем пробуждении таймера. В таком случае таймер срабатывает сразу же. Псевдокод SetLossDetectionTimer приведён ниже (^ обозначает возведение в степень).

   GetLossTimeAndSpace():
     time = loss_time[Initial]
     space = Initial
     for pn_space in [ Handshake, ApplicationData ]:
       if (time == 0 || loss_time[pn_space] < time):
         time = loss_time[pn_space];
         space = pn_space
     return time, space

   GetPtoTimeAndSpace():
     duration = (smoothed_rtt + max(4 * rttvar, kGranularity))
         * (2 ^ pto_count)
     // Антиблокировочный тайм-аут PTO запускается с текущего момента
     if (no ack-eliciting packets in flight):
       assert(!PeerCompletedAddressValidation())
       if (has handshake keys):
         return (now() + duration), Handshake
       else:
         return (now() + duration), Initial
     pto_timeout = infinite
     pto_space = Initial
     for space in [ Initial, Handshake, ApplicationData ]:
       if (no ack-eliciting packets in flight in space):
           continue;
       if (space == ApplicationData):
         // Пропуск Application Data, пока согласование не подтверждено.
         if (handshake is not confirmed):
           return pto_timeout, pto_space
         // Включение max_ack_delay и отсрочки для Application Data.
         duration += max_ack_delay * (2 ^ pto_count)

       t = time_of_last_ack_eliciting_packet[space] + duration
       if (t < pto_timeout):
         pto_timeout = t
         pto_space = space
     return pto_timeout, pto_space

   PeerCompletedAddressValidation():
     // Предположим, что клиент проверяет адрес сервера неявно.
     if (endpoint is server):
       return true
     // Сервер завершает проверку адреса при получении 
     // защищённого пакета.
     return has received Handshake ACK ||
          handshake confirmed

   SetLossDetectionTimer():
     earliest_loss_time, _ = GetLossTimeAndSpace()
     if (earliest_loss_time != 0):
       // Временной порог обнаружения потерь.
       loss_detection_timer.update(earliest_loss_time)
       return

     if (server is at anti-amplification limit):
       // Таймер сервера не устанавливается, если нечего передать.
       loss_detection_timer.cancel()
       return

     if (no ack-eliciting packets in flight &&
         PeerCompletedAddressValidation()):
       // Нет ничего для обнаружения потерь и таймер не устанавливается.
       // Однако клиент должен активировать таймер, если сервер может
       // быть заблокирован пределом антиусиления.
       loss_detection_timer.cancel()
       return

     timeout, _ = GetPtoTimeAndSpace()
     loss_detection_timer.update(timeout)

A.9. Тайм-аут

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

   OnLossDetectionTimeout():
     earliest_loss_time, pn_space = GetLossTimeAndSpace()
     if (earliest_loss_time != 0):
       // Временной порог обнаружения потерь
       lost_packets = DetectAndRemoveLostPackets(pn_space)
       assert(!lost_packets.empty())
       OnPacketsLost(lost_packets)
       SetLossDetectionTimer()
       return

     if (no ack-eliciting packets in flight):
       assert(!PeerCompletedAddressValidation())
       // Клиент передал противоблокироваочный пакет: пакет Initial 
       // дополнен для увеличения предела антиусиления,
       // пакет Handshake подтверждает владение адресом.
       if (has Handshake keys):
         SendOneAckElicitingHandshakePacket()
       else:
         SendOneAckElicitingPaddedInitialPacket()
     else:
       // PTO. При наличии передаются новые данные или повторяются прежние.
       // Если ничего не доступно, передаётся один кадр PING.
       _, pn_space = GetPtoTimeAndSpace()
       SendOneOrTwoAckElicitingPackets(pn_space)

     pto_count++
     SetLossDetectionTimer()

A.10. Обнаружение потери пакетов

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

   DetectAndRemoveLostPackets(pn_space):
     assert(largest_acked_packet[pn_space] != infinite)
     loss_time[pn_space] = 0
     lost_packets = []
     loss_delay = kTimeThreshold * max(latest_rtt, smoothed_rtt)

     // Минимальное время kGranularity перед тем как пакет 
     // будет сочтён потерянным.
     loss_delay = max(loss_delay, kGranularity)

     // Пакеты, переданные до этого времени, считаются потерянными.
     lost_send_time = now() - loss_delay

     foreach unacked in sent_packets[pn_space]:
       if (unacked.packet_number > largest_acked_packet[pn_space]):
         continue

       // Маркировка пакета как потерянного или установка времени, когда
       // его следует пометить. Отметим, что kPacketThreshold здесь
       // предполагает отсутствие заданных отправителем пропусков номеров.
       if (unacked.time_sent <= lost_send_time ||
           largest_acked_packet[pn_space] >=
             unacked.packet_number + kPacketThreshold):
         sent_packets[pn_space].remove(unacked.packet_number)
         lost_packets.insert(unacked)
       else:
         if (loss_time[pn_space] == 0):
           loss_time[pn_space] = unacked.time_sent + loss_delay
         else:
           loss_time[pn_space] = min(loss_time[pn_space],
                                     unacked.time_sent + loss_delay)
     return lost_packets

A.11. Отбрасывание ключей Initial или Handshake

При отбрасывании ключей Initial или Handshake пакеты из этого пространства отбрасываются и обновляется статус обнаружения потерь. Псевдокод OnPacketNumberSpaceDiscarded приведён ниже.

   OnPacketNumberSpaceDiscarded(pn_space):
     assert(pn_space != ApplicationData)
     RemoveFromBytesInFlight(sent_packets[pn_space])
     sent_packets[pn_space].clear()
     // Сброс обнаружения потерь и таймера PTO.
     time_of_last_ack_eliciting_packet[pn_space] = 0
     loss_time[pn_space] = 0
     pto_count = 0
     SetLossDetectionTimer()

Приложение B. Псевдокод контроля перегрузки

Здесь рассматривается пример реализации контроллера перегрузок, описанного в разделе 7. Приведённый псевдокод лицензируется как компоненты кода (см. «Авторские права»).

B.1. Константы

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

kInitialWindow

Используемый по умолчанию предел находящихся в пути (in flight) байтов, как описано в параграфе 7.2.

kMinimumWindow

Минимальное окно перегрузки (в байтах), как описано в параграфе 7.2.

kLossReductionFactor

Фактор масштабирования, применяемый для сужения окна перегрузки при обнаружении новой потери. Раздел 7 рекомендует значение 0,5.

kPersistentCongestionThreshold

Интервал времени фиксации сохраняющейся перегрузки, задаваемый коэффициентом для PTO. Параграф 7.6 рекомендует значение 3.

B.2. Переменные

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

max_datagram_size

Текущий максимальный размер содержимого (payload) для отправителя без учёта заголовков UDP и IP. Значение max_datagram_size применяется при расчёте окна перегрузки. Конечная точка устанавливает значение этой переменной на основе максимального блока данных для пути (Path Maximum Transmission Unit или PMTU, см. параграф 14.2 в [QUIC-TRANSPORT]), но не менее 1200 байтов.

ecn_ce_counters[kPacketNumberSpace]

Наибольшее значение счётчика ECN-CE в пространстве номеров пакета, сообщённое партнёром в кадре ACK. Это значение применяется для обнаружения роста сообщённых счётчиков ECN-CE.

bytes_in_flight

Суммарное число байтов во всех переданных пакетах, содержащих кадр с запросом подтверждения или PADDING, которые ещё не были подтверждены или объявлены потерянными. Заголовки IP и UDP не учитываются, но включается заголовок QUIC и данные аутентифицированного шифрования со связанными данными (Authenticated Encryption with Associated Data или AEAD). Пакеты, содержащие лишь кадры ACK, не учитываются в bytes_in_flight, чтобы контроль перегрузок не препятствовал обратной связи в случае насыщения.

congestion_window

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

congestion_recovery_start_time

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

ssthresh

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

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

B.3. Инициализация

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

   congestion_window = kInitialWindow
   bytes_in_flight = 0
   congestion_recovery_start_time = 0
   ssthresh = infinite
   for pn_space in [ Initial, Handshake, ApplicationData ]:
     ecn_ce_counters[pn_space] = 0

B.4. Передача пакета

При каждой отправке пакета, содержащего кадры, отличные от ACK, увеличивается значение bytes_in_flight.

   OnPacketSentCC(sent_bytes):
     bytes_in_flight += sent_bytes

B.5. Подтверждение пакета

Приведённый ниже псевдокод вызывается из OnAckReceived для обнаружения потерь с недавними acked_packets из числа sent_packets. В механизмах предотвращения перегрузки разработчикам, применяющим целочисленное представление congestion_window, следует быть осторожными с делением и можно применять другой подход, предложенный в параграфе 2.1 [RFC3465].

   InCongestionRecovery(sent_time):
     return sent_time <= congestion_recovery_start_time

   OnPacketsAcked(acked_packets):
     for acked_packet in acked_packets:
       OnPacketAcked(acked_packet)

   OnPacketAcked(acked_packet):
     if (!acked_packet.in_flight):
       return;
     // Исключение из bytes_in_flight.
     bytes_in_flight -= acked_packet.sent_bytes
     // Не увеличивать congestion_window, если ограничено
     // приложением или контролем потока данных.
     if (IsAppOrFlowControlLimited())
       return
     // Не увеличивать congestion_window в период восстановления.
     if (InCongestionRecovery(acked_packet.time_sent)):
       return
     if (congestion_window < ssthresh):
       // Замедленный старт.
       congestion_window += acked_packet.sent_bytes
     else:
       // Предотвращение перегрузки.
       congestion_window +=
         max_datagram_size * acked_packet.sent_bytes
         / congestion_window

B.6. Событие перегрузки

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

   OnCongestionEvent(sent_time):
     // Нет реакции, если период восстановления уже начат.
     if (InCongestionRecovery(sent_time)):
       return

     // Вход в период восстановления.
     congestion_recovery_start_time = now()
     ssthresh = congestion_window * kLossReductionFactor
     congestion_window = max(ssthresh, kMinimumWindow)
     // Можно передать пакет для ускорения восстановления.
     MaybeSendOnePacket()

B.7. Обработка сведений ECN

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

   ProcessECN(ack, pn_space):
     // Если сообщённое партнёром значение ECN-CE увеличивается,
     // это может быть новым фактом перегрузки.
     if (ack.ce_counter > ecn_ce_counters[pn_space]):
       ecn_ce_counters[pn_space] = ack.ce_counter
       sent_time = sent_packets[ack.largest_acked].time_sent
       OnCongestionEvent(sent_time)

B.8. Потеря пакета

Приведённый ниже псевдокод вызывается, когда DetectAndRemoveLostPackets считает пакеты потерянными.

   OnPacketsLost(lost_packets):
     sent_time_of_last_loss = 0
     // Исключение потерянных пакетов из bytes_in_flight.
     for lost_packet in lost_packets:
       if lost_packet.in_flight:
         bytes_in_flight -= lost_packet.sent_bytes
         sent_time_of_last_loss =
           max(sent_time_of_last_loss, lost_packet.time_sent)
     // Перегрузка, если находящиеся в пути пакеты потеряны
     if (sent_time_of_last_loss != 0):
       OnCongestionEvent(sent_time_of_last_loss)

     // Сброс окна перегрузки, если потеря этих пакетов указывает
     // продолжающуюся перегрузку. Учитываются лишь пакеты,
     // переданные после выборки RTT.
     if (first_rtt_sample == 0):
       return
     pc_lost = []
     for lost in lost_packets:
       if lost.time_sent > first_rtt_sample:
         pc_lost.insert(lost)
     if (InPersistentCongestion(pc_lost)):
       congestion_window = kMinimumWindow
       congestion_recovery_start_time = 0

B.9. Исключение отброшенных пакетов из числа байтов в пути

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

   RemoveFromBytesInFlight(discarded_packets):
     // Исключение неподтвержденных пакетов 
     // из числа находящихся в пути.
     foreach packet in discarded_packets:
       if packet.in_flight
         bytes_in_flight -= size

Участники работы

Рабочая группа IETF QUIC получила огромную поддержку от многих людей. Ниже перечислены те, кто внёс существенный вклад в этот документ.

Alessandro Ghedini

Benjamin Saunders

Gorry Fairhurst

山本和彦 (Kazu Yamamoto)

奥 一穂 (Kazuho Oku)

Lars Eggert

Magnus Westerlund

Marten Seemann

Martin Duke

Martin Thomson

Mirja Kühlewind

Nick Banks

Praveen Balasubramanian

Адреса авторов

Jana Iyengar (editor)

Fastly

Email: jri.ietf@gmail.com

Ian Swett (editor)

Google

Email: ianswett@google.com


Перевод на русский язык

Николай Малых

nmalykh@protokols.ru

1Internet Engineering Task Force.

2Internet Engineering Steering Group.

3Congestion Experienced — наступила перегрузка.

Рубрика: RFC | Оставить комментарий

RFC 9001 Using TLS to Secure QUIC

Internet Engineering Task Force (IETF)                   M. Thomson, Ed.
Request for Comments: 9001                                       Mozilla
Category: Standards Track                                 S. Turner, Ed.
ISSN: 2070-1721                                                    sn3rd
                                                                May 2021

Using TLS to Secure QUIC

Использование TLS для защиты QUIC

PDF

Аннотация

Этот документ описывает применение защиты на транспортном уровне (Transport Layer Security или TLS) для QUIC.

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

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

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

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

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

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

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

1. Введение

В этом документе описан способ защиты QUIC [QUIC-TRANSPORT] с использованием TLS [TLS13].

TLS 1.3 обеспечивает значительное снижение задержки при организации соединений по сравнению с предыдущими версиями. При отсутствии потери пакетов большинство новых соединений может быть организовано и защищено за один круговой обход, а в последующих соединениях между теми же клиентом и сервером клиент зачастую может передавать данные приложения сразу же, используя соединение без кругового обхода (zero round-trip setup).

Этот документ описывает использование TLS для защиты QUIC.

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

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

В этом документе используются термины, определённые в [QUIC-TRANSPORT].

Для краткости аббревиатура TLS обозначает TLS 1.3, хотя могут применяться и более новые версии (параграф 4.2).

2.1. Обзор TLS

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

TLS представляет собой многоуровневый протокол, структура которого показана на рисунке 1.

            +------------+-----------+--------------+---------+
Уровень     |            |           |    Данные    |         |
содержимого |Согласование|  Сигналы  |  приложения  |   ...   |
            |            |           |              |         |
            +------------+-----------+--------------+---------+
Уровень     |                                                 |
записи      |                    Записи                       |
            |                                                 |
            +-------------------------------------------------+

Рисунок 1. Уровни TLS.


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

Между конечными точками (клиент и сервер) выполняется аутентифицированный обмен ключами. Обмен инициирует клиент, а сервер отвечает ему. При успешном обмене ключами клиент и сервер согласуют секрет. TLS поддерживает заранее распространённые общие ключи (pre-shared key или PSK) и обмен Diffie-Hellman по конечным полям или эллиптическим кривым ((EC)DHE). PSK служит основой для начальных данных (Early Data, 0-RTT), а обмен — совершенную защиту (forward secrecy или FS) при уничтожении ключей (EC)DHE. Режимы можно комбинировать для обеспечения совершенной защиты при аутентификации PSK.

По завершении согласования TLS клиент узнает и подтвердит отождествление сервера, а сервер сможет узнать и отождествить клиента. TLS поддерживает аутентификацию на основе сертификатов X.509 [RFC5280] для клиента и сервера. При использовании обмена ключами PSK (как при возобновлении) знание PSK служит для аутентификации партнёра.

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

TLS обеспечивает два основных режима согласования для QUIC.

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

  • Согласование 0-RTT, где клиент использует полученные ранее от сервера сведения для немедленной отправки данных приложения. Эти данные могут быть воспроизведены (replay) атакующим, поэтому 0-RTT не подходит для передачи инструкций, способных вызвать какие-либо действия с нежелательными последствиями.

Упрощённая схема согласования TLS с данными приложения 0-RTT показана на рисунке 2.

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

 ClientHello
(0-RTT Application Data)  -------->
                                               ServerHello
                                      {EncryptedExtensions}
                                                 {Finished}
                          <-------- [Application Data] {Finished} -------->

[Application Data]        <------->      [Application Data]

 () Сообщения, защищенные ключами Early Data (0-RTT)
 {} Сообщения, защищенные ключами Handshake 
 [] Сообщения, защищенные ключами Application Data (1-RTT)

Рисунок 2. TLS Handshake с 0-RTT.


На рисунке 2 не показано сообщение EndOfEarlyData, которое не применяется в QUIC (см. параграф 8.3), как и сообщения ChangeCipherSpec и KeyUpdate. Сообщение ChangeCipherSpec избыточно в TLS 1.3 (параграф 8.4). В QUIC имеется свой механизм обновления ключей, описанный в разделе 6. Обновление ключей.

Данные защищаются с использованием нескольких уровней шифрования:

  • ключи Initial;

  • ключи 0-RTT;

  • ключи Handshake;

  • ключи 1-RTT.

Данные приложений могут присутствовать на уровнях 0-RTT и 1-RTT, сообщения согласования и сигналов — на любом.

Согласование 0-RTT может применяться, если между клиентом и сервером уже было взаимодействие. В согласовании 1-RTT клиент не может передавать защищённые данные приложения, пока сервер не передаст сообщения Handshake.

3. Обзор протокола

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

+--------------+--------------+ +-------------+
| Согласование |   Сигналы    | | Приложения  |
|     TLS      |     TLS      | |    QUIC     |
|              |              | | (h3 и т. п.)|
+--------------+--------------+-+-------------+
|                                             |
|                Транспорт QUIC               |
|   (потоки, надежность, перегрузки и пр.)    |
|                                             |
+---------------------------------------------+
|                                             |
|           Защита пакетов QUIC               |
|                                             |
+---------------------------------------------+

Рисунок 3. Уровни QUIC.


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

  • TLS передаёт и принимает сообщения через QUIC с обеспечением абстракции надёжного потока для TLS;

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

На рисунке 4 более подробно показаны эти взаимодействия, где защита пакетов QUIC вызывается отдельно.

+------------+                               +------------+
|            |<-- Сообщения согласования --->|            |
|            |<- Проверка параметров 0-RTT ->|            |
|            |<-------- Ключи 0-RTT ---------|            |
|    QUIC    |<------ Ключи Handshake -------|    TLS     |
|            |<-------- Ключи 1-RTT ---------|            |
|            |<--- Согласование завершено ---|            |
+------------+                               +------------+
 |         ^
 | Защита  | Защищенный
 v         | паекет
+------------+
|  Защита    |
|  пакета    |
|   QUIC     |
+------------+

Рисунок 4. Взаимодействие QUIC и TLS.


В отличие от TLS по протоколу TCP, приложения QUIC, желающие передавать данные, не шлют их с использованием записей TLS Application Data, а просто передают кадры QUIC STREAM или иных типов, которые доставляются в пакетах QUIC.

4. Передача сообщений TLS

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

Каждый уровень шифрования соответствует пространству номеров пакетов. Используемое пространство номеров определяет семантика кадра. Некоторые кадры запрещены в разных пространствах номеров (см. параграф 12.5 в [QUIC-TRANSPORT]).

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

Таблица 1. Ключи шифрования по типам пакетов.

Тип пакета

Ключи шифрования

Пространство номеров

Initial

Initial secrets

Initial

0-RTT Protected

0-RTT

Application data

Handshake

Handshake

Handshake

Retry

Retry

N/A

Version Negotiation

N/A

N/A

Short Header

1-RTT

Application data

В разделе 17 [QUIC-TRANSPORT] показано использование пакетов с разным уровнем шифрования при согласовании.

4.1. Интерфейс с TLS

Как показано на рисунке 4, интерфейс из QUIC в TLS поддерживает четыре основных функции:

  • передача и приём сообщений в процессе согласования;

  • обработка сохранённого состояния транспорта и приложения из возобновляемой сессии и определение их пригодности для генерации или восприятия данных 0-RTT;

  • смена ключей (отправка и приём);

  • обновление статуса согласования.

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

4.1.1. Завершение согласования

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

4.1.2. Подтверждение согласования

В этом документе согласование TLS считается подтверждённым на сервере после его завершения. Сервер должен передать кадр HANDSHAKE_DONE, как только согласование завершится. Клиент считает согласование завершённым после получения кадра HANDSHAKE_DONE.

Кроме того, клиент может считать согласование завершённым, получив подтверждение для пакета 1-RTT. Это может быть реализовано путём записи наименьшего порядкового номера пакета, переданного с ключами 1-RTT, и сравнения его с Largest Acknowledged в любом принятом кадре 1-RTT ACK — большее значение последнего подтверждает согласование.

4.1.3. Отправка и получение сообщений Handshake

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

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

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

Применяются 4 уровня шифрования, создающих ключи для пакетов Initial, 0-RTT, Handshake и 1-RTT. Кадры CRYPTO передаются только на трёх уровнях (без 0-RTT). Этим 4 уровням соответствуют три пространства номеров пакетов — пакеты Initial используют отдельные пространства, а 0-RTT и 1-RTT — пространство данных приложения.

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

Кадры QUIC CRYPTO передают лишь сообщения согласования TLS. Сигналы TLS преобразуются в коды ошибок QUIC CONNECTION_CLOSE (см. параграф 4.8). Данные приложения TLS и другие типы содержимого не могут транспортироваться протоколом QUIC на любом из уровней шифрования и получение их от стека TLS является ошибкой.

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

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

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

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

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

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

Завершение согласования TLS указывается протоколу QUIC вместе с финальными байтами согласования, которые TLS требуется передать. На этом этапе проверяется подлинность транспортных параметров, анонсированных партнёром при согласовании (см. параграф 8.2).

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

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

4.1.4. Смена уровня шифрования

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

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

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

  • секрет;

  • функция аутентифицированного шифрования со связанными данными (Authenticated Encryption with Associated Data или AEAD);

  • функция вывода ключа (Key Derivation Function или KDF).

Эти значения основаны на согласуемых TLS значениях и применяются QUIC в Handshake Confirmed для генерации ключей защиты пакета и заголовков (см. раздел 5 и параграф 5.4).

0-RTT (при возможности) готов к использованию после того, как клиент передаст сообщение TLS ClientHello или сервер получит его. После предоставления клиенту QUIC первых байтов согласования стек TLS может сигнализировать смену ключей 0-RTT. На сервере после получения байтов согласования с сообщением ClientHello сервер TLS может сигнализировать доступность ключей 0-RTT.

Хотя TLS в каждый момент использует лишь один уровень шифрования, QUIC может использовать несколько. Например, после отправки сообщения Finished (с использованием кадра CRYPTO на уровне шифрования Handshake) конечная точка может передать данные STREAM (шифрование 1-RTT). Если сообщение Finished теряется, конечная точка использует уровень шифрования Handshake для повторной передачи потерянного сообщения. Нарушение порядка или потеря пакетов могут означать для QUIC необходимость обрабатывать пакеты с разными уровнями шифрования. В процессе согласования это означает возможность обработки пакетов с более высоким и более низким уровнем шифрования по сравнению с текущим уровнем, используемым TLS.

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

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

4.1.5. Сводка по интерфейсу TLS

На рисунке 5 показан обмен между QUIC и TLS для клиента и сервера. Сплошные стрелки указывают пакеты с данными согласования, пунктирные — пакеты с данными приложения. Каждая стрелка помечена применяемым уровнем шифрования.

На рисунке показано несколько пакетов, образующих одну отправку (flight) сообщений, которые обрабатываются по отдельности, для демонстрации разных действий, вызываемых входящими сообщениями. Это показано несколькими вызовами Get Handshake для извлечения сообщений с разными уровнями шифрования. Новые сообщения согласования запрашиваются после обработки входящих пакетов.

Клиент                                                    Сервер
======                                                    ======
Get Handshake
                     Initial ------------->
Install tx 0-RTT keys
                     0-RTT - - - - - - - ->

                                              Handshake Received
                                                   Get Handshake
                     <------------- Initial
                                           Install rx 0-RTT keys
                                          Install Handshake keys
                                                   Get Handshake
                     <----------- Handshake
                                           Install tx 1-RTT keys
                     <- - - - - - - - 1-RTT 
Handshake Received (Initial) 
Install Handshake keys 
Handshake Received (Handshake) 
Get Handshake 
                     Handshake ----------->
Handshake Complete
Install 1-RTT keys
                     1-RTT - - - - - - - ->

                                              Handshake Received
                                              Handshake Complete
                                             Handshake Confirmed
                                           Install rx 1-RTT keys
                     <--------------- 1-RTT
                           (HANDSHAKE_DONE)
Handshake Confirmed

Рисунок 5. Сводка взаимодействия между QUIC и TLS.


Рисунок 5 иллюстрирует одну из простых структур для одного обмена при согласовании. Точный процесс зависит от структуры реализации конечных точек и порядка прибытия пакетов. Реализации могут использовать иное число операций или выполнять их в другом порядке.

4.2. Версия TLS

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

Клиентам недопустимо предлагать версии TLS до 1.3. некорректно настроенная реализация TLS может согласовать TLS 1.2 или другую старую версию. Конечная точка должна прервать соединение при согласовании версии TLS до 1.3.

4.3. Размер ClientHello

Первый пакет Initial от клиента содержит начало или все первое сообщение криптографического согласования, которым для TLS является ClientHello. Серверам может потребоваться синтаксический анали всего ClientHello (например, для доступа к таким расширениям, как SNI3 или ALPN4) для принятия решения о восприятии нового входящего соединения QUIC. Если сообщение ClientHello разделено между несколькими пакетами Initial, серверу придётся буферизовать полученные в начале фрагменты, что может потребовать избыточных ресурсов, если адрес клиента ещё не проверен. Для предотвращения этого серверы могут использовать свойство Retry (см. параграф 8.1 в [QUIC-TRANSPORT]) для буферизации частичных сообщений ClientHello лишь от клиентов с проверенным адресом.

Пакет QUIC и кадрирование добавляют по меньшей мере 36 байтов к размеру сообщения ClientHello. Эти издержки возрастают при выборе клиентом непустого поля Source Connection ID. Издержки не включают маркер и Destination Connection ID длиннее 8 байтов, которые могут потребоваться, если сервер передал пакет Retry.

Типичное сообщение TLS ClientHello может легко поместиться в пакет размером 1200 байтов, однако в дополнение к издержкам QUIC имеется несколько переменных, которые могут вызвать превышение этого размера. Большие сеансовые квитанции, большие или многочисленные общие ключи, длинные списки поддерживаемых шифров, алгоритмов подписи, версий, транспортных параметров QUIC и другие согласуемые параметры и расширения ведут к росту сообщения.

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

Реализация TLS не обязана гарантировать, что сообщение ClientHello достаточно велико в соответствии с требованиями QUIC для дейтаграмм с пакетом Initial (см. параграф 14.1 в [QUIC-TRANSPORT]). Реализации QUIC используют кадры PADDING или объединение пакетов для увеличения размера дейтаграмм.

4.4. Проверка подлинности партнёра.

Требования к аутентификации зависят от применяемого прикладного протокола. TLS обеспечивает проверку подлинности сервера и позволяет серверам проверить подлинность клиентов. Клиент должен проверять подлинность сервера. Обычно это включает проверку включения идентификации сервера в сертификат и выпуск сертификата доверенной организацией (см. пример в [RFC2818]).

Примечание. Если сервер предоставляет сертификаты для аутентификации, размер цепочки сертификатов может быть достаточно большим. Контролирование размера цепочек сертификатов очень важно для производительности QUIC, поскольку серверы могут передавать не более 3 байтов в ответ на каждый полученный байт, пока адрес клиента не проверен (см. параграф 8.1 в [QUIC-TRANSPORT]). Размер цепочки сертификатов можно сократить, ограничивая число имён или расширений, используя компактное представление открытых ключей, подобное ECDSA, или сжимая сертификаты [COMPRESS].

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

Серверу недопустимо проверять подлинность клиента после согласования (как указано в параграфе 4.6.2 [TLS13]), поскольку мультиплексирование в QUIC не позволяет клиентам сопоставить запрос сертификата с вызвавшим его событием на уровне приложения (см. [HTTP2-TLS13]). Более конкретно, серверам недопустимо передавать сообщения TLS CertificateRequest после согласования, а клиенты должны считать получение такого сообщения ошибкой соединения типа PROTOCOL_VIOLATION.

4.5. Возобновление сессии

QUIC может использовать функцию восстановления сессии TLS 1.3. Это делается путём передачи сообщений NewSessionTicket в кадрах CRYPTO после завершения согласования. Возобновление сессии моно использовать для обеспечения 0-RTT даже при отключённом 0-RTT.

Конечным точкам, возобновляющим сессию, может потребоваться запомнить некую информацию о текущем соединении при создании возобновлённого соединения. TLS требует сохранения некой информации (см. параграф 4.6.1 в [TLS13]). Протокол QUIC не зависит от сохранения какого-либо состояния при возобновлении соединения, пока не применяется 0-RTT (см. параграф 7.4.1 в [QUIC-TRANSPORT] и параграф 4.6.1). Протокол приложения может зависеть от состояния, сохраняемого между соединениями.

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

Возобновление сессии помогает серверам связывать действия в исходном соединении с возобновляемым, что может создавать для клиентов проблемы приватности. Клиенты могут отказаться от возобновления сессий для предотвращения такого сопоставления. Клиентам не следует повторно применять квитанции, поскольку это может помочь сторонним объектам сопоставить соединения (см. Приложение C.4 к [TLS13]).

4.6. 0-RTT

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

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

[TLS13] устанавливает 7-дневное ограничение между исходным соединением и попыткой использования 0-RTT. Имеются и другие ограничения для применения 0-RTT, в частности связанные с возможностью replay-атак (см. параграф 9.2).

4.6.1. Включение 0-RTT

Определено расширение TLS early_data в сообщении NewSessionTicket для передачи (в параметре max_early_data_size) объема данных TLS 0-RTT, которые сервер готов воспринять. QUIC не использует ранние данные TLS, применяя для передачи таких данных пакеты 0-RTT. Соответственно, параметр max_early_data_size переназначен для контрольного значения 0xffffffff, указывающего, что сервер готов воспринимать данные QUIC 0-RTT. Отсутствие расширения early_data в NewSessionTicket говорит о нежелании сервера принимать данные 0-RTT. Объем данных, которые клиент может передать в QUIC 0-RTT, задаёт переданный сервером параметр initial_max_data.

Серверам недопустимо передавать расширение early_data с полем max_early_data_size, отличным от 0xffffffff. Клиент должен считать получение NewSessionTicket с расширением early_data, содержащим иное значение, ошибкой соединения типа PROTOCOL_VIOLATION.

Клиент, желающий передавать пакеты 0-RTT, использует расширение early_data в сообщении ClientHello последующего согласования (см. параграф 4.2.10 в [TLS13]) и затем передаёт данные в пакетах 0-RTT.

Клиент, пытающийся передать 0-RTT, может также предоставить маркер проверки адреса, если сервер передал ему пакет NEW_TOKEN (см. параграф 8.1 в [QUIC-TRANSPORT]).

4.6.2. Восприятие и отклонение 0-RTT

Сервер воспринимает 0-RTT, отправляя расширение early_data в EncrypteEncryptedExtensions (см. параграф 4.2.10 в [TLS13]). После этого сервер обрабатывает и подтверждает получаемые пакеты 0-RTT. Чтобы отвергнуть 0-RTT, сервер передаёт EncryptedExtensions без расширения early_data. Сервер всегда будет отвергать 0-RTT, если он передал TLS HelloRetryRequest. Отвергающему 0-RTT серверу недопустимо обрабатывать пакеты 0-RTT, даже когда он способен делать это. Если пакеты 0-RTT отвергнуты, клиенту следует считать приём подтверждения пакета 0-RTT ошибкой соединения PROTOCOL_VIOLATION, если он может обнаруживать это условие.

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

Клиент может повторить попытку 0-RTT при получении пакета Retry или Version Negotiation. Эти пакеты не означают отказа от 0-RTT.

4.6.3. Проверка конфигурации 0-RTT

При получении сервером ClientHello с расширением early_data он должен принять решение о восприятии или отклонении 0-RTT от клиента. Отчасти решение определяет стек TLS (например, проверка наличия возобновляемого шифра в ClientHello, см. параграф 4.2.10 в [TLS13]). Даже при отсутствии у стека TLS причин отвергать 0-RTT, стек QUIC или прикладной протокол, использующий QUIC, может отклонить данные 0-RTT по причине несовместимости конфигурации транспорта или приложения, связанной с возобновляемым соединением, с текущей настройкой сервера.

QUIC требует связывания дополнительного состояния транспорта с сеансовой квитанцией 0-RTT. Одним из основных способов реализации этого является использование сеансовых квитанций без учёта состояния и сохранение состояния в этой квитанции. Прикладной протокол, использующий QUIC, может иметь похожие требования в части связывания или сохранения статуса. Это связанное состояние применяется при решении вопроса об отклонении 0-RTT. Например, настройки HTTP/3 [QUIC-HTTP] могут определять интерпретацию клиентских данных 0-RTT. Другие приложения, использующие QUIC, могут иметь свои требования в части восприятия или отклонения данных 0-RTT.

4.7. HelloRetryRequest

Сообщение HelloRetryRequest (см. параграф 4.1.4 в [TLS13]) может служить для запроса у клиента новых сведений, таких как общий ключ, или для проверки некоторых характеристик клиента. С точки зрения QUIC сообщение HelloRetryRequest не отличается от других сообщений криптографического согласования, передаваемых в пакетах Initial. Хотя это свойство можно применять для проверки адреса, реализациям QUIC следует использовать для этого Retry (см. параграф 8.1 в [QUIC-TRANSPORT]).

4.8. Ошибки TLS

При возникновении ошибки TLS генерирует сигнал в соответствии с разделом 6 в [TLS13], который преобразуется в ошибку соединения QUIC. Значение AlertDescription добавляется к 0x0100 для создания кода ошибки QUIC из диапазона для CRYPTO_ERROR (параграф 20.1 в [QUIC-TRANSPORT]) и полученное значение передаётся в кадре QUIC CONNECTION_CLOSE типа 0x1c.

QUIC может передавать лишь сигналы критического уровня (fatal). В TLS 1.3 единственным применением уровня предупреждения (warning) является сигнализация о закрытии соединения (параграф 6.1 в [TLS13]). QUIC поддерживает другие механизмы прерывания соединений, а соединение TLS закрывается лишь при ошибке и конечная точка QUIC должна считать любой сигнал от TLS, как сигнал уровня fatal.

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

4.9. Отбрасывание неиспользуемых ключей

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

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

Конечная точка не может отбросить ключи для данного уровня шифрования, пока она не получит от партнёра все сообщения криптографического согласования на данном уровне от своего партнёра и партнёр не сделает то же самое. Для ключей Initial (параграф 4.9.1) и Handshake (параграф 4.9.2) предусмотрены другие методы контроля отбрасывания. Эти методы не препятствуют приёму или отправке пакетов на данном уровне шифрования, поскольку партнёр мог не получить все требуемые подтверждения.

Хотя конечная точка может сохранять старые ключи, новые данные должны передаваться с наивысшим доступным уровнем шифрования, а прежний уровень можно применять лишь для кадров ACK и данных, повторяемых в кадрах CRYPTO. Такие пакеты могут также включать кадры PADDING.

4.9.1. Отбрасывание ключей Initial

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

Успешное использование пакетов Handshake показывает, что обмен пакетами Initial больше не требуется, поскольку нужные для этого ключи могут создаваться лишь после получения всех кадров CRYPTO из пакетов Initial. Поэтому клиент должен отбросить ключи Initial при первой отправке пакета Handshake, а сервер должен отбросить эти ключи при первой успешной обработке пакета Handshake. После этого конечным точкам недопустимо передавать пакеты Initial.

Это ведёт к отказу от состояния восстановления потерь для уровня шифрования Initial и игнорированию оставшихся пакетов Initial.

4.9.2. Отбрасывание ключей Handshake

Конечная точка должна отбросить ключи Handshake после подтверждения согласования TLS (параграф 4.1.2).

4.9.3. Отбрасывание ключей 0-RTT

Пакеты 0-RTT и 1-RTT используют общее пространство номеров и клиенты не передают пакеты 0-RTT после отправки 1-RTT (параграф 5.6). Поэтому клиенту следует отбрасывать ключи 0-RTT, как только он установит ключи 1-RTT.

Кроме того, сервер может отбросить ключи 0-RTT, как только получит пакет 1-RTT. Однако в результате нарушения порядка пакеты 0-RTT могут приходить после 1-RTT. Сервер может временно сохранить ключи 0-RTT для обработки доставленных с нарушением порядка пакетов без необходимости повторять их содержимое с ключами 1-RTT. После приёма пакета 1-RTT сервер должен отбрасывать пакеты 0-RTT по истечении короткого времени, для которого рекомендуется устанавливать утроенное значение тайм-аута зондирования (Probe Timeout или PTO, см. [QUIC-RECOVERY]). Сервер может начать отбрасывание 0-RTT раньше, если он понимает, что все пакеты 0-RTT получены, что можно определить путём отслеживания пропущенных номеров.

5. Защита пакета

Как и TLS про протоколу TCP, QUIC защищает пакеты с помощью ключей, выведенных из согласования TLS с использованием алгоритма AEAD [AEAD] согласованного TLS. Защита пакетов QUIC зависит от их типа:

  • для пакетов Version Negotiation криптографическая защита не применяется;

  • пакеты Retry используют AEAD_AES_128_GCM для защиты от случайного изменения и ограничения числа объектов, которые могут создавать действительные пакеты Retry (см. параграф 5.8);

  • пакеты Initial применяют AEAD_AES_128_GCM с ключами, выведенными из поля Destination Connection ID в первом пакете Initial от клиента (см. параграф 5.2);

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

В этом разделе описано применение защиты к пакетам Handshake, 0-RTT и 1-RTT. Такая же защита используется для пакетов Initial. Однако определить ключи защиты пакетов Initial несложно, поэтому конфиденциальность и целостность их не считается защищённой. Пакеты Retry используют фиксированный ключ и также не защищены в части конфиденциальности и целостности.

5.1. Ключи защиты пакета

QUIC выводит ключи защиты пакетов таким же способом, как TLS выводит ключи защиты записей.

Каждый уровень шифрования имеет свои секретные значения для защиты пакетов в каждом направлении. Эти секреты трафика выводятся TLS (см. параграф 7.1 и [TLS13]) и применяются QUIC для всех уровней шифрования кроме уровня Initial. Секреты для уровня шифрования Initial рассчитываются на основе исходного значения Destination Connection ID, полученного от клиента, как описано в параграфе 5.2.

Ключи защиты пакетов рассчитываются из секретов TLS с использованием функции KDF, предоставляемой TLS. В TLS 1.3 применяется функция HKDF-Expand-Label, описанная в параграфе 7.1 [TLS13], с хэш-функцией из согласованного шифронабора. При любом применении HKDF-Expand-Label в QUIC используется Context нулевого размера (пустой). Отметим, что метки, описываемые строками, кодируются как байты с использованием кодировки ASCII [ASCII] без кавычек и NUL-байта в конце.

Другие версии TLS должны предоставлять похожую функцию для использования в QUIC.

Секрет текущего уровня шифрования и метка quic key служат входными данными KDF для создания ключа AEAD, а метка quic iv служит для вывода вектора инициализации (Initialization Vector или IV, см. параграф 5.3). Ключ защиты заголовка использует метку quic hp (см. параграф 5.4). Применение меток обеспечивает разделение ключей QUIC и TLS (см. параграф 9.6).

Метки quic key и quic hp применяются для создания ключей, поэтому размер Length, предоставляемый HKDF-Expand-Label, вместе с этими метками определяется размером ключей в AEAD или алгоритме защиты заголовка. Length для quic iv является минимальным размером AEAD nonce или составляет 8 байтов, если тот больше [AEAD].

KDF, используемой для начальных секретов, всегда служит функция HKDF-Expand-Label из TLS 1.3 (см. параграф 5.2).

5.2. Секреты Initial

Пакеты Initial используют защиту, но секрет выводится из поля Destination Connection ID в первом пакете Initial от клиента. Этот секрет определяется использованием HKDF-Extract (см. параграф 2.2 в [HKDF]) с затравкой (salt) 0x38762cf7f55934b34d179ae6a4c80cadccbb7f0a и входным ключевым материалом (input keying material или IKM) из поля Destination Connection ID. В результате создаётся промежуточный псевдослучайный ключ (pseudorandom key или PRK), применяемый для создания двух секретов, используемых при передаче и приёме.

Секрет, применяемый клиентами при создании пакетов Initial, использует PRK и метку client in как входные данные функции HKDF-Expand-Label из TLS [TLS13] для создания 32-байтового секрета. В создаваемых сервером пакетах применяется тот же процесс с меткой server in. Хэш-функцией для HKDF при создании начальных секретов служит SHA-256 [SHA]. Псевдокод процесса приведён ниже.

   initial_salt = 0x38762cf7f55934b34d179ae6a4c80cadccbb7f0a
   initial_secret = HKDF-Extract(initial_salt, client_dst_connection_id)

   client_initial_secret = HKDF-Expand-Label(initial_secret,
                                             "client in", "",
                                             Hash.length)
   server_initial_secret = HKDF-Expand-Label(initial_secret,
                                             "server in", "",
                                             Hash.length)

Идентификатор соединения, используемый с HKDF-Expand-Label, — это Destination Connection ID из пакета Initial, переданного клиентом. Это поле содержит случайное значение, если клиент не создаёт пакет Initial после получения пакета Retry, где значение Destination Connection ID выбрано сервером.

Будущим версиям QUIC следует применять новое значение затравки, чтобы ключи отличались в разных версиях QUIC. Это не позволит промежуточному устройству, распознающему лишь одну версию QUIC, просматривать или изменять содержимое пакетов будущих версий. Функция HKDF-Expand-Label из TLS 1.3 должна применяться для пакетов Initial даже при отсутствии TLS 1.3 среди предлагаемых версий TLS.

Секреты, применяемые для создания последующих пакетов Initial, меняются, когда сервер передает пакет Retry с выбранным им идентификатором соединения. Секреты не меняются при изменении клиентом значения Destination Connection ID, используемого им в ответ на пакет Initial от сервера.

Примечание. Поле Destination Connection ID может иметь любой размер до 20 байтов, включая 0, если сервер передал пакет Retry с пустым полем Source Connection ID. После Retry ключи Initial не обеспечивают клиенту гарантии получения его пакета сервером, поэтому клиенту приходиться полагаться на обмен, включающий пакет Retry, для проверки адреса сервера (см. параграф 8.1 в [QUIC-TRANSPORT]).

Примеры пакетов Initial представлены в Приложении A.

5.3. Применение AEAD

Функция AEAD [AEAD], применяемая для защиты пакетов QUIC, является AEAD, согласованной для использования в соединении TLS. Например, если TLS использует шифр TLS_AES_128_GCM_SHA256, будет применяться функция AEAD_AES_128_GCM.

QUIC может применять любой шифронабор, заданный в [TLS13], за исключением TLS_AES_128_CCM_8_SHA256. Недопустимо согласовывать шифр, для которого не определена схема защиты заголовков. Этот документ определяет схему защиты заголовков для всех шифров, заданных в [TLS13], кроме TLS_AES_128_CCM_8_SHA256. Эти шифры имеют 16-байтовый тег аутентификации и дают на выходе рост на 16 байтов по сравнению со входными данными.

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

При создании пакетов функция AEAD применяется до защиты заголовка (см. параграф 5.4). Незащищённый заголовок является частью связанных данных (associated data или A). При обработке пакетов конечная точка сначала снимает защиту заголовка.

Ключ и IV для пакета рассчитываются в соответствии с параграфом 5.1. Значение nonce (N) формируется путём объединения IV защиты пакета с номером пакета. 62 бита восстановленного номера пакета QUIC в сетевом порядке байтов дополняются слева нулями до размера IV. После этого применяется операция «исключительное ИЛИ» (XOR) к дополненному номеру пакета и IV для создания AEAD.

Связанными данными (A) для AEAD является содержимое заголовка QUIC, начиная с первого байта короткого или длинного заголовка и заканчивая незащищённым номером пакета (включительно). Входными открытыми данными (plaintext или P) для AEAD служит содержимое (payload) пакета QUIC, как описано в [QUIC-TRANSPORT]. Выходной шифротекст (ciphertext или C) функции AEAD передаётся в пакете вместо P.

Некоторые функции AEAD имеют ограничения на число пакетов, шифруемых с одним ключом и IV (см. параграф 6.6). Этот предел может быть меньше предельного числа пакетов. Конечная точка должна запустить обновление ключей (раздел 6) до достижения предела, установленного для используемой функции AEAD.

5.4. Защита заголовка

Поля заголовка пакетов QUIC, в частности, Packet Number, защищаются с использованием ключа, выведенного отдельно от ключа защиты пакета и IV. Ключ выводится с использованием метки quic hp и применяется для защиты конфиденциальности полей, не раскрываемых элементам пути доставки.

Эта защита применяется для младших битов первого байта и полю Packet Number. Для пакетов с длинным заголовком защищаются 4 младших бита первого байта, для пакетов с коротким заголовком — 5. Для обоих вариантов заголовка это включает резервные биты и поле Packet Number Length, а для короткого заголовка — бит Key Phase.

В течение срока соединения применяется один ключ защиты заголовков без смены при обновлении ключей (раздел 6). Это позволяет защитить заголовок в Key Phase. Процесс защиты не применяется для пакетов Retry и Version Negotiation, которые не включают защищаемых данных или полей заголовков.

5.4.1. Применение защиты заголовка

Защита заголовка применяется после защиты пакета (см. параграф 5.3). Делается выборка шифрованного содержимого пакета, которая служит вводом для алгоритма шифрования. Алгоритм зависит от согласования AEAD. Выходом алгоритма является 5-байтовая маска, применяемая к защищаемым полям заголовка в операции «исключительное ИЛИ» (XOR). Младшие биты первого байта пакета маскируются младшими битами первого байта маски, а порядковый номер — её. оставшимися байтами. Лишние биты маски (если номер короткий) не применяются.

На рисунке 6 показан пример алгоритма для защиты заголовка. Снятие защиты заголовка отличается лишь порядком определения размера номера пакета (pn_length), ^ представляет операцию XOR.

   mask = header_protection(hp_key, sample)

   pn_length = (packet[0] & 0x03) + 1
   if (packet[0] & 0x80) == 0x80:
      # Long header: 4 bits masked
      packet[0] ^= mask[0] & 0x0f
   else:
      # Short header: 5 bits masked
      packet[0] ^= mask[0] & 0x1f

   # pn_offset – начало поля Packet Number.
   packet[pn_offset:pn_offset+pn_length] ^= mask[1:1+pn_length]

Рисунок 6. Псевдокод защиты заголовка.


Конкретные функции защиты заголовка определяются на основе выбранного шифра (см. параграфы 5.4.3 и 5.4.4).

На рисунке 7 показан пример пакетов с длинным (Initial) и коротким (1-RTT) заголовком и указаны поля в каждом заголовке, охватываемые защитой, а также выбираемые части защищённого пакета.

   Initial Packet {
     Header Form (1) = 1,
     Fixed Bit (1) = 1,
     Long Packet Type (2) = 0,
     Reserved Bits (2),         # Защищено
     Packet Number Length (2),  # Защищено
     Version (32),
     DCID Len (8),
     Destination Connection ID (0..160),
     SCID Len (8),
     Source Connection ID (0..160),
     Token Length (i),
     Token (..),
     Length (i),
     Packet Number (8..32),     # Защищено
     Protected Payload (0..24), # Пропускается
     Protected Payload (128),   # Выбирается
     Protected Payload (..)     # Остальное
   }

   1-RTT Packet {
     Header Form (1) = 0,
     Fixed Bit (1) = 1,
     Spin Bit (1),
     Reserved Bits (2),         # Защищено
     Key Phase (1),             # Защищено
     Packet Number Length (2),  # Защищено
     Destination Connection ID (0..160),
     Packet Number (8..32),     # Защищено
     Protected Payload (0..24), # Пропускается
     Protected Payload (128),   # Выбирается
     Protected Payload (..),    # Остальное
   }

Рисунок 7. Пример защиты заголовка и шифротекста.


До того, как шифр TLS можно будет применять в QUIC, должен быть задан алгоритм защиты заголовка и AEAD, используемый с этим шифром. Этот документ задаёт алгоритмы AEAD_AES_128_GCM, AEAD_AES_128_CCM, AEAD_AES_256_GCM (AES AEAD, определённые в [AEAD]) и AEAD_CHACHA20_POLY1305 (определён в [CHACHA]). До выбора шифронабора TLS применяется защита заголовка AES (параграф 5.4.3), соответствующая защите пакета AEAD_AES_128_GCM.

5.4.2. Пример защиты заголовка

Алгоритм защиты заголовка использует ключ защиты заголовка и выборку шифротекста из поля Payload в пакете. Отбирается всегда одинаковое количество данных, но необходимо учитывать снятие защиты на приёмной стороне, которая не знает размер поля Packet Number. Выборка шифрованных данных начинается со смещением 4 байта от начала поля Packet Number, т. е. при выборке предполагается 4-байтовое поле Packet Number (максимальный размер).

Конечная точка должна отбрасывать пакеты, размера которых недостаточно для полной выборки. Для обеспечения достаточного размера выборки пакеты дополняются так, суммарный размер кодированного номера пакета и шифрованного содержимого по меньшей мере на 4 байта превышает размер требуемой для защиты заголовка выборки. Шифры, заданные в [TLS13] (кроме TLS_AES_128_CCM_8_SHA256, не применяемого в схеме защиты заголовка) имеют 16-байтовые расширения и 16-байтовую выборку для защиты заголовка. Это требует по меньшей мере 3 байтов в кадрах незащищённого содержимого, если номер пакета кодируется одним байтом или 2 байтов в кадрах при 2-байтовом кодировании номера пакета. Выборку шифротекста можно реализовать приведённым ниже псевдокодом.

   # pn_offset начало поля Packet Number.
   sample_offset = pn_offset + 4

   sample = packet[sample_offset..sample_offset+sample_length]

Смещение номера пакета в коротком заголовке определяется как

   pn_offset = 1 + len(connection_id)

В пакете с длинным заголовком смещение порядкового номера рассчитывается как

   pn_offset = 7 + len(destination_connection_id) +
                   len(source_connection_id) +
                   len(payload_length)
   if packet_type == Initial:
       pn_offset += len(token_length) +
                    len(token)

Например, для пакета с коротким заголовком, 8-байтовым идентификатором соединения и защитой AEAD_AES_128_GCM, выборка будет включать байты с 13 по 28 (отсчёт от 0). В одну дейтаграмму UDP может включаться несколько пакетов QUIC, каждый из которых обрабатывается отдельно.

5.4.3. Защита заголовка на основе AES

В этом параграфе определён алгоритм защиты пакетов для AEAD_AES_128_GCM, AEAD_AES_128_CCM и AEAD_AES_256_GCM. AEAD_AES_128_GCM и AEAD_AES_128_CCM используют 128-битовый шифр AES в режиме ECB (Electronic Codebook — электронный шифровальный блокнот). AEAD_AES_256_GCM использует 256-битовый шифр AES в режиме ECB. Протокол AES определён в [AES].

Этот алгоритм извлекает 16 шифрованного содержимого и использует в AES-ECB. Псевдокод функции защиты заголовков имеет вид

   header_protection(hp_key, sample):
     mask = AES-ECB(hp_key, sample)

5.4.4. Защита заголовка на основе ChaCha20

При использовании AEAD_CHACHA20_POLY1305 для защиты заголовков применяется raw-функция ChaCha20, определённая в параграфе 2.4 [CHACHA]. Она использует 256-битовый ключ 16-байтовую выборку из защищённой части пакета. Первые 4 байта выборки служат счётчиком блоков. Реализация ChaCha20 может принимать 32-битовое целое число вместо последовательности байтов и в этом случае последовательность байтов интерпретируется как значение little-endian. Оставшиеся 12 используются как nonce. реализация ChaCha20 может принимать массив из трёх 32-битовых целых чисел вместо последовательности байтов и в этом случае байты nonce интерпретируются как последовательность 32-битовых целых чисел little-endian.

Маска шифрования создаётся вызовом ChaCha20 для защиты 5 байтов со значением 0. Псевдокод защиты заголовка имеет вид

   header_protection(hp_key, sample):
     counter = sample[0..3]
     nonce = sample[4..15]
     mask = ChaCha20(hp_key, counter, nonce, {0,0,0,0,0})

5.5. Приём защищённых пакетов

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

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

5.6. Использование ключей 0-RTT

Если доступны ключи 0-RTT (см. параграф 4.6.1), отсутствие защиты от повторного использования (replay) означает, что ограничения на применение ключей требуются для защиты от replay-атак на протокол. Среди определённых в [QUIC-TRANSPORT] кадров, для кадров STREAM, RESET_STREAM, STOP_SENDING, CONNECTION_CLOSE использование с 0-RTT может быть небезопасным, поскольку эти кадры содержат данные приложения. Полученные в 0-RTT данные могут заставить приложение на сервере обрабатывать данные несколько раз вместо одного. Предпринимаемые в результате сервером дополнительные действия по обработке повторно использованных данных приложения могут приводить к нежелательным последствиям. Поэтому клиенту недопустимо использовать 0-RTT для данных приложения, если это не запрашивается приложением специально.

Использующий QUIC прикладной протокол должен включать профиль, определяющий допустимость использования 0-RTT, иначе 0-RTT можно применять лишь для кадров QUIC, не содержащих данных приложения. Например, профиль для HTTP описан в [HTTP-REPLAY] и применяется для HTTP/3 (см. параграф 10.9 в [QUIC-HTTP]).

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

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

В остальном клиент считает ключи 0-RTT эквивалентом ключей 1-RTT, за исключением невозможности передачи некоторых кадров с ключами 0-RTT (см. параграф 12.5 в [QUIC-TRANSPORT]).

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

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

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

5.7. Получение разупорядоченных защищённых пакетов

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

  • Подлинность клиента не проверена, пока сервер не решил использовать распространённый заранее ключ и не проверил привязку заранее распространенного ключа клиента (см. параграф 4.2.11 в [TLS13]).

  • Клиент не продемонстрировал работоспособность, пока сервер не проверил адрес клиента с помощью пакета Retry или иным способом (см. параграф 8.1 в [QUIC-TRANSPORT]).

  • Все полученные данные 0-RTT, на которые сервер отвечает, могут быть использованными повторно (replay).

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

Примечание. Реализации TLS могут предоставлять все секреты 1-RTT до завершения согласования. Даже при наличии у реализации QUIC ключей чтения 1-RTT эти ключи не применяются до завершения согласования.

Требование к серверу ждать сообщения Finished от клиента создаёт зависимость от доставки этого сообщения. Клиент может предотвратить возможную блокировку head-of-line, которую это подразумевает, передавая свои пакеты 1-RTT объединёнными с пакетом Handshake, содержащим копию кадра CRYPTO с сообщением Finished, пока один из пакетов Handshake не будет подтверждён. Это позволяет серверу незамедлительно обработать такие пакеты.

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

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

5.8. Целостность пакета Retry

Пакеты Retry (см. параграф 17.2.5 в [QUIC-TRANSPORT]) переносят Retry Integrity Tag, позволяющий отбрасывать пакеты, случайно повреждённые в сети и разрешающий передачу пакета Retry лишь объекту, имеющему доступ к пакету Initial.

Retry Integrity Tag — это 128-битовое поле, возвращаемое функцией AEAD_AES_128_GCM [AEAD], по входным данным:

  • секретный ключ K — 128 битов со значением 0xbe0c690b9f66575a1d766b54e368c84e;

  • одноразовое значение (nonce) N — 96 битов со значением 0x461599d35d632bf2239825bb;

  • нешифрованные данные (plaintext) P с пустым значением;

  • связанные данные A, содержащие Retry Pseudo-Packet, как показано на рисунке 8.

Секретный ключ и nonce выводятся вызовом HKDF-Expand-Label с использованием секрета 0xd9c9943e6101fd200021506bcc02814c73030f25c79d71ce876eca876e6fca8e и метками quic key и quic iv (параграф 5.1).

   Retry Pseudo-Packet {
     ODCID Length (8),
     Original Destination Connection ID (0..160),
     Header Form (1) = 1,
     Fixed Bit (1) = 1,
     Long Packet Type (2) = 3,
     Unused (4),
     Version (32),
     DCID Len (8),
     Destination Connection ID (0..160),
     SCID Len (8),
     Source Connection ID (0..160),
     Retry Token (..),
   }

Рисунок 8. Псевдопакет Retry.


Псевдопакет Retry не передаётся в линию. Он рассчитывается по принятому пакету Retry путём удаления Retry Integrity Tag и добавления в начало двух полей.

ODCID Length

Размер поля Original Destination Connection ID (в байтах), представленный 8-битовым целым числом без знака.

Original Destination Connection ID

Значение поля Destination Connection ID из пакета Initial, вызвавшего данный пакет Retry. Размер этого поля указан в ODCID Length. Наличие этого поля гарантирует возможность передачи действительного пакета Retry лишь объектом, которому доступен пакет Initial.

6. Обновление ключей

Когда согласование подтверждено (см. параграф 4.1.2), конечная точка может инициировать обновление ключей.

Бит Key Phase указывает ключи, применяемые для защиты пакетов. Бит Key Phase исходно сброшен (0) для первого набора пакетов 1-RTT и переключается для сигнализации каждого последующего обновления ключей.

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

Инициирование обновления ключей ведёт к обновлению ключей в обеих конечных точках. Это отличается от TLS, где конечные точки могут обновляться независимо. Этот механизм заменяет механизм обновления ключей TLS, основанный на сообщениях KeyUpdate, передаваемых с использованием ключей шифрования 1-RTT. Конечным точкам недопустимо передавать сообщения TLS KeyUpdate и они должны считать получение такого сообщения ошибкой соединения типа 0x010a, эквивалентной сигналы TLS unexpected_message (см. параграф 4.8).

На рисунке 9 показан процесс обмена ключами, где исходные ключи (@M) заменяются новыми (@N). Значение бита Key Phase указано в квадратных скобках.

Партнер-инициатор                       Отвечающий партнер

@M [0] Пакеты QUIC

... Обновление до @N
@N [1] Пакеты QUIC 
                      -------->
                                      Обновление до @N ...
                                      Пакеты QUIC [1] @N
                      <--------
                                      Пакеты QUIC [1] @N,
                                      содержащие ACK
                      <-------- 
... Обновление ключей разрешено 

@N [1] Пакеты QUIC, 
       содержащие ACK для @N пакетов 
                      -------->
                           Обновление ключей разрешено ...

Рисунок 9. Обновление ключа.


6.1. Запуск обновления ключей

Конечные точки поддерживают разные секреты чтения и записи для защиты пакетов. Конечная точка запускает обновление ключей, обновляя свой секрет записи для защиты пакетов и используя его с новыми пакетами. Новый секрет записи создаётся из имеющегося в соответствии с параграфом 7.2 в [TLS13]. При этом используется функция KDF, обеспечиваемая TLS, с меткой quic ku. Соответствующий ключ и IV создаются из этого секрета, как указано в параграфе 5.1. Ключ защиты заголовков не обновляется.

Например, для обновления ключей записи с TLS 1.3 применяется HKDF-Expand-Label

   secret_<n+1> = HKDF-Expand-Label(secret_<n>, "quic ku", "", Hash.length)

Конечная точка меняет бит Key Phase и использует обновленный ключ и IV для защиты последующих пакетов.

Конечной точке недопустимо запускать обновление ключа до подтверждения согласования (параграф 4.1.2). Конечной точке недопустимо инициировать последующие обновления ключа, пока она не получила подтверждения пакетов, защищённых с ключом из текущей фазы. Это гарантирует доступность ключей обоим партнёрам, прежде чем будет начато обновление. Это можно реализовать путём отслеживания наименьшего номера пакета, переданного с каждой фазой ключа, и наибольшего номера подтверждения в пространстве 1-RTT — как только номер подтверждения станет не меньше наименьшего номера переданного пакета, можно запускать обновления ключа.

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

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

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

6.2. Отклик на обновление ключей

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

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

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

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

6.3. Синхронизация создания ключа приёма

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

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

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

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

6.4. Передача с обновлёнными ключами

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

6.5. Приём с другими ключами

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

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

В качестве варианта конечные точки могут сохранять лишь два набора ключей защиты пакетов, переходя с прежнего к следующему по истечении достаточно большого времени, позволяющего учесть нарушение порядка в сети. В этом случае бит Key Phase позволяет однозначно выбрать ключи. Конечная точка может внести интервал приблизительно равный интервалу зондирования (Probe Timeout или PTO, см [QUIC-RECOVERY]) после того, как следующий набор ключей становится текущим, до создания следующего набора ключей защиты пакетов. Эти обновлённые ключи могут заменить прежние ключи в любой момент. С учётом того, что PTO является субъективной мерой (т. е. у партнёра может быть иное представление о RTT), предполагается, что этого времени будет достаточно, чтобы все разупорядоченные пакеты были сочтены партнёром потерянными, даже если они были подтверждены, и интервал будет достаточно коротким, чтобы партнёр мог запустить дальнейшее обновление ключей.

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

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

6.6. Ограничения применимости AEAD

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

Пределы использования, заданные в TLS 1.3, применяются для защиты от атак на конфиденциальность при использовании защиты AEAD. Защита целостности при аутентифицированном шифровании также зависит от ограничения числа попыток подделки пакетов. TLS обеспечивает это путём закрытия соединений, если какая-либо запись не прошла проверку подлинности. QUIC игнорирует не прошедшие аутентификацию пакеты, разрешая множество попыток подделки.

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

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

Для AEAD_AES_128_GCM и AEAD_AES_256_GCM предел в части конфиденциальности составляет 223 зашифрованных пакетов (см. Приложение B.1), для AEAD_CHACHA20_POLY1305 предел превышает возможное число пакетов (262) и им можно пренебречь, а для AEAD_AES_128_CCM предел составляет 221,5 зашифрованных пакетов (см. Приложение B.2). Применение ограничений снижает вероятность того, что атакующий сможет определить применяемый алгоритм AEAD от случайного изменения (см. [AEBounds], [ROBUST], [GCM-MU]).

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

Для AEAD_AES_128_GCM и AEAD_AES_256_GCM предел в части целостности составляет 252 недействительных пакетов (см. Приложение B.1), для AEAD_CHACHA20_POLY1305 — 236 недействительных пакетов (см. [AEBounds]), а для AEAD_AES_128_CCM — 221,5 недействительных пакетов (см. Приложение B.2). Применение этих ограничений снижает вероятность успешной подделки пакетов злоумышленником (см. [AEBounds], [ROBUST], [GCM-MU]).

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

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

6.7. Код ошибки при обновлении ключей

Код ошибки KEY_UPDATE_ERROR (0x0e) служит для сигнализации ошибок, связанных с обновлением ключей.

7. Защита пакетов Initial

Пакеты Initial не могут быть защищены с использованием секретного ключа, поэтому атакующий способен изменить их. QUIC обеспечивает защиту от злоумышленников, не способных читать пакеты, но не пытается предоставить дополнительную защиту от атак с возможностью наблюдения и внедрения пакетов. Некоторые из форм вмешательства, такие как изменение самих сообщений TLS, могут быть замечены, но другие, например, изменение ACK, остаются не обнаруженными. Например, атакующий может внедрить пакет с кадром ACK чтобы создать впечатление о том, что кадр не был получен или представить ложное состояние соединения (например, путём изменения ACK Delay). Отметим, что такие пакеты могут вызывать отбрасывание легитимных пакетов как дубликатов. Реализациям следует проявлять осторожность, полагаясь на данные из пакетов Initial, которые не аутентифицированы иным способом.

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

8. Связанные с QUIC настройки TLS Handshake

Некоторые аспекты согласования TLS меняются при использовании с QUIC. Кроме криптографических параметров в процессе согласования передаются и аутентифицируются параметры транспорта QUIC.

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

QUIC требует, чтобы криптографическое согласование обеспечивало аутентифицированное согласование протокола. TLS использует согласование протокола прикладного уровня [ALPN] для выбора протокола приложения. Если не задан иной механизм согласования такого протокола, конечные точки должны применять ALPN. При использовании ALPN конечные точки должны немедленно закрывать соединение (см. параграф 10.2 в [QUIC-TRANSPORT]) с сигналом TLS no_application_protocol (код ошибки QUIC 0x0178, см. параграф 4.8), если прикладной протокол не согласован. Хотя [ALPN] лишь указывает, что серверы используют этот сигнал, клиенты QUIC должны по коду 0x0178 прерывать соединение в случае отказа при согласовании ALPN.

Прикладной протокол может ограничивать версии QUIC, с которыми он работает. Серверы должны выбирать протокол приложений, совместимый с выбранной клиентом версией QUIC. Сервер должен считать неспособность выбрать совместимый протокол ошибкой соединения типа 0x0178 (no_application_protocol). Клиент должен считать выбор серверов несовместимого прикладного протокола ошибкой соединения типа 0x0178.

8.2. Расширение для транспортных параметров QUIC

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

      enum {
         quic_transport_parameters(0x39), (65535)
      } ExtensionType;

Поле extension_data field в расширении quic_transport_parameters содержит значение, определённое используемой версией QUIC.

Расширение quic_transport_parameters передаётся в сообщениях ClientHello и EncryptedExtensions в процессе согласования. Конечные точки должны передавать расширение quic_transport_parameters, а конечные точки, получившие сообщение ClientHello или EncryptedExtensions без quic_transport_parameters, должны закрывать соединение с ошибкой типа 0x016d (эквивалент критического сигнала TLS missing_extension, см. параграф 4.8).

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

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

Согласование расширения quic_transport_parameters вызывает исключение EndOfEarlyData (см. параграф 8.3).

8.3. Удаление сообщения EndOfEarlyData

Сообщение TLS EndOfEarlyData не используется с QUIC и протокол не полагается на это сообщение для маркировки завершения данных 0-RTT или сигнализации о смене ключей Handshake. Клиентам недопустимо передавать сообщение EndOfEarlyData, а сервер должен считать получение кадра CRYPTO в пакете 0-RTT ошибкой соединения типа PROTOCOL_VIOLATION.

В результате сообщение EndOfEarlyData не присутствует в согласовании TLS.

8.4. Запрет режима TLS Middlebox Compatibility

В Приложении D.4 [TLS13] описано изменение согласования TLS 1.3 для обхода ошибок некоторых промежуточных устройств. Режим совместимости с промежуточными устройствами в TLS 1.3 включает установку для поля legacy_session_id 32-байтового значения в ClientHello и ServerHello, затем передачу изменённой записи change_cipher_spec. Оба поля и запись не несут семантического содержимого и игнорируются.

Этот режим не используется в QUIC поскольку применим лишь к промежуточным устройствам, нарушающим работу TLS по протоколу TCP. QUIC также не предоставляет средств доставки записи change_cipher_spec. Клиентам недопустимо запрашивать использование режима совместимости TLS 1.3, а серверам следует считать получение TLS ClientHello с непустым полем legacy_session_id ошибкой соединения типа PROTOCOL_VIOLATION.

9. Вопросы безопасности

Все вопросы безопасности, связанные с TLS применимы и к использованию TLS в QUIC. Чтение [TLS13] и приложений к нему обеспечивает наилучший способ разобраться с вопросами безопасности QUIC. В этом разделе приведена сводка некоторых важных аспектов безопасности, относящихся к интеграции TLS, хотя многие детали, связанные с безопасностью рассмотрены в оставшейся части документа.

9.1. Связывание сессий

Использование сеансовых квитанций TLS позволяет серверами и возможно другим объектам сопоставлять соединения одного клиента (см. параграф 4.5).

9.2. Replay-атаки с 0-RTT

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

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

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

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

В конечном итоге ответственность за контроль рисков replay-атак с 0-RTT ложится на протокол приложения. Использующий QUIC прикладной протокол должен описывать применение 0-RTT и меры, реализуемые для защиты от replay-атак. Анализ связанных с этим рисков должен учитывать все свойства протокола QUIC, связанные с семантикой приложения.

Полное отключение 0-RTT является наиболее эффективным способом защиты от replay-атак.

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

9.3. Ослабление атак с отражением пакетов

Небольшое сообщение ClientHello, вызывающее большой блок сообщений согласования от сервера, можно использовать для атак с отражением, усиливающих трафик от атакующего. QUIC включает три средства защиты от таких атак. Во-первых, клиент должен дополнять пакет с ClientHello до минимального размера. Во-вторых, при отклике по неизвестным адресам отправителей серверу запрещено передавать более троекратного объёма полученных данных (см. параграф 8.1 в [QUIC-TRANSPORT]). В-третьих, поскольку подтверждения пакетов Handshake аутентифицируются, при атаке вслепую их нельзя подделать. Эти меры ограничивают степень усиления трафика.

9.4. Анализ защиты заголовков

В [NAN] анализируются алгоритмы аутентифицированного шифрования, обеспечивающие конфиденциальность nonce, называемую преобразованием HN (Hide Nonce). Базовая конструкция защиты заголовков в этом документе основана на одном из таких алгоритмов (HN1). Защита заголовка применяется после защиты AEAD для пакета путём выборки набора байтов (sample) из вывода AEAD и шифрования поля заголовка с применением псевдослучайной функции PRF

   protected_field = field XOR PRF(hp_key, sample)

Варианты защиты заголовка в этом документе используют псевдослучайную перестановку (pseudorandom permutation или PRP) вместо базовой PRF. Однако, поскольку все PRP являются также PRF [IMC], эти варианты не отклоняются от конструкции HN1.

Поскольку hp_key отличается от ключа защиты пакета, защита заголовка обеспечивает уровень AE2, как определено в [NAN], и поэтому гарантирует конфиденциальность field — защищённого заголовка пакета. Будущие варианты защиты заголовка на основе этой конструкции должны использовать PRF для обеспечения эквивалентных гарантий защиты.

Использование одного ключа и выборки шифрованных данных более одного раза ставит под угрозу защиту заголовка. Защита двух разных заголовков с одним ключом и выборкой шифротекста раскрывает XOR защищённых полей. В предположении AEAD в качестве PRF и выборки L битов вероятность совпадения двух выборок шифротекста составит 2(-L/2) (birthday bound). Для алгоритмов, описанных в этом документе вероятность составляет 2-64.

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

9.5. Побочные каналы синхронизации защиты заголовка

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

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

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

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

9.6. Разнообразие ключей

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

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

Для начальных секретов применяется ключ, зависящий от согласованной версии QUIC. Новым версиям QUIC следует задавать иную затравку (salt) для расчёта начальных секретов.

9.7. Случайные значения

QUIC зависит от способности конечных точек создавать безопасные случайные значения напрямую для таких параметров протокола как идентификаторы соединений и опосредованно через TLS. Рекомендации по созданию случайных чисел приведены в [RFC4086].

10. Взаимодействие с IANA

Агентство IANA зарегистрировало код 57 (0x39) для расширения quic_transport_parameters (см. параграф 8.2) в реестре TLS ExtensionType Values [TLS-REGISTRIES]. В столбце Recommended для этого расширения указано значение Yes, а столбец TLS 1.3 включает CH (ClientHello) и EE (EncryptedExtensions).

Таблица 2. Записи реестра TLS ExtensionType Values.

Значение

Имя расширения

TLS 1.3

Рекомендация

Документ

57

quic_transport_parameters

CH, EE

YY

Данный документ

11. Литература

11.1. Нормативные документы

[AEAD] McGrew, D., «An Interface and Algorithms for Authenticated Encryption», RFC 5116, DOI 10.17487/RFC5116, January 2008, <https://www.rfc-editor.org/info/rfc5116>.

[AES] «Advanced encryption standard (AES)», National Institute of Standards and Technology report, DOI 10.6028/nist.fips.197, November 2001, <https://doi.org/10.6028/nist.fips.197>.

[ALPN] Friedl, S., Popov, A., Langley, A., and E. Stephan, «Transport Layer Security (TLS) Application-Layer Protocol Negotiation Extension», RFC 7301, DOI 10.17487/RFC7301, July 2014, <https://www.rfc-editor.org/info/rfc7301>.

[CHACHA] Nir, Y. and A. Langley, «ChaCha20 and Poly1305 for IETF Protocols», RFC 8439, DOI 10.17487/RFC8439, June 2018, <https://www.rfc-editor.org/info/rfc8439>.

[HKDF] Krawczyk, H. and P. Eronen, «HMAC-based Extract-and-Expand Key Derivation Function (HKDF)», RFC 5869, DOI 10.17487/RFC5869, May 2010, <https://www.rfc-editor.org/info/rfc5869>.

[QUIC-RECOVERY] Iyengar, J., Ed. and I. Swett, Ed., «QUIC Loss Detection and Congestion Control», RFC 9002, DOI 10.17487/RFC9002, May 2021, <https://www.rfc-editor.org/info/rfc9002>.

[QUIC-TRANSPORT] Iyengar, J., Ed. and M. Thomson, Ed., «QUIC: A UDP-Based Multiplexed and Secure Transport», RFC 9000, DOI 10.17487/RFC9000, May 2021, <https://www.rfc-editor.org/info/rfc9000>.

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>.

[RFC4086] Eastlake 3rd, D., Schiller, J., and S. Crocker, «Randomness Requirements for Security», BCP 106, RFC 4086, DOI 10.17487/RFC4086, June 2005, <https://www.rfc-editor.org/info/rfc4086>.

[RFC8174] Leiba, B., «Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words», BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[SHA] Dang, Q., «Secure Hash Standard», National Institute of Standards and Technology report, DOI 10.6028/nist.fips.180-4, July 2015, <https://doi.org/10.6028/nist.fips.180-4>.

[TLS-REGISTRIES] Salowey, J. and S. Turner, «IANA Registry Updates for TLS and DTLS», RFC 8447, DOI 10.17487/RFC8447, August 2018, <https://www.rfc-editor.org/info/rfc8447>.

[TLS13] Rescorla, E., «The Transport Layer Security (TLS) Protocol Version 1.3», RFC 8446, DOI 10.17487/RFC8446, August 2018, <https://www.rfc-editor.org/info/rfc8446>.

11.2. Дополнительная литература

[AEBounds] Luykx, A. and K. Paterson, «Limits on Authenticated Encryption Use in TLS», 28 August 2017, <https://www.isg.rhul.ac.uk/~kp/TLS-AEbounds.pdf>.

[ASCII] Cerf, V., «ASCII format for network interchange», STD 80, RFC 20, DOI 10.17487/RFC0020, October 1969, <https://www.rfc-editor.org/info/rfc20>.

[CCM-ANALYSIS] Jonsson, J., «On the Security of CTR + CBC-MAC», Selected Areas in Cryptography, SAC 2002, Lecture Notes in Computer Science, vol 2595, pp. 76-93, DOI 10.1007/3-540-36492-7_7, 2003, <https://doi.org/10.1007/3-540-36492-7_7>.

[COMPRESS] Ghedini, A. and V. Vasiliev, «TLS Certificate Compression», RFC 8879, DOI 10.17487/RFC8879, December 2020, <https://www.rfc-editor.org/info/rfc8879>.

[GCM-MU] Hoang, V., Tessaro, S., and A. Thiruvengadam, «The Multi-user Security of GCM, Revisited: Tight Bounds for Nonce Randomization», CCS ’18: Proceedings of the 2018 ACM SIGSAC Conference on Computer and Communications Security, pp. 1429-1440, DOI 10.1145/3243734.3243816, 2018, <https://doi.org/10.1145/3243734.3243816>.

[HTTP-REPLAY] Thomson, M., Nottingham, M., and W. Tarreau, «Using Early Data in HTTP», RFC 8470, DOI 10.17487/RFC8470, September 2018, <https://www.rfc-editor.org/info/rfc8470>.

[HTTP2-TLS13] Benjamin, D., «Using TLS 1.3 with HTTP/2», RFC 8740, DOI 10.17487/RFC8740, February 2020, <https://www.rfc-editor.org/info/rfc8740>.

[IMC] Katz, J. and Y. Lindell, «Introduction to Modern Cryptography, Second Edition», ISBN 978-1466570269, 6 November 2014.

[NAN] Bellare, M., Ng, R., and B. Tackmann, «Nonces Are Noticed: AEAD Revisited», Advances in Cryptology — CRYPTO 2019, Lecture Notes in Computer Science, vol 11692, pp. 235-265, DOI 10.1007/978-3-030-26948-7_9, 2019, <https://doi.org/10.1007/978-3-030-26948-7_9>.

[QUIC-HTTP] Bishop, M., Ed., «Hypertext Transfer Protocol Version 3 (HTTP/3)», Work in Progress, Internet-Draft, draft-ietf-quic-http-34, 2 February 2021, <https://tools.ietf.org/html/draft-ietf-quic-http-34>.

[RFC2818] Rescorla, E., «HTTP Over TLS», RFC 2818, DOI 10.17487/RFC2818, May 2000, <https://www.rfc-editor.org/info/rfc2818>.

[RFC5280] Cooper, D., Santesson, S., Farrell, S., Boeyen, S., Housley, R., and W. Polk, «Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile», RFC 5280, DOI 10.17487/RFC5280, May 2008, <https://www.rfc-editor.org/info/rfc5280>.

[ROBUST] Fischlin, M., Günther, F., and C. Janson, «Robust Channels: Handling Unreliable Networks in the Record Layers of QUIC and DTLS 1.3», 16 May 2020, <https://eprint.iacr.org/2020/718>.

Приложение A. Пример защиты пакета

В этом приложении даны примеры защиты пакетов для поэтапной проверки реализаций. Определены образцы пакетов Initial для клиента и сервера, а также пакета Retry. В пакетах используется выбранное клиентом значение Destination Connection ID of 0x8394c8f03e515708. Включены также некоторые промежуточные значения. Все числа представлены в шестнадцатеричном формате.

A.1. Ключи

Ниже приведены метка, создаваемые в процессе выполнения функции HKDF-Expand-Label (т. е. HkdfLabel.label) и часть значения, переданного функции HKDF-Expand.

   client in:  00200f746c73313320636c69656e7420696e00
   server in:  00200f746c7331332073657276657220696e00
   quic key:   00100e746c7331332071756963206b657900
   quic iv:    000c0d746c733133207175696320697600
   quic hp:    00100d746c733133207175696320687000

Общий исходный секрет

   initial_secret = HKDF-Extract(initial_salt, cid)
       = 7db5df06e7a69e432496adedb0085192
         3595221596ae2ae9fb8115c1e9ed0a44

Секреты для защиты пакетов клиента

   client_initial_secret
       = HKDF-Expand-Label(initial_secret, "client in", "", 32)
       = c00cf151ca5be075ed0ebfb5c80323c4
         2d6b7db67881289af4008f1f6c357aea

   key = HKDF-Expand-Label(client_initial_secret, "quic key", "", 16)
       = 1f369613dd76d5467730efcbe3b1a22d

   iv  = HKDF-Expand-Label(client_initial_secret, "quic iv", "", 12)
       = fa044b2f42a3fd3b46fb255c

   hp  = HKDF-Expand-Label(client_initial_secret, "quic hp", "", 16)
       = 9f50449e04a0e810283a1e9933adedd2

Секреты для защиты пакетов сервера

   server_initial_secret
       = HKDF-Expand-Label(initial_secret, "server in", "", 32)
       = 3c199828fd139efd216c155ad844cc81
         fb82fa8d7446fa7d78be803acdda951b

   key = HKDF-Expand-Label(server_initial_secret, "quic key", "", 16)
       = cf3a5331653c364c88f0f379b6067e37

   iv  = HKDF-Expand-Label(server_initial_secret, "quic iv", "", 12)
       = 0ac1493ca1905853b0bba03e

   hp  = HKDF-Expand-Label(server_initial_secret, "quic hp", "", 16)
       = c206b8d9b9f0f37644430b490eeaa314

A.2. Initial от клиента

В пакете Initial от клиента незащищённая часть данных (payload) содержит показанный ниже кадр CRYPTO и кадры PADDING для увеличения размера содержимого до 1162 байтов.

   060040f1010000ed0303ebf8fa56f129 39b9584a3896472ec40bb863cfd3e868
   04fe3a47f06a2b69484c000004130113 02010000c000000010000e00000b6578
   616d706c652e636f6dff01000100000a 00080006001d00170018001000070005
   04616c706e0005000501000000000033 00260024001d00209370b2c9caa47fba
   baf4559fedba753de171fa71f50f1ce1 5d43e994ec74d748002b000302030400
   0d0010000e0403050306030203080408 050806002d00020101001c0002400100
   3900320408ffffffffffffffff050480 00ffff07048000ffff08011001048000
   75300901100f088394c8f03e51570806 048000ffff

Незащищённый заголовок указывает размер 1182 байта — 4-байтовый номер пакета, 1162 байта кадров и 16-байтовый тег аутентификации. Заголовок включает идентификатор соединения и номера пакета (2)

   c300000001088394c8f03e5157080000449e00000002

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

   sample = d1b1c98dd7689fb8ec11d242b123dc9b

   mask = AES-ECB(hp, sample)[0..4]
        = 437b9aec36

   header[0] ^= mask[0] & 0x0f
        = c0
   header[18..21] ^= mask[1..4]
        = 7b9aec34
   header = c000000001088394c8f03e5157080000449e7b9aec34

Полученный в результате защищённый пакет имеет вид

   c000000001088394c8f03e5157080000 449e7b9aec34d1b1c98dd7689fb8ec11
   d242b123dc9bd8bab936b47d92ec356c 0bab7df5976d27cd449f63300099f399
   1c260ec4c60d17b31f8429157bb35a12 82a643a8d2262cad67500cadb8e7378c
   8eb7539ec4d4905fed1bee1fc8aafba1 7c750e2c7ace01e6005f80fcb7df6212
   30c83711b39343fa028cea7f7fb5ff89 eac2308249a02252155e2347b63d58c5
   457afd84d05dfffdb20392844ae81215 4682e9cf012f9021a6f0be17ddd0c208
   4dce25ff9b06cde535d0f920a2db1bf3 62c23e596d11a4f5a6cf3948838a3aec
   4e15daf8500a6ef69ec4e3feb6b1d98e 610ac8b7ec3faf6ad760b7bad1db4ba3
   485e8a94dc250ae3fdb41ed15fb6a8e5 eba0fc3dd60bc8e30c5c4287e53805db
   059ae0648db2f64264ed5e39be2e20d8 2df566da8dd5998ccabdae053060ae6c
   7b4378e846d29f37ed7b4ea9ec5d82e7 961b7f25a9323851f681d582363aa5f8
   9937f5a67258bf63ad6f1a0b1d96dbd4 faddfcefc5266ba6611722395c906556
   be52afe3f565636ad1b17d508b73d874 3eeb524be22b3dcbc2c7468d54119c74
   68449a13d8e3b95811a198f3491de3e7 fe942b330407abf82a4ed7c1b311663a
   c69890f4157015853d91e923037c227a 33cdd5ec281ca3f79c44546b9d90ca00
   f064c99e3dd97911d39fe9c5d0b23a22 9a234cb36186c4819e8b9c5927726632
   291d6a418211cc2962e20fe47feb3edf 330f2c603a9d48c0fcb5699dbfe58964
   25c5bac4aee82e57a85aaf4e2513e4f0 5796b07ba2ee47d80506f8d2c25e50fd
   14de71e6c418559302f939b0e1abd576 f279c4b2e0feb85c1f28ff18f58891ff
   ef132eef2fa09346aee33c28eb130ff2 8f5b766953334113211996d20011a198
   e3fc433f9f2541010ae17c1bf202580f 6047472fb36857fe843b19f5984009dd
   c324044e847a4f4a0ab34f719595de37 252d6235365e9b84392b061085349d73
   203a4a13e96f5432ec0fd4a1ee65accd d5e3904df54c1da510b0ff20dcc0c77f
   cb2c0e0eb605cb0504db87632cf3d8b4 dae6e705769d1de354270123cb11450e
   fc60ac47683d7b8d0f811365565fd98c 4c8eb936bcab8d069fc33bd801b03ade
   a2e1fbc5aa463d08ca19896d2bf59a07 1b851e6c239052172f296bfb5e724047
   90a2181014f3b94a4e97d117b4381303 68cc39dbb2d198065ae3986547926cd2
   162f40a29f0c3c8745c0f50fba3852e5 66d44575c29d39a03f0cda721984b6f4
   40591f355e12d439ff150aab7613499d bd49adabc8676eef023b15b65bfc5ca0
   6948109f23f350db82123535eb8a7433 bdabcb909271a6ecbcb58b936a88cd4e
   8f2e6ff5800175f113253d8fa9ca8885 c2f552e657dc603f252e1a8e308f76f0
   be79e2fb8f5d5fbbe2e30ecadd220723 c8c0aea8078cdfcb3868263ff8f09400
   54da48781893a7e49ad5aff4af300cd8 04a6b6279ab3ff3afb64491c85194aab
   760d58a606654f9f4400e8b38591356f bf6425aca26dc85244259ff2b19c41b9
   f96f3ca9ec1dde434da7d2d392b905dd f3d1f9af93d1af5950bd493f5aa731b4
   056df31bd267b6b90a079831aaf579be 0a39013137aac6d404f518cfd4684064
   7e78bfe706ca4cf5e9c5453e9f7cfd2b 8b4c8d169a44e55c88d4a9a7f9474241
   e221af44860018ab0856972e194cd934

A.3. Initial от сервера

Сервер передаёт в ответ показанный ниже пакет, включающий кадры ACK и CRYPTO без заполнения PADDING.

   02000000000600405a020000560303ee fce7f7b37ba1d1632e96677825ddf739
   88cfc79825df566dc5430b9a045a1200 130100002e00330024001d00209d3c94
   0d89690b84d08a60993c144eca684d10 81287c834d5311bcf32bb9da1a002b00
   020304

Заголовок от сервера включает новый идентификатор соединения и 2-байтовый номера пакета (1)

   c1000000010008f067a5502a4262b50040750001

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

   sample = 2cd0991cd25b0aac406a5816b6394100
   mask   = 2ec0d8356a
   header = cf000000010008f067a5502a4262b5004075c0d9

Защищённый пакет в результате имеет вид

   cf000000010008f067a5502a4262b500 4075c0d95a482cd0991cd25b0aac406a
   5816b6394100f37a1c69797554780bb3 8cc5a99f5ede4cf73c3ec2493a1839b3
   dbcba3f6ea46c5b7684df3548e7ddeb9 c3bf9c73cc3f3bded74b562bfb19fb84
   022f8ef4cdd93795d77d06edbb7aaf2f 58891850abbdca3d20398c276456cbc4
   2158407dd074ee

A.4. Пакет Retry

Ниже показан пакет Retry, который может быть передан в ответ на пакет Initial из Приложения A.2. Защита целостности включает выбранный клиентом идентификатор соединения 0x8394c8f03e515708, но это значение не включается в окончательный пакет Retry, показанный ниже.

   ff000000010008f067a5502a4262b574 6f6b656e04a265ba2eff4d829058fb3f
   0f2496ba

A.5. Пакет с коротким заголовком ChaCha20-Poly1305

В этом примере показаны некоторые шаги, требуемые для защиты пакета с коротким заголовком. Применяется шифрование AEAD_CHACHA20_POLY1305. В примере TLS создаёт для приложения секрет записи, из которого сервер с помощью HKDF-Expand-Label создаёт 4 значения — ключ, IV, ключ защиты заголовка и секрет, применяемый после обновления ключей (это значение далее в примере не используется).

   secret
       = 9ac312a7f877468ebe69422748ad00a1
         5443f18203a07d6060f688f30f21632b

   key = HKDF-Expand-Label(secret, "quic key", "", 32)
       = c6d98ff3441c3fe1b2182094f69caa2e
         d4b716b65488960a7a984979fb23e1c8

   iv  = HKDF-Expand-Label(secret, "quic iv", "", 12)
       = e0459b3474bdd0e44a41c144

   hp  = HKDF-Expand-Label(secret, "quic hp", "", 32)
       = 25a282b9e82f06f21f488917a4fc8f1b
         73573685608597d0efcb076b0ab7a7a4

   ku  = HKDF-Expand-Label(secret, "quic ku", "", 32)
       = 1223504755036d556342ee9361d25342
         1a826c9ecdf3c7148684b36b714881f9

Ниже показаны шаги, требуемые для защиты минимального пакета с пустым полем Destination Connection ID. Этот пакет содержит один кадр PING (содержимое 0x01) и имеет номер 654360564. В примере использование номера пакета размером 3 (кодируется в 49140) позволяет избежать дополнения содержимого пакета, если же использовать более короткое представление номера, потребуются кадры PADDING.

   pn                 = 654360564 (десятичное)
   nonce              = e0459b3474bdd0e46d417eb0
   unprotected header = 4200bff4
   payload plaintext  = 01
   payload ciphertext = 655e5cd55c41f69080575d7999c25a5bfb

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

   sample = 5e5cd55c41f69080575d7999c25a5bfb
   mask   = aefefe7d03
   header = 4cfe4189

Защищённый пакет имеет минимальный возможный размер 21 байт.

   packet = 4cfe4189655e5cd55c41f69080575d7999c25a5bfb

Приложение B. Анализ алгоритмов AEAD

В этом приложении описан анализ, используемый при выводе ограничений AEAD для алгоритмов AEAD_AES_128_GCM, AEAD_AES_128_CCM, AEAD_AES_256_GCM. В описаниях используются символы умножения (*), деления (/), возведения в степень (^) и скобки для указания порядка действий. Описания символов приведены ниже.

t

Размер тега аутентификации с битах. Для рассматриваемых шифров это 128.

n

Размер блока в битах. Для рассматриваемых шифров это 128.

k

Размер ключа в битах. Это 128 для AEAD_AES_128_GCM и AEAD_AES_128_CCM, 256 для AEAD_AES_256_GCM.

l

Число блоков в каждом пакете (см. ниже).

q

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

v

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

o

Число автономных (offline) запросов шифрования, предпринимаемых злоумышленником.

Последующий анализ основан на подсчете числа операций с блоками при создании каждого сообщения. Этот анализ выполняется для пакетов размером до 211 (l = 27) и 216 (l = 212) байтов. Предполагается, что размер 211 будет пределом для базовых вариантов развёртывания, а 216 задаёт максимальный размер пакета QUIC. Лишь точки, строго ограничивающие размер пакетов, могут использовать более высокие пределы в части целостности и конфиденциальности, выведенные для меньших размеров.

Для AEAD_AES_128_GCM и AEAD_AES_256_GCM размером сообщения (l) считается размер связанных данных в блоках с добавлением размера нешифрованных данных (plaintext) в блоках.

Для AEAD_AES_128_CCM общее число блочных операций шифрования является суммой размера связанных данных в блоках, размера шифротекста в блоках, размера открытых данных в блоках и 1. В этом анализе принимается упрощения до удвоенного размера пакета в блоках (т. е. 2l = 28 для пакетов до 211 байтов и 2l = 213 в остальных случаях). Это упрощение основано на пакетах, содержащих все связанные данные и шифротекст, что ведёт к завышению оценки числа операций для пакета на 1-3 блока.

B.1. Анализ применимости AEAD_AES_128_GCM и AEAD_AES_256_GCM

[GCM-MU] определяет конкретные границы применимости AEAD_AES_128_GCM и AEAD_AES_256_GCM при использовании в TLS 1.3 и QUIC. В этом параграфе приведён анализ в некоторыми упрощениями.

  • Число шифрованных блоков, используемых атакующим в попытках подделки, ограничено произведением v * l (число попыток подделки, умноженное на размер каждого пакета в блоках).

  • Объем работы, автономно выполняемой злоумышленником, не преобладает над другими факторами.

Ограничения в [GCM-MU] являются более жёсткими и полными по сравнению с [AEBounds], где разрешены пределы выше описанных в [TLS13].

B.1.1. Ограничение в части конфиденциальности

В части конфиденциальности теорема 4.3 в [GCM-MU] показывает, что для одного пользователя, не повторяющего значения nonce, доминирующим членом, определяющим сравнительные преимущества реального и случайного алгоритма AEAD, получаемые злоумышленником, составляют

   2 * (q * l)^2 / 2^n

Для целевого преимущества 2-57 это даёт

   q <= 2^35 / l

Таким образом, конечные точки, не передающие пакетов размером более 211 байтов, не могут защитить более 228 пакетов в одном соединении, не предоставляя атакующему преимущества выше 2-57. Для конечных точек, поддерживающих размер пакетов до 216 байтов, предел составляет 223.

B.1.2. Ограничение в части целостности

В части целостности теорема 4.3 в [GCM-MU] показывает, что атакующий получит преимущество в подделке пакетов не позднее указанного ниже числа пакетов.

   (1 / 2^(8 * n)) + ((2 * v) / 2^(2 * n))
           + ((2 * o * v) / 2^(k + n)) + (n * (v + (v * l)) / 2^k)

Цель состоит в ограничении этого преимущества значением 2-57. Для AEAD_AES_128_GCM четвёртый член выражения доминирует над остальными, поэтому их можно исключить без существенного влияния на результат. Это даёт приближение

   v <= 2^64 / l

Конечные точки, не пытающиеся снимать защиту с пакетов размером более 211 байтов, могут снимать защиту не более чем с 257 пакетов. Конечные точки, не ограничивающие размер обрабатываемых пакетов, могут снять защиту не более чем с 252 пакетов.

Для AEAD_AES_256_GCM в выражении доминирует тот же член, но большее значение k даёт приближение

   v <= 2^192 / l

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

B.2. Анализ применимости AEAD_AES_128_CCM

TLS [TLS13] и [AEBounds] не задают ограничений на использование AEAD_AES_128_CCM. Однако любой алгоритм AEAD, используемый с QUIC, требует ограничений, обеспечивающих сохранение конфиденциальности и целостности. В этом разделе приведён анализ этих ограничений, основанный на [CCM-ANALYSIS]. Результаты этого анализа применяются для вывода пределов применимости в соответствии с ограничениями, заданными в [TLS13].

В части конфиденциальности теорема 2 из [CCM-ANALYSIS] указывает, что атакующий получает заметное преимущество над идеальной псевдослучайной перестановкой (pseudorandom permutation или PRP) после не более чем (2l * q)2/2n пакетов.

В части целостности теорема 1 из [CCM-ANALYSIS] указывает, что атакующий получает строго большее преимуществу при том же числе пакетов. Поскольку цели получения преимуществ в части конфиденциальности и целостности совпадают, достаточно рассмотреть лишь теорему 1. Эта теорема показывает, что атакующий получает преимущество перед идеальной PRP при числе пакетов не более

   v / 2^t + (2l * (v + q))^2 / 2^n

Поскольку t и n имеют значение 128, первый член пренебрежимо мал по сравнению со вторым и его можно исключить без существенного влияния на результат. Это порождает отношение, объединяющее попытки шифрования и дешифровки с одинаковым пределом, который определяется лишь теоремой для конфиденциальности. Для целевого преимущества 2-57 это даёт

   v + q <= 2^34,5 / l

Установив q = v, можно получить значения для целостности и конфиденциальности. Конечные точки, ограничивающие размер пакетов значением 211 байтов, будут иметь в части целостности и конфиденциальность ограничение 226,5 пакетов. Конечные точки, не ограничивающие размер пакетов, будут иметь предел 221,5 пакетов.

Участники работы

Рабочая группа IETF QUIC получила поддержку от многих людей. Ниже перечислены те, кто внёс существенных вклад в работу.

Adam Langley

Alessandro Ghedini

Christian Huitema

Christopher Wood

David Schinazi

Dragana Damjanovic

Eric Rescorla

Felix Günther

Ian Swett

Jana Iyengar

奥 一穂 (Kazuho Oku)

Marten Seemann

Martin Duke

Mike Bishop

Mikkel Fahnøe Jørgensen

Nick Banks

Nick Harper

Roberto Peon

Rui Paulo

Ryan Hamilton

Victor Vasiliev

Адреса авторов

Martin Thomson (editor)

Mozilla

Email: mt@lowentropy.net

Sean Turner (editor)

sn3rd

Email: sean@sn3rd.com


Перевод на русский язык

Николай Малых

nmalykh@protokols.ru

1Internet Engineering Task Force.

2Internet Engineering Steering Group.

3Server Name Identification — идентификация имени сервера.

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

Рубрика: RFC | Оставить комментарий

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

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 документа IETF Trust Legal Provisions, без каких-либо гарантий (как указано в Simplified BSD License).

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.

13. Пакетизация и надёжность доставки

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

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

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

13.1. Обработка пакета

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

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

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

13.2. Генерация подтверждений

Конечные точки подтверждают все пакеты, которые они получили и обработали. Однако лишь пакеты с запросом подтверждения (ack-eliciting) вызывают отправку кадра ACK в интервале максимально разрешённой задержки подтверждения. Остальные пакеты подтверждаются лишь при отправке кадра ACK по иным причинам.

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

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

13.2.1. Передача кадров ACK

Каждый пакет следует подтверждать по меньшей мере один раз, а пакеты с запросом подтверждения должны подтверждаться не менее 1 раза в интервале максимальной задержки, указанного конечной точкой в транспортном параметре max_ack_delay (см. раздел 18.2). Параметр max_ack_delay задаёт явное требование — конечная точка обещает никогда не задерживать преднамеренно подтверждения пакетов ack-eliciting более указанного времени. Если задержка происходит, любое превышение учитывается при оценке RTT и может приводить к ложным или задержанным повторам передачи партнёром. Отправитель использует значение max_ack_delay, заданное получателем, при определении тайм-аутов для повтора по времени, как описано в параграфе 6.2 [QUIC-RECOVERY].

Конечная точка должна подтверждать все пакеты Initial и Handshake с запросом подтверждения незамедлительно, а все пакеты 0-RTT и 1-RTT с запросом подтверждения в анонсированном интервале max_ack_delay, с одним исключением. До подтверждения согласования (handshake) у конечной точки может не быть ключей для расшифровки принимаемых пакетов Handshake, 0-RTT, 1-RTT, поэтому она может буферизовать их и подтверждать после обретения ключей.

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

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

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

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

Для оказания помощи в обнаружении потерь отправителем конечной точке следует создавать и отправлять кадр ACK без задержки при получении пакета с запросом подтверждения, а также:

  • при получении пакета с номером меньше чем в другом полученном пакете с запросом подтверждения;

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

Точно так же пакеты с кодом ECN CE12 в заголовке IP следует подтверждать незамедлительно для снижения времени отклика партнёра на перегрузку.

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

13.2.2. Частота подтверждений

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

Конечные точки полагаются на своевременные подтверждения при обнаружении потерь (см. раздел 6 в [QUIC-RECOVERY]). Контроллеры перегрузки на основе окна, такие как описано в разделе 7 [QUIC-RECOVERY], используют подтверждения для управления окном перегрузки. В обоих случаях задержка подтверждений может существенно влиять на производительность. С другой стороны, снижение частоты передачи пакетов, содержащих лишь подтверждения, уменьшает издержки на передачу и обработку в обеих конечных точках. Это может значительно повысить пропускную способность на ассиметричных каналах и снизить объем трафика подтверждений на пути возврата (см. раздел 3 в [RFC3449]).

Получателю следует передавать кадр ACK после приёма по меньшей мере двух пакетов с запросом подтверждения. Эта рекомендация имеет общий характер и согласуется с рекомендациями для конечных точек TCP [RFC5681]. Знание условий в сети и сведения о контроллере перегрузок у партнёра, а также дополнительные исследования и эксперименты могут предложить иную стратегию подтверждения с лучшими показателями производительности.

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

13.2.3. Поддержка диапазонов ACK

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

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

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

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

Получатель должен сохранять ACK Range, пока не может гарантировать, что позднее не воспримет пакеты из этого диапазона. Поддержка минимального номера пакета, возрастающего по мере отбрасывания диапазонов является одним из способов решения задачи с минимальным состоянием. Получатель может отбросить все ACK Range, но он должен хранить максимальный номер успешно обработанного пакета, поскольку он служит для восстановления номеров из последующих пакетов (см. параграф 17.1). Получателю следует включать ACK Range с наибольшим полученным номером пакета в каждый кадр ACK. Поле Largest Acknowledged применяется при проверке ECN у отправителя и включение значения меньше указанного в предыдущем кадре ACK может приводить к ненужному отключению ECN (см. параграф 13.4.2).

В параграфе 13.2.4 описан примерный подход к определению пакетов, подтверждаемых в каждом кадре ACK. Хотя цель алгоритма состоит в генерации подтверждения для каждого обработанного пакета, это не препятствует потере подтверждений.

13.2.4. Ограничение диапазонов путём отслеживания кадров ACK

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

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

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

13.2.5. Измерение и передача задержки на хосте

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

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

Когда измеренная задержка подтверждения превышает max_ack_delay, конечной точке следует сообщить об измеренной задержке. Эта информация особенно полезна при согласовании, когда задержки могут быть велики (см. параграф 13.2.1).

13.2.6. Кадры ACK и защита пакета

Кадры ACK должны передаваться лишь в пакетах из одного пространства номеров с подтверждаемым пакетом (см. параграф 12.1). Например, пакеты, защищённые ключами 1-RTT, должны подтверждаться в пакетах, также защищённых ключами 1-RTT.

Пакеты, которые клиент передаёт с защитой 0-RTT, должны подтверждаться сервером в пакетах, защищённых ключами 1-RTT. Это означает, что клиент не может использовать эти подтверждения, если пакеты криптографического согласования от сервера задержаны или потеряны. Отметим, что такое же ограничение применимо и к другим данным, которые сервер защищает с помощью ключей 1-RTT.

13.2.7. Кадры PADDING, занимающие окно перегрузки

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

13.3. Повторная передача информации

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

  • Данные из кадров CRYPTO передаются повторно в соответствии с правилами [QUIC-RECOVERY], пока все данные не будут подтверждены. Данные в кадрах CRYPTO пакетов Initial и Handshake отбрасываются при отбрасывании ключей для соответствующего пространства номеров.

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

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

  • Отмена передачи потока в кадре RESET_STREAM передаётся, пока не будет подтверждена или пока партнёр не подтвердит все данные потока (т. е. будет достигнуто состояние Reset Recvd или Data Recvd на передающей стороне потока). Содержимое RESET_STREAM недопустимо менять при повторе передачи.

  • Аналогично, запрос на отмену передачи потока в кадре STOP_SENDING, отправляется пока принимающая сторона потока не перейдёт в состояние Data Recvd или Reset Recvd (см. параграф 3.5).

  • Сигналы закрытия соединения, включая пакеты с кадрами CONNECTION_CLOSE, не повторяются при обнаружении потери пакета. Повторная отправка этих сигналов описана в разделе 10.

  • Максимальный объем данных текущего соединения передаётся в кадрах MAX_DATA. Обновлённое значение передаётся в кадре MAX_DATA, если пакет с наиболее свежим переданным кадром MAX_DATA был объявлен потерянным или конечная точка решила обновить предел. Нужна осторожность, чтобы избежать слишком частой отправки этого кадра, поскольку предел может увеличиваться часто и это вызовет передачу слишком большого числа кадров MAX_DATA (см. параграф 4.2).

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

  • Ограничение числа потоков данного типа передаётся в кадрах MAX_STREAMS. Подобно MAX_DATA, обновлённое значение передаётся, когда пакет с наиболее свежим MAX_STREAMS для этого типа потока объявлен потерянным или при обновлении предела, с мерами предосторожности для предотвращения слишком частой отправки.

  • Сигналы блокировки передаются в кадрах DATA_BLOCKED, STREAM_DATA_BLOCKED и STREAMS_BLOCKED. Областью действия DATA_BLOCKED является соединение, STREAM_DATA_BLOCKED — поток, STREAMS_BLOCKED — конкретный тип потока. Новый кадр передаётся, если пакет с наиболее свежим кадром для области действия считается потерянным при условии блокировки конечной точки по соответствующему пределу. Эти кадры всегда включают предел, вызвавший блокировку на момент передачи.

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

  • Отклики при проверке пути с использованием кадров PATH_RESPONSE передаются однократно. Предполагается, что партнёр передаст при необходимости дополнительные кадры PATH_CHALLENGE для отправки новых кадров PATH_RESPONSE.

  • Новые идентификаторы соединения передаются в кадрах NEW_CONNECTION_ID и повторяются при потере пакета с сохранением порядкового номера. Отозванные идентификаторы соединения передаются в кадрах RETIRE_CONNECTION_ID и повторяются при потере пакета.

  • Кадры NEW_TOKEN передаются повторно при потере пакета с кадром. Для этих кадров не выполняется обнаружения разупорядочения или дублирования сверх прямого сравнения содержимого кадров.

  • Кадры PING и PADDING не содержат информации, поэтому их потеря не требует восстановления.

  • Кадр HANDSHAKE_DONE должен передаваться повторно, пока не будет получено подтверждение.

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

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

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

При обнаружении потерь отправитель должен принять меры по контролю перегрузки. Детали обнаружения потерь и контроля перегрузки описаны в [QUIC-RECOVERY].

13.4. Явное уведомление о перегрузке

Конечные точки QUIC могут использовать ECN [RFC3168] для обнаружения перегрузки в сети и реагирования на неё. ECN позволяет конечной точке установить код ECT13 в поле ECN пакета IP. Узел сети может тогда указать перегрузку, устанавливая код ECN-CE в поле ECN вместо отбрасывания пакета [RFC8087]. Конечные точки реагируют на сведения о перегрузке путём снижения скорости передачи, как описано в [QUIC-RECOVERY].

Для включения ECN передающая конечная точка QUIC сначала проверяет поддержку маркировки ECN на пути и возможность партнёра сообщать значения ECN в принятых пакетах IP (см. параграф 13.4.2).

13.4.1. Информирование о значениях ECN

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

Даже если конечная точка не устанавливает поле ECT в передаваемых пакетах, она должна предоставлять отклики о полученных маркерах ECN, если они доступны. Отказ от передачи этих значений вынудит отправителя отключить использование ECN в соединении.

При получении пакета IP с кодом ECT(0), ECT(1) или ECN-CE конечная точка с поддержкой ECN обращается к полю ECN и увеличивает соответствующее значение ECT(0), ECT(1) или ECN-CE. Значения ECN включаются в последующие кадры ACK (см. параграфы 13.2 и 19.3).

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

Счётчики ECN инкрементируются лишь в том случае, когда пакеты QUIC из полученного пакета IP обработаны. Таким образом, дубликаты пакетов QUIC не увеличивают счётчики ECN (см. параграф 21.10 в части безопасности).

13.4.2. Проверка ECN

Неисправные устройства в сети могут повреждать или ошибочно отбрасывать пакеты с ненулевым кодом ECN. Для обеспечения связности при наличии таких устройств конечная точка проверяет значения ECN для каждого пути через сеть и отключает ECN на путях с ошибками. Для проверки ECN на новом пути:

  • конечная точка устанавливает код ECT(0) в заголовке IP ранних исходящих пакетов на новом пути к партнёру [RFC8311];

  • конечная точка отслеживает, все ли пакеты, переданные с кодом ECT, в конечном итоге будут потеряны (параграф 6 в [QUIC-RECOVERY]), что говорит об отказе при проверке ECN.

Если у конечной точки есть основания ожидать отбрасывания пакетов IP с кодом ECT неисправными элементами сети, она может устанавливать код ECT лишь для первого десятка исходящих пакетов на этом пути или в течении трёх PTO (см. параграф 6.2 в [QUIC-RECOVERY]). Если все пакеты с ненулевым кодом ECN будут потеряны, она может отключить маркировку в предположении, что та вызывает потерю пакетов. Таким образом, конечная точка пытается использовать ECN и проверяет это для каждого нового соединения при переключении на предпочтительный адрес сервера или активном переходе соединения на новый путь. Возможный алгоритм представлен в Приложении A.4. Возможны и другие методы проверки ECN на пути, а также иная стратегия маркировки. Реализации могут применять другие методы, определённые в RFC, см. [RFC8311].Реализациям, использующим код ECT(1) нужно выполнять проверку ECN с использованием сообщаемых значений ECT(1).

13.4.2.1. Прием кадров ACK со значениями ECN

Ошибочная маркировка ECN-CE в сети может снижать производительность соединения. Конечная точка, получившая кадр ACK со значением ECN, проверяет полученное значение до его использования. Эта проверка выполняется путём сравнения недавно полученного значения со значениями из последнего успешно обработанного кадра ACK. Любое увеличение счётчика ECN проверяется на основе маркировки ECN, которая применялась для пакетов, которые недавно подтверждены в кадре ACK.

Если кадр ACK снова подтверждает пакет, переданный конечной точкой с кодом ECT(0) или ECT(1), это говорит о неудачной проверке ECN при отсутствии соответствующих счётчиков ECN в кадре ACK. Такая проверка обнаруживает элементы сети, которые обнуляют поле ECN, или партнёра, не сообщающего маркировку ECN. Проверка ECN также будет неудачной, если сумма роста счётчиков ECT(0) и ECN-CE меньше числа недавно подтверждённых пакетов, которые были переданы с маркировкой ECT(0). Точно так же проверка ECN будет неудачной, если сумма увеличения счётчиков ECT(1) и ECN-CE будет меньше числа недавно подтверждённых пакетов, которые были переданы с маркировкой ECT(1). Это позволяет обнаружить перемаркировку ECN-CE в сети.

Конечная точка может пропустить подтверждения для пакета при потере кадров ACK, поэтому общее увеличение счётчиков ECT(0), ECT(1) и ECN-CE может быть больше числа пакетов, недавно подтверждённых в кадре ACK. По этой причине счётчикам ECN разрешено превышать общее число подтверждённых пакетов.

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

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

13.4.2.2. Результаты проверки ECN

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

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

14. Размер дейтаграмм

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

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

В QUIC предполагается минимальный размер пакета IP не менее 1280 байтов. Эти минимальный размер для IPv6 [IPv6] и он поддерживается в большинстве современных сетей IPv4. В предположении заголовка IP размером 40 байтов для IPv6 и 20 для IPv4, а также размера заголовка UDP 8 байтов максимальный размер дейтаграммы будет 1232 байта для IPv6 и 1252 для IPv4. Таким образом, пути через современные сети IPv4 и все сети IPv6 предполагаются пригодными для QUIC.

Примечание. Требование поддержки данных UDP размером 1200 байтов ограничивает пространство для заголовков расширения IPv6 значением 32 байта и опций IPv4 — значением 52 байта, если путь поддерживает лишь минимальное для IPv6 значение MTU в 1280 байтов. Это влияет на пакеты Initial и проверку пути.

Превышение значения 1200 байтов для максимального размера в можно обнаружить с помощью механизма PMTUD14 (см. параграф 14.2.1) или DPLPMTUD15 (см. параграф 14.3).

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

Дейтаграммы UDP недопустимо фрагментировать на уровне IP. В IPv4 [IPv4] должен устанавливаться флаг запрета фрагментирования (Don’t Fragment или DF), если это возможно.

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

14.1. Размер дейтаграмм Initial

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

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

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

Сервер должен отбрасывать пакет Initial, переданный в дейтаграмме UDP с объёмом данных меньше наименьшего максимума в 1200 байтов. Сервер может также незамедлительно закрыть соединение, передав кадр CONNECTION_CLOSE с кодом ошибки PROTOCOL_VIOLATION (см. параграф 10.2.3).

Сервер также должен ограничивать число байтов, передаваемых до проверки адреса клиента (см. раздел 8).

14.2. MTU на пути

PMTU определяет максимальный размер пакета IP с учётом заголовков IP и UDP, а также данных UDP, включая один или несколько заголовков пакетов QUIC и защищённые данные. PMTU может зависеть от характеристик пути и меняться с течением времени. Максимальный размер данных UDP (payload), которые конечная точка может передать в данный момент называется максимальным размером дейтаграммы для конечной точки.

Конечной точке следует применять механизм DPLPMTUD (параграф 14.3) или PMTUD (параграф 14.2.1) для определения максимального размера (без фрагментации) дейтаграмм на пути к получателю. При отсутствии этих механизмов конечным точкам QUIC не следует передавать дейтаграммы размером больше наименьшего максимума.

DPLPMTUD и PMTUD передают дейтаграммы размером больше текущего максимума, называемые зондами PMTU. Всем пакетам QUIC, передаваемым не в зондах PMTU, следует ограничивать размер для размещения в дейтаграммах максимального размера, чтобы избежать фрагментации или отбрасывания [RFC8085].

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

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

Реализация QUIC может быть более консервативной при расчёте максимального размера дейтаграмм, чтобы учесть неизвестные издержки туннелирования и/или опций (расширений) в заголовках IP.

14.2.1. Обработка сообщений ICMP в PMTUD

PMTUD [RFC1191] [RFC8201] полагается на приём сообщений ICMP (т. е. IPv6 Packet Too Big), указывающий, что пакет IP отброшен из-за превышения MTU на маршрутизаторе. DPLPMTUD также может использовать такие сообщения. Этот подход имеет уязвимость для атак со стороны объектов, не способных наблюдать за пакетами, но могущим угадать используемые на пути адреса. Такие атаки позволяют снизить значение PMTU для уменьшения пропускной способности. Конечная точка должна игнорировать сообщения ICMP, заявляющие о снижении PMTU ниже наименьшего для QUIC максимума размера дейтаграмм.

В требованиях к генерации ICMP [RFC1812] [RFC4443] сказано, что в пакет следует включать максимально возможную часть исходного пакета без превышения минимального MTU для версии IP. Размер включаемой в сообщение части пакета может быть меньше или информация может быть непонятной, как указано в параграфе 1.1 [DPLPMTUD].

Конечным точкам QUIC, использующим PMTUD, следует проверять сообщения ICMP для защиты от вставки пакетов, как указано в [RFC8201] и параграфе 5.2 [RFC8085]. Для этой проверки следует использовать включённую в сообщение часть пакета для сопоставления сообщения ICMP с соответствующим транспортным соединением (см. параграф 4.6.1 в [DPLPMTUD]). Проверка сообщения ICMP должна включать сопоставление адреса IP и порта UDP [RFC8085], а по возможности идентификатор соединения для активной сессии QUIC. Конечное точке следует игнорировать сообщения ICMP, не прошедшие проверку.

Конечной точке недопустимо увеличивать PMTU на основе сообщений ICMP (см. п. 6 в разделе 3 [DPLPMTUD]). Снижение максимального размера дейтаграмм QUIC в ответ на сообщения ICMP может быть предварительным, пока алгоритм обнаружения потерь QUIC не укажет, что пакет был действительно потерян.

14.3. Определение PMTU для уровня пакетизации дейтаграмм

DPLPMTUD [DPLPMTUD] полагается на отслеживание потерь или подтверждений пакетов QUIC, переданных в зондах PMTU. Зонды PMTU для DPLPMTUD, использующие кадр PADDING, реализуют «Зондирование с использованием заполнения», описанное в параграфе 4.1 [DPLPMTUD].

Конечным точкам следует устанавливать исходное значение BASE_PLPMTU (параграф 5.1 в [DPLPMTUD]) в соответствии с наименьшим максимальным размером дейтаграмм QUIC. MIN_PLPMTU совпадает с BASE_PLPMTU.

Конечные точки QUIC, реализующие DPLPMTUD, поддерживают максимальный размер пакета DPLPMTUD (Maximum Packet Size или MPS) (параграф 4.4 в [DPLPMTUD]) для каждой пары из локального и удалённого адреса IP. Это соответствует максимальному размеру дейтаграмм.

14.3.1. DPLPMTUD и связность для Initial

С точки зрения DPLPMTUD протокол QUIC является уровнем пакетизации (Packetization Layer или PL) с подтверждениями. Поэтому отправитель QUIC может перейти в состояние DPLPMTUD BASE (параграф 5.2 в [DPLPMTUD]) по завершении согласования QUIC.

14.3.2. Проверка сетевого пути с DPLPMTUD

QUIC является PL с подтверждениями, поэтому отправитель QUIC не реализует DPLPMTUD CONFIRMATION_TIMER в состоянии SEARCH_COMPLETE (см. параграф 5.2 в [DPLPMTUD]).

14.3.3. Обработка сообщений ICMP в DPLPMTUD

Конечная точка, применяющая DPLPMTUD, требует проверки любого полученного сообщения ICMP PTB до использования сведений PTB, как указано в параграфе 4.6 [DPLPMTUD]. В дополнение к проверке порта UDP протокол QUIC проверяет сообщение ICMP путём использования других сведений PL (например, проверку идентификатора соединения во включённой в сообщение ICMP части исходного пакета).

Рассмотренные в параграфе 14.2.1 вопросы обработки сообщений ICMP применимы и к сообщениям, используемым DPLPMTUD.

14.4. Отправка зондов QUIC PMTU

Зонды PMTU являются пакетами с запросом подтверждения.

Конечные точки могут ограничивать содержимое зондов PMTU кадрами PING и PADDING, поскольку пакеты с размером, превышающий текущий максимум для дейтаграмм, с большой вероятностью будут отброшены сетью. Поэтому потеря пакета QUIC в зонде PMTU не является надёжной индикацией перегрузки и ей не следует вызывать реакцию механизма контроля перегрузок (см. п. 7 в разделе 3 [DPLPMTUD]). Однако зонды PMTU занимают окно перегрузки, что может задерживать последующую передачу данных приложения.

14.4.1. Зонды PMTU с Source Connection ID

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

Одним из способов создания зонда PMTU является объединение (см. параграф 12.2) пакета с длинным заголовком, такого как Handshake или 0-RTT (параграф 17.2) и пакета с коротким заголовком в одну дейтаграмму UDP. Если полученный зонд PMTU достигает конечной точки, пакет с длинным заголовком она проигнорирует, но подтвердит пакет с коротким заголовком. Если зонд PMTU вызывает отправку сообщения ICMP, в это сообщение будет включена первая часть пробного пакета. Если поле Source Connection ID попадает в эту часть, оно может служить для маршрутизации или проверки сообщения ICMP.

Примечание. Цель использования пакета с длинным заголовком заключается лишь в попытке включить поле Source Connection ID в часть пакета, возвращаемую в сообщении ICMP. Этот пакет не обязан быть действительным и его можно передавать даже в том случае, когда пакеты данного типа не используются.

15. Версии

Версия QUIC указывается 32-битовым целым числом без знака. Значение 0x00000000 зарезервировано для согласования версий, а текущая версия протокола имеет номер 0x00000001.

Другие версии QUIC могут отличаться свойствами. Набор свойств QUIC, гарантированных в любой версии, описан в [QUIC-INVARIANTS].

Версия 0x00000001 протокола QUIC применяет TLS в качестве протокола криптографического согласования, как указано в [QUIC-TLS].

Версии, где 16 старших битов имеют значение 0, зарезервированы для использования в согласованных IETF документах.

Версии, соответствующие шаблону 0x?a?a?a?a, зарезервированы для использования в принудительном согласовании версии, когда принимается любой номер версии, где 4 младших бита каждого байта имеют двоичное значение 1010. Клиент или сервер может анонсировать поддержку любой из этих зарезервированных версий.

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

16. Представление целочисленных полей переменного размера

В пакетах и кадрах QUIC широко применяется представление неотрицательных целых чисел с переменным размером. Такое представление обеспечивает меньший размер для небольших целых чисел.

QUIC резервирует 2 старших бита для представления размера числа двоичным логарифмом. Остальные биты служат для значения числа с использованием сетевого порядка байтов. Это означает представление целых чисел 1, 2, 4 или 8 байтами и значения этих чисел выражаются 6, 14, 30 или 62 байтами, соответственно (таблица 4).

Таблица 4. Сводка представления целых чисел.

2 старших бита

Число байтов

Число битов значения

Диапазон

00

1

6

0-63

01

2

14

0-16383

10

4

30

0-1073741823

11

8

62

0-4611686018427387903

Пример алгоритма декодирования и образцы кодирования приведены в Приложении A.1.

Значения не требуется кодировать с минимально возможным размером за исключением поля Frame Type (параграф 12.4).

Версии (раздел 15), номера пакетов в заголовках (раздел 17.1) и размер идентификатора соединения в длинном заголовке (параграф 17.2) задаются целыми числами, но не используют описанного здесь кодирования.

17. Формат пакетов

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

17.1. Кодирование и декодирование номера пакетов

Номера пакетов указываются числами от 0 до 262-1 (параграф 12.3). При указании в заголовке они имеют размер от 1 до 4 байтов. Число используемых битов уменьшается за счёт включения лишь младших битов порядкового номера. Номер пакета защищается, как указано в параграфе 5.4 [QUIC-TLS].

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

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

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

17.2. Пакеты с длинным заголовком

     Long Header Packet {
     Header Form (1) = 1,
     Fixed Bit (1) = 1,
     Long Packet Type (2),
     Type-Specific Bits (4),
     Version (32),
     Destination Connection ID Length (8),
     Destination Connection ID (0..160),
     Source Connection ID Length (8),
     Source Connection ID (0..160),
     Type-Specific Payload (..),
   }

Рисунок 13. Формат пакета с длинным заголовком.


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

Header Form

Старший бит (0x80) байта 0 (первый байт) устанавливается в длинном заголовке.

Fixed Bit

Следующий бит (0x40) байта 0 устанавливается (1), если пакет не относится к Version Negotiation. Пакеты со сброшенным битом считаются в этой версии недействительными и должны отбрасываться. Установка этого бита позволяет QUIC сосуществовать с другими протоколами, см. [RFC7983].

Long Packet Type

Два следующих бита (маска 0x30) байта 0 указывают тип пакета (см. таблицу 5).

Type-Specific Bits

Семантика 4 младших битов (маска 0x0f) байта 0 определяется типом пакета.

Version

QUIC Version — 32-битовое поле, следующее за первым байтом, указывающее используемую версию QUIC и определяющее интерпретацию остальных полей протокола.

Destination Connection ID Length

Байт после номера версии указывает размер (в байтах) следующего за ним поля Destination Connection ID, представляемый 8-битовым целым числом без знака. В QUIC версии 1 этому значению недопустимо превосходить 20. Конечная точка версии 1, получившая заголовок со значением больше 20 в этом поле, должна отбросить пакет. Для корректного формирования пакета Version Negotiation серверам следует поддерживать возможность чтения более длинного идентификатора соединения из других версий QUIC.

Destination Connection ID

Поле Destination Connection ID следует за полем Destination Connection ID Length, указывающим его размер. Использование этого поля описано в параграфе 7.2.

Source Connection ID Length

Байт после поля Destination Connection ID указывает размер (в байтах) следующего за ним поля Source Connection ID, представленный 8-битовым целым числом без знака. В QUIC версии 1 этому значению недопустимо превосходить 20. Конечная точка версии 1, получившая заголовок со значением больше 20 в этом поле, должна отбросить пакет. Для корректного формирования пакета Version Negotiation серверам следует поддерживать возможность чтения более длинного идентификатора соединения из других версий QUIC.

Source Connection ID

Поле Source Connection ID следует за полем Source Connection ID Length, указывающим его размер. Использование этого поля описано в параграфе 7.2.

Type-Specific Payload

Оставшаяся часть пакета (при её наличии) зависит от типа пакета.

В этой версии QUIC определены показанные в таблице 5 типы пакетов с длинным заголовком.

Таблица 5. Типы пакетов с длинным заголовком.

Тип

Имя

Параграф

0x00

Initial

17.2.2. Начальный пакет

0x01

0-RTT

17.2.3. Пакет 0-RTT

0x02

Handshake

17.2.4. Пакет согласования

0x03

Retry

17.2.5. Пакет Retry

Бит формы заголовка, поля размера идентификаторов соединения и самих идентификаторов, а также поле Version в длинном заголовке не зависят от версии. Остальные поля первого байта зависят от версии протокола. В [QUIC-INVARIANTS] описана интерпретация пакетов разных версий QUIC. Интерпретация этих полей и данных (payload) определяется версией и типом пакета. Задаваемая типом семантика для данной версии описана в следующих параграфах, однако некоторые типы пакетов с длинным заголовком в этой версии QUIC содержат дополнительные поля.

Reserved Bits

Два бита (маска 0x0c) байта 0 зарезервированы для нескольких типов пакетов. Эти биты охватывается защитой заголовка (см. параграф 5.4 в [QUIC-TLS]). До установки защиты биты должны иметь значение 0. Конечная точка должна считать получение пакета с отличными от 0 значениями этих битов после снятия защиты пакета и заголовка ошибкой соединения типа PROTOCOL_VIOLATION. Отбрасывание такого пакета после снятия лишь защиты заголовка может раскрывать конечную точку для атаки (см. параграф 9.5 в [QUIC-TLS]).

Packet Number Length

В типах пакетов с полем Packet Number два младших бита (маска 0x03) байта 0 указывают размер поля Packet Number, представленный 2-битовым целым число без знака на 1 меньше фактического размера поля Packet Number в байтах. Т. е. размер поля Packet Number определяется добавлением 1 к значению этого поля. Эти биты охватывается защитой заголовка (см. параграф 5.4 в [QUIC-TLS]).

Length

Размер оставшейся части пакета (поля Packet Number и Payload) в байтах, представленный целым числом без знака с переменным размером (раздел 16).

Packet Number

Поле размером от 1 до 4 Байтов, охватываемое защитой заголовка (см. параграф 5.4 в [QUIC-TLS]). Размер поля Packet Number представлен в поле Packet Number Length байта 0, как описано выше.

Packet Payload

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

17.2.1. Пакет согласования версии

Пакет Version Negotiation по своей природе не зависит от версии. При получении клиентом пакет будет идентифицирован как Version Negotiation по полю Version = 0. Пакет согласования версии служит откликом на пакет клиент, запросивший у сервера не поддерживаемую тем версию. Пакет передаётся только серверами.

   Version Negotiation Packet {
     Header Form (1) = 1,
     Unused (7),
     Version (32) = 0,
     Destination Connection ID Length (8),
     Destination Connection ID (0..2040),
     Source Connection ID Length (8),
     Source Connection ID (0..2040),
     Supported Version (32) ...,
   }

Рисунок 14. Пакет согласования версии.


В поле Unused сервер устанавливает произвольное значение, а клиент должен игнорировать это поле. Если QUIC может мультиплексироваться с другими протоколами (см. [RFC7983]), серверу следует установить старший бит поля (0x40), чтобы в пакетах Version Negotiation было установлено поле Fixed Bit. Отметим, что в других версиях QUIC эта рекомендация может отсутствовать.

Поле Version в пакете Version Negotiation должно иметь значение 0x00000000.

Сервер должен включить значение Source Connection ID из полученного от клиента пакета в поле Destination Connection ID. Значение поля Source Connection ID должно копироваться из поля Destination Connection ID в полученном пакете, которое клиент выбрал случайно. Возврат обоих идентификаторов соединения даёт клиенту уверенность в том, что сервер получил запрос от клиента и пакет Version Negotiation не был создан объектом, который не видел пакета Initial.

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

Оставшаяся часть пакета Version Negotiation содержит список 32-битовых номеров версий, поддерживаемых сервером.

Пакеты Version Negotiation не подтверждаются и передаются лишь в ответ на пакет, указывающий неподдерживаемую версию (см. параграф 5.)2.2.

Пакет Version Negotiation не включает полей Packet Number и Length, имеющихся в других пакетах с длинным заголовком, поэтому такой пакет занимает дейтаграмму UDP целиком. Серверу недопустимо передавать более 1 пакета Version Negotiation в ответ на одну дейтаграмму UDP. Процесс согласования версии описан в разделе 6.

17.2.2. Начальный пакет

Пакет Initial использует длинный заголовок со значением типа 0x00 и передаёт первые кадры CRYPTO от клиента и сервера для обмена ключами, а также кадры ACK в любом из направлений.

   Initial Packet {
     Header Form (1) = 1,
     Fixed Bit (1) = 1,
     Long Packet Type (2) = 0,
     Reserved Bits (2),
     Packet Number Length (2),
     Version (32),
     Destination Connection ID Length (8),
     Destination Connection ID (0..160),
     Source Connection ID Length (8),
     Source Connection ID (0..160),
     Token Length (i),
     Token (..),
     Length (i),
     Packet Number (8..32),
     Packet Payload (8..),
   }

Рисунок 15. Пакет Initial.


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

Token Length

Целое число переменного размера, задающее размер поля Token в байтах. Значение 0 указывает отсутствие маркера. Пакеты Initial от сервера должны содержать Token Length = 0 и клиент, получающий пакет Initial с ненулевым значением Token Length должен отбросить пакет или установить ошибку соединения типа PROTOCOL_VIOLATION.

Token

Значение маркера, представленное ранее в пакете Retry или кадре NEW_TOKEN (см. параграф 8.1).

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

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

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

Данные в пакете Initial включают кадр(ы) CRYPTO с сообщением криптографического согласования, кадры ACK или оба типа. Разрешены также кадры PING, PADDING, CONNECTION_CLOSE типа 0x1c. Конечная точка, получившая пакет Initial с кадрами иных типов, может отбросить пакет как ложный или считать его ошибкой соединения.

Первый пакет от клиента всегда включает кадр CRYPTO, содержащий начало или все сообщение криптографического согласования. Первый кадр CRYPTO всегда начинается со смещения 0 (см. раздел 7).

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

17.2.2.1. Прекращение использования пакетов Initial

Клиент прекращает отправку и обработку пакетов Initial при отправке своего первого пакета Handshake, сервер — при получении своего первого пакета Handshake. Хотя пакеты ещё могут оставаться в сети или ждать подтверждения, дополнительные пакеты Initial больше не нужны с этого момента. Ключи защиты пакетов Initial отбрасываются (см. параграф 4.9.1 в [QUIC-TLS]) вместе с состояниями восстановления потерь и контроля перегрузки (см. параграф 6.4 в [QUIC-RECOVERY]). Данные из кадров CRYPTO отбрасываются (и не передаются повторно) после отбрасывания ключей Initial.

17.2.3. Пакет 0-RTT

Пакет 0-RTT использует длинный заголовок типа 0x01, за которым следуют поля Length и Packet Number (см. параграф 17.2). Первый байт содержит поля Reserved и Packet Number Length (см. параграф 17.2). Пакеты 0-RTT используются для передачи «ранних» данных от клиента к серверу как части первой отправки до завершения согласования. В процессе согласования TLS сервер может воспринять или отвергнуть эти данные. Обсуждение данных 0-RTT и связанных с ними ограничений приведено в параграфе 2.3 [TLS13].

   0-RTT Packet {
     Header Form (1) = 1,
     Fixed Bit (1) = 1,
     Long Packet Type (2) = 1,
     Reserved Bits (2),
     Packet Number Length (2),
     Version (32),
     Destination Connection ID Length (8),
     Destination Connection ID (0..160),
     Source Connection ID Length (8),
     Source Connection ID (0..160),
     Length (i),
     Packet Number (8..32),
     Packet Payload (8..),
   }

Рисунок 16. Пакет 0-RTT.


Номера пакетов с защитой 0-RTT используют то же пространство, что и защищённые пакеты 1-RTT.

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

Клиент получает подтверждения для его пакетов 0-RTT лишь по завершении согласования, как указано в параграфе 4.1.1 [QUIC-TLS].

Клиенту недопустимо передавать пакеты 0-RTT после начала обработки пакетов 1-RTT от сервера. Это значит, что пакеты 0-RTT не могут содержать отклики на кадры из пакетов 1-RTT. Например, клиент не может передать кадр ACK в пакете 0-RTT, поскольку этот кадр может подтверждать лишь пакет 1-RTT. Подтверждение для пакета 1-RTT должно передаваться в пакете 1-RTT.

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

17.2.4. Пакет согласования

Пакеты Handshake используют длинный заголовок типа 0x02, за которым следуют поля Length и Packet Number (см. параграф 17.2). Первый байт содержит поля Reserved и Packet Number Length (см. параграф 17.2). Пакеты служат для передачи сообщений криптографического согласования и подтверждений от сервера и клиента.

   Handshake Packet {
     Header Form (1) = 1,
     Fixed Bit (1) = 1,
     Long Packet Type (2) = 2,
     Reserved Bits (2),
     Packet Number Length (2),
     Version (32),
     Destination Connection ID Length (8),
     Destination Connection ID (0..160),
     Source Connection ID Length (8),
     Source Connection ID (0..160),
     Length (i),
     Packet Number (8..32),
     Packet Payload (8..),
   }

Рисунок 17. Защищенный пакет Handshake.


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

Поле Destination Connection ID в пакете Handshake содержит идентификатор соединения выбранный получателем пакета, Source Connection ID — идентификатор соединения, который желает использовать отправитель (параграф 7.2).

Пакеты Handshake имеют своё пространство номеров, поэтому сервер передаёт первый пакет Handshake с номером 0.

Данные (payload) этого пакета включают кадры CRYPTO и могут включать PING, PADDING или ACK. Пакеты Handshake могут содержать кадры CONNECTION_CLOSE типа 0x1c. Конечная точка должна считать получения пакета Handshake с кадрами других типов ошибкой соединения PROTOCOL_VIOLATION.

Подобно пакетам Initial (см. параграф 17.2.2.1), данные в кадрах CRYPTO пакетов Handshake отбрасываются (и не передаются повторно), когда ключи защиты Handshake отбрасываются.

17.2.5. Пакет Retry

Как показано на рисунке 18, пакет Retry использует длинный заголовок с типом 0x03 и служит для передачи маркера проверки адреса, созданного отправителем. Пакет применяется сервером, желающим выполнить повтор (см. параграф 8.1).

   Retry Packet {
     Header Form (1) = 1,
     Fixed Bit (1) = 1,
     Long Packet Type (2) = 3,
     Unused (4),
     Version (32),
     Destination Connection ID Length (8),
     Destination Connection ID (0..160),
     Source Connection ID Length (8),
     Source Connection ID (0..160),
     Retry Token (..),
     Retry Integrity Tag (128),
   }

Рисунок 18. Пакет Retry.


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

Retry Token

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

Retry Integrity Tag

Тег, определённый в параграфе 5.8 (Целостность пакета Retry) [QUIC-TLS].

17.2.5.1. Отправка пакета Retry

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

Сервер может передавать пакеты Retry в ответ на Initial и 0-RTT. Сервер может отбрасывать или буферизовать полученные пакеты 0-RTT и может отправлять несколько пакетов Retry при получении Initial или 0-RTT. Серверу недопустимо передавать более одного пакета Retry в ответ на одну дейтаграмму UDP.

17.2.5.2. Обработка пакета Retry

Клиент должен воспринимать и обрабатывать не более одного пакета Retry для каждой попытки соединения. После приёма и обработки клиентом сообщения Initial или Retry от сервера клиент должен отбрасывать последующие пакеты Retry.

Клиенты должны отбрасывать пакеты Retry с полем Retry Integrity Tag, которое они не могут проверить (параграф 5.8 в [QUIC-TLS]). Это препятствует внедрению пакетов Retry злоумышленниками и защищает от случайно повреждённых пакетов Retry. Клиент должен отбрасывать пакеты с пустым (размер 0) полем Retry Token.

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

Пакет Retry не включает номера и не может быть явно подтверждён клиентом.

17.2.5.3. Продолжение согласования после пакета Retry

Последующие пакеты Initial от клиента включают идентификатор соединения и маркер из пакета Retry. Клиент копирует поле Source Connection ID из Retry в поле Destination Connection ID и использует это значение, пока не будет получен пакет Initial с обновлённым значением (см. параграф 7.2). Значение поля Token копируется во все последующие пакеты Initial (см. параграф 8.1.2).

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

Клиент может попытаться использовать 0-RTT после приёма сообщения Retry, передавая пакеты 0-RTT с полученным от сервера идентификатором соединения.

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

Идентификаторы соединения в пакетах Initial и Retry, которыми обмениваются клиент и сервер, копируются в транспортные параметры и проверяются, как описано в параграфе 7.3.

17.3. Пакеты с коротким заголовком

В этой версии QUIC определён единственный пакет, использующий короткий заголовок.

17.3.1. Пакет 1-RTT

   1-RTT Packet {
     Header Form (1) = 0,
     Fixed Bit (1) = 1,
     Spin Bit (1),
     Reserved Bits (2),
     Key Phase (1),
     Packet Number Length (2),
     Destination Connection ID (0..160),
     Packet Number (8..32),
     Packet Payload (8..),
   }

Рисунок 19. Пакет 1-RTT.


Пакеты 1-RTT использует короткий и передаются заголовок после согласования версии и ключей 1-RTT.

Header Form

Старший бит (0x80) байта 0 сброшен (0) для короткого заголовка.

Fixed Bit

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

Spin Bit

Третий бит (0x20) байта 0 является битом задержки и устанавливается в соответствии с параграфом 17.4.

Reserved Bits

Два следующих бита (маска 0x18) байта 0 являются резервными. Эти биты охватываются защитой заголовка (см. параграф 5.4 в [QUIC-TLS]). До применения защиты в поле должно быть установлено значение 0. Конечная точка должна считать отличное от 0 значение этого поля после снятия защиты ошибкой соединения типа PROTOCOL_VIOLATION. Отбрасывание таких пакетов после снятия защиты заголовка может делать конечную точку уязвимой для атак (см. параграф 9.5 в [QUIC-TLS]).

Key Phase

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

Packet Number Length

Два младших бита (маска 0x03) байта 0 указывают размер поля Packet Number, представленный 2-битовым целым число без знака на 1 меньше фактического размера поля Packet Number в байтах. Т. е. размер поля Packet Number определяется добавлением 1 к значению этого поля. Эти биты охватывается защитой заголовка (см. параграф 5.4 в [QUIC-TLS]).

Destination Connection ID

Идентификатор соединения, выбранный предполагаемым получателем пакета (см. параграф 5.1).

Packet Number

Поле размером от 1 до 4 Байтов, охватываемое защитой заголовка (см. параграф 5.4 в [QUIC-TLS]). Размер поля Packet Number представлен в поле Packet Number Length байта 0 (см. параграф 17.1).

Packet Payload

Пакеты 1-RTT всегда включают данные, защищённые с использованием режима 1-RTT.

Бит формы заголовка и поле Destination Connection ID в коротком заголовке не зависят от версии. Остальные поля первого байта зависят от версии протокола. В [QUIC-INVARIANTS] описана интерпретация пакетов разных версий QUIC.

17.4. Spin Bit для задержки

Поле Spin Bit, определённое для пакетов 1-RTT (параграф 17.3.1), позволяет вести пассивных мониторинг задержки из точек наблюдения на пути через сеть в течение соединения. Сервер возвращает полученное значение бита, а клиент «поворачивает» (spin) его после одного RTT. Находящиеся на пути наблюдатели могут измерить время между двумя переключениями бита для оценки сквозного значения RTT в соединении.

Spin Bit применяется лишь в пакетах 1-RTT, поскольку можно измерить начальное значение RTT в соединении, наблюдая за согласованием (handshake). Поэтому бит становится доступным по завершении согласования версии и организации соединения. Измерение в пути и использование бита дополнительно рассматриваются в [QUIC-MANAGEABILITY].

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

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

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

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

Конечная точка сбрасывает в 0 значение Spin Bit для пути при смене идентификатора соединения на этом пути.

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

Поле extension_data расширения quic_transport_parameters, определённое в [QUIC-TLS], содержит транспортные параметры QUIC, кодируемые в виде последовательности, как показано на рисунке 20.

   Transport Parameters {
     Transport Parameter (..) ...,
   }

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


Каждый параметр представляется триплетом (идентификатор, размер, значение), как показано на рисунке 21

   Transport Parameter {
     Transport Parameter ID (i),
     Transport Parameter Length (i),
     Transport Parameter Value (..),
   }

Рисунок 21. Кодирование транспортных параметров.


Поле Transport Parameter Length указывает размер поля Transport Parameter Value в октетах.

QUIC кодирует параметры транспорта в последовательности байтов, включаемые в криптографическое согласование.

18.1. Резервные параметры транспорта

Транспортные параметры с идентификаторами вида 31*N+27 при целочисленных N зарезервированы для выполнения требования по игнорированию неизвестных параметров. Эти параметры не имеют семантики и могут включать произвольные значения.

18.2. Определения транспортных параметров

В этом параграфе детализируются транспортные параметры, определённые в документе. Многие из перечисленных параметров транспорта имеют целочисленные значения и для них используется кодирование с переменным размером, описанное в разделе 6. Для неуказанных параметров по умолчанию принимается значение 0, если не указано иное.

original_destination_connection_id (0x00)

Значение поля Destination Connection ID из первого пакета Initial от клиента (см. параграф 7.3). Параметр передают только серверы.

max_idle_timeout (0x01)

Число миллисекунд максимального тайм-аута бездействия, представленное целочисленным значением. (параграф 10.1). Тайм-аут бездействия отключается, если обе точки укажут значение 0 или опустят этот параметр.

stateless_reset_token (0x02)

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

max_udp_payload_size (0x03)

Максимальный размер данных UDP (payload), выраженный целым числом, для ограничения размера дейтаграмм UDP, которые эта конечная точка хочет получать. Дейтаграммы UDP с большим размером данных могут не обрабатываться их получателем. По умолчанию для этого параметра используется максимальный размер данных в дейтаграмме UDP (65527 байтов). Значения меньше 1200 являются недействительными. Этот параметр служит дополнительным ограничением размера дейтаграмм к значению MTU на пути, но является свойством конечной точки, а не пути (см. раздел 14). Предполагается, что это значение определяется пространством, выделенным конечной точкой для входящих пакетов.

initial_max_data (0x04)

Целое число, указывающее заданный в начале максимальный объем данных, которые могут быть переданы в соединении. Это эквивалентно передаче MAX_DATA (параграф 19.9) для соединения сразу после согласования.

initial_max_stream_data_bidi_local (0x05)

Целое число, задающее начальный предел управления потоком данных, для локально инициированных двухсторонних потоков. Этот предел относится к недавно созданным двухсторонним потокам, открытым конечной точкой, которая передала транспортный параметр. В параметрах клиента этот относится к потокам с идентификатором, где два младших бита имеют значение 0x00, в параметрах сервера — 0x01.

initial_max_stream_data_bidi_remote (0x06)

Целое число, задающее начальный предел управления потоком данных, для инициированных партнёром двухсторонних потоков. Этот предел относится к недавно созданным двухсторонним потокам, открытым конечной точкой, которая получила транспортный параметр. В параметрах клиента этот относится к потокам с идентификатором, где два младших бита имеют значение 0x01, в параметрах сервера — 0x00.

initial_max_stream_data_uni (0x07)

Целое число, задающее начальный предел управления потоком данных, для односторонних потоков. Этот предел относится к недавно созданным односторонним потокам, открытым конечной точкой, которая получила транспортный параметр. В параметрах клиента этот относится к потокам с идентификатором, где два младших бита имеют значение 0x03, в параметрах сервера — 0x02.

initial_max_streams_bidi (0x08)

Целое число, задающее начальное ограничение числа двухсторонних потоков, которые разрешено инициировать принявшей параметр конечной станции. Если параметр отсутствует или имеет значение 0, партнёр не может создавать двухсторонних поток до передачи кадра MAX_STREAMS. Установка параметра эквивалентна отправке MAX_STREAMS (параграф 19.11) соответствующего типа с тем же значением.

initial_max_streams_uni (0x09)

Целое число, задающее начальное ограничение числа односторонних потоков, которые разрешено инициировать принявшей параметр конечной станции. Если параметр отсутствует или имеет значение 0, партнёр не может создавать двухсторонних поток до передачи кадра MAX_STREAMS. Установка параметра эквивалентна отправке MAX_STREAMS (параграф 19.11) соответствующего типа с тем же значением.

ack_delay_exponent (0x0a)

Целое число, указывающее показатель степени, используемый для декодирования поля ACK Delay в кадре ACK (параграф 19.3). По умолчанию используется значение 3 (коэффициент 8). Значения больше 20 недействительны.

max_ack_delay (0x0b)

Целое число, указывающее максимальную задержку (в миллисекундах) отправки подтверждения конечной точкой. В значении следует учитывать задержку, после которой получатель устанавливает сигнал тревоги. Например, если получатель установил таймер на 5 мсек а сигнал тревоги обычно задерживается на 1 мсек, следует задать max_ack_delay = 6 мсек. По умолчанию предполагается 25 мсек. Значения 214 и больше недействительны.

disable_active_migration (0x0c)

Параметр запрета активного переноса включается, если конечная точка не поддерживает активный перенос соединений (раздел 9) для адреса, использованного при согласовании. Получившей этот параметр конечной точке недопустимо использовать новый локальный адрес при отправке по адресу, который партер использовал для согласования. Этот параметр не запрещает перенос соединения, после того, как клиент воздействовал на транспортный параметр preferred_address transport. Параметр имеет нулевой размер.

preferred_address (0x0d)

Предпочтительный адрес сервера служит для изменения адреса сервера в конце согласования, как описано в параграфе 9.6. Этот параметр передают только серверы. Сервер может выбрать предпочтительный адрес лишь для одного семейства, указав для другого нулевой адрес и порт (0.0.0.0:0 или [::]:0). Адрес IP указывается с сетевым порядком байтов.

Параметр preferred_address содержит адрес и порт для IPv4 и IPv6. За 4-байтовым полем IPv4 следует 2 байта поля IPv4, затем 16 байтов IPv6 Address и 2 байта IPv6 Port. После адресов и портов указывается поле Connection ID Length, задающее размер следующего за ним поля Connection ID. Последним является 16-байтовое поле Stateless Reset Token с маркером сброса без учёта состояния, связанным с идентификатором соединения. Формат транспортного параметра показан на рисунке 22.

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

   Preferred Address {
     IPv4 Address (32),
     IPv4 Port (16),
     IPv6 Address (128),
     IPv6 Port (16),
     Connection ID Length (8),
     Connection ID (..),
     Stateless Reset Token (128),
   }

Рисунок 22. Формат предпочтительного адреса.


active_connection_id_limit (0x0e)

Целое число, задающее максимальное количество идентификаторов соединений от партнёра, которые конечная точка желает сохранить. Это значение включает идентификатор соединения, полученный при согласовании соединения, а также полученные в транспортном параметре preferred_address и кадрах NEW_CONNECTION_ID. Значение параметра active_connection_id_limit должно быть не меньше 2. Конечная точка, получившая значение меньше 2, должна закрыть соединение с ошибкой типа TRANSPORT_PARAMETER_ERROR. При отсутствии этого транспортного параметра предполагается значение 2. Если конечная точка указывает пустой идентификатор соединения, она не будет передавать кадров NEW_CONNECTION_ID, поэтому игнорирует полученное от партнёра значение active_connection_id_limit.

initial_source_connection_id (0x0f)

Значение, указанное конечной точкой в поле Source Connection ID первого пакета Initial в соединении (параграф 7.3).

retry_source_connection_id (0x10)

Значение, указанное сервером в поле Source Connection ID пакета Retry (параграф 7.3). Этот параметр передаёт только сервер.

При наличии транспортных параметров, устанавливающих начальные пределы для управления потоком данных на уровне потока (initial_max_stream_data_bidi_local, initial_max_stream_data_bidi_remote, initial_max_stream_data_uni), они эквивалентны отправке кадра MAX_STREAM_DATA (параграф 19.10) в каждом потоке соответствующего типа сразу после создания. При отсутствии транспортного параметра потоки данного типа запускаются с пределом управления потоком данных 0.

Клиенту недопустимо включать какие-либо транспортные параметры, предназначенные лишь для серверов (original_destination_connection_id, preferred_address, retry_source_connection_id, stateless_reset_token). Сервер должен считать получение такого транспортного параметра ошибкой соединения типа TRANSPORT_PARAMETER_ERROR.

19. Типы и форматы кадров

Как указано в параграфе 12.4, пакет содержит 1 или несколько кадров. В этом разделе описан формат и семантика основных типов кадров QUIC.

19.1. Кадр PADDING

Кадр PADDING (тип 0x00) не имеет семантического значения и служит для увеличения размера пакета. Заполнение может применяться для увеличения пакетов Initial до минимально требуемого размера или для защиты от анализа трафика защищённых пакетов.

   PADDING Frame {
     Type (i) = 0x00,
   }

Рисунок 23. Формат кадра PADDING.


Формат кадра PADDING показан на рисунке 23, из которого видно отсутствие в кадре содержимого. Т. е. кадр PADDING содержит лишь байт идентификатора типа.

19.2. Кадр PING

Конечные точки могут применять кадры PING (тип 0x01) для проверки живучести партнёра или его достижимости.

Формат кадра PING показан на рисунке 24, из которого видно отсутствие в кадре содержимого.

   PING Frame {
     Type (i) = 0x01,
   }

Рисунок 24. Формат кадра PING.


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

19.3. Кадр ACK

Получатели передают кадры ACK (тип 0x02 и 0x03) для информирования отправителя о приёме и обработке его пакетов. Кадр ACK включает один или несколько диапазонов ACK Range, указывающих подтверждаемые пакеты. Кадры ACK типа 0x03 содержат также кумулятивный счётчик пакетов QUIC со связанной маркировкой ECN, полученных через соединение к моменту отправки кадра. Реализации QUIC должны обрабатывать оба типа кадров, а при поддержке ECN для передаваемых пакетов им также следует использовать сведения из раздела ECN для поддержки статуса перегрузки.

Подтверждения QUIC являются безотзывными, т. е. после подтверждения пакет считается доставленным, даже если он не указан в будущем кадре ACK. Это отличается от отказа для селективных подтверждений TCP (Selective Acknowledgment или SACK) [RFC2018].

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

Пакеты Version Negotiation и Retry не могут подтверждаться, поскольку у них нет порядкового номера. Вместо кадров ACK для них используются неявные подтверждения в следующем пакете Initial, переданном клиентом.

   ACK Frame {
     Type (i) = 0x02..0x03,
     Largest Acknowledged (i),
     ACK Delay (i),
     ACK Range Count (i),
     First ACK Range (i),
     ACK Range (..) ...,
     [ECN Counts (..)],
   }

Рисунок 25. Формат кадра ACK.


Формат кадра ACK показан на рисунке 25.

Largest Acknowledged

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

ACK Delay

Целое число с переменным размером, указывающее задержку подтверждения в миллисекундах (параграф 13.2.5). Значение декодируется путём умножения поля на 2 в степени, заданной транспортным параметром ack_delay_exponent, переданным отправителем кадра ACK (параграф 18.2). По сравнению с простым заданием задержки целым числом такое кодирование позволяет указать больший диапазон тем же числом битов за счёт снижения точности.

ACK Range Count

Целое число с переменным размером, указывающее количество полей ACK Range в кадре.

First ACK Range

Целое число с переменным размером, указывающее количество непрерывных пакетов, предшествующих подтверждаемому значению Largest Acknowledged. Таким образом, меньший номер, подтверждаемый диапазоном, определяется вычитанием First ACK Range из Largest Acknowledged.

ACK Ranges

Дополнительные диапазоны пропущенных (Gap) и подтверждённых (ACK Range) пакетов (параграф 19.3.1).

ECN Counts

Три значения счётчиков ECN (см. параграф 19.3.2).

19.3.1. Диапазоны ACK

Каждое поле ACK Range состоит из чередующихся значений Gap и ACK Range Length в порядке уменьшения номеров пакетов. Поля ACK Range могут повторяться. Число значений Gap и ACK Range Length определяется полем ACK Range Count. Структура ACK Range показана на рисунке 26.

   ACK Range {
     Gap (i),
     ACK Range Length (i),
   }

Рисунок 26. Диапазоны ACK.


Gap

Целое число переменного размера, указывающее количество последовательных неподтвержденных пакетов перед пакетом с меньшим на 1 номером по сравнению с меньшим из предшествующего ACK Range.

ACK Range Length

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

В полях Gap и ACK Range Length используется относительное кодирование целых чисел для эффективности. Хотя каждое значение является положительным, значения вычитаются так, что в каждом ACK Range описывается диапазон с меньшими номерами. Каждое поле ACK Range подтверждает непрерывный диапазон пакетов, указывая число подтверждённых пакетов, предшествующих большему значению диапазона. Значение 0 указывает, что подтверждается лишь пакет с наибольшим номером. Большие значения ACK Range указывают больший диапазон с соответствующим меньшим значением для наименьшего номера пакета в диапазоне. Таким образом, по большему номеру пакета в диапазоне (largest) меньший (smallest) определяется как smallest = largest — ack_range.

ACK Range подтверждает все пакеты от меньшего до большего номера, включительно. Наибольшее значение для ACK Range определяется путём последовательного вычитания размера всех предшествующих полей ACK Range Length и Gap. Каждое значение Gap указывает диапазон пакетов, которые не подтверждаются. Число пропущенных пакетов на 1 больше значения поля Gap. Поле Gap задаёт наибольший номер пакета для последующего ACK Range выражением largest = previous_smallest — gap — 2. Если какой-либо из рассчитанных номеров имеет отрицательное значение, конечная точка должна генерировать ошибку типа FRAME_ENCODING_ERROR.

19.3.2. ECN Counts

Кадры ACK используют младший бит типа (0x03) для индикации обратной связи ECN и информирования о получении пакетов QUIC с кодами ECN ECT(0), ECT(1), ECN-CE в заголовке IP. Поле ECN присутствует лишь в кадрах ACK типа 0x03. Формат поля показан на рисунке 27.

   ECN Counts {
     ECT0 Count (i),
     ECT1 Count (i),
     ECN-CE Count (i),
   }

Рисунок 27. Формат ECN Counts.


ECT0 Count

Целое число переменного размера — количество пакетов с кодом ECT(0) в пространстве номеров кадра ACK.

ECT1 Count

Целое число переменного размера — количество пакетов с кодом ECT(1) в пространстве номеров кадра ACK.

ECN-CE Count

Целое число переменного размера — количество пакетов с кодом ECN-CE в пространстве номеров кадра ACK.

Счётчики ECN поддерживаются независимо в каждом пространстве порядковых номеров пакетов.

19.4. Кадр RESET_STREAM

Конечная точка применяет кадр RESET_STREAM (тип 0x04) для внезапной остановки передающей части потока. После отправки RESET_STREAM конечная точка прекращает передачу кадров STREAM в указанном потоке. Получатель RESET_STREAM может отбросить любые данные, уже принятые в этом потоке. Принявшая RESET_STREAM конечная точка для потока, который лишь передаёт (send-only), должна прервать соединение с ошибкой STREAM_STATE_ERROR. Формат кадра RESET_STREAM показан на рисунке 28.

   RESET_STREAM Frame {
     Type (i) = 0x04,
     Stream ID (i),
     Application Protocol Error Code (i),
     Final Size (i),
   }

Рисунок 28. Формат кадра RESET_STREAM.


Stream ID

Целое число переменного размера, представляющее идентификатор прерываемого потока.

Application Protocol Error Code

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

Final Size

Целое число переменного размера, указывающее конечный размер потока у отправителя RESET_STREAM в байтах (см. параграф 4.5).

19.5. Кадр STOP_SENDING

Конечная точка использует кадр STOP_SENDING (тип 0x05) для информирования о том, что входящие данные отбрасываются при получении по запросу приложения. STOP_SENDING запрашивает у партнёра прекращение передачи в поток. Кадр STOP_SENDING можно передать для потоков в состоянии Recv или Size Known 9см. параграф 3.2). Получение STOP_SENDING для локально инициированного потока, который ещё не создан, должно считаться ошибкой соединения типа STREAM_STATE_ERROR. Конечная точка, получившая STOP_SENDING для потока, который только принимает (receive-only), должна прервать соединение с ошибкой STREAM_STATE_ERROR. Формат кадра STOP_SENDING показан на рисунке 29.

   STOP_SENDING Frame {
     Type (i) = 0x05,
     Stream ID (i),
     Application Protocol Error Code (i),
   }

Рисунок 29. Формат кадра STOP_SENDING.


Stream ID

Целое число переменного размера, указывающее идентификатор игнорируемого потока.

Application Protocol Error Code

Целое число переменного размера с заданным приложением кодом причины игнорирования потока отправителем (см. параграф 20.2).

19.6. Кадр CRYPTO

Кадр CRYPTO (тип 0x06) служит для передачи сообщений криптографического согласования и может передаваться во всех типах пакетов кроме 0-RTT. Кадр CRYPTO предлагает криптографическому протоколу упорядоченный поток байтов. Функционально кадры CRYPTO идентичны STREAM, но они не включают идентификатор потока, для них не применяется управления потоком данных и в кадрах нет маркеров смещения, размера и конца потока. Формат CRYPTO показан на рисунке 30.

   CRYPTO Frame {
     Type (i) = 0x06,
     Offset (i),
     Length (i),
     Crypto Data (..),
   }

Рисунок 30. Формат кадра CRYPTO.


Offset

Целое число переменного размера — байтовое смещение в потоке для данных в этом кадре CRYPTO.

Length

Целое число переменного размера, указывающее размер поля Crypto Data в этом кадре CRYPTO.

Crypto Data

данные криптографического сообщения.

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

Наибольшее смещение данных, доставляемых в потоке (сумма смещения и размера данных) не может превышать 262-1. Получение кадра сверх этого предела должно считаться ошибкой соединения типа FRAME_ENCODING_ERROR или CRYPTO_BUFFER_EXCEEDED.

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

19.7. Кадр NEW_TOKEN

Сервер передаёт кадр NEW_TOKEN (тип 0x07) для предоставления клиенту маркера, который тот передаёт в заголовке пакета Initial для будущего соединения. Формат кадра NEW_TOKEN показан на рисунке 31.

   NEW_TOKEN Frame {
     Type (i) = 0x07,
     Token Length (i),
     Token (..),
   }

Рисунок 31. Формат кадра NEW_TOKEN.


Token Length

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

Token

Необрабатываемый блок данных (blob), который клиент может указать в будущем пакете Initial. Пустой маркер не допустим и клиент должен считать получение кадра NEW_TOKEN с пустым полем Token ошибкой соединения типа FRAME_ENCODING_ERROR.

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

19.8. Кадр STREAM

Кадры STREAM неявно создают поток и переносят его данные. Поле Type в кадре STREAM принимает форму 0b00001XXX (или набор значений от 0x08 до 0x0f). Три младших бита типа определяют присутствующие в кадре поля.

  • Бит OFF (0x04) в типе кадра указывает наличие поля Offset. При установленном (1) биту поле Offset присутствует, а при сброшенном его нет и данные потока (Stream Data) начинаются со смещения 0 (т. е. кадр содержит первые байты потока или конец пустого потока).

  • Бит LEN (0x02) в типе кадра указывает наличие поля Length. Сброшенный (0) бит говорит, что поля Length нет и поле Stream Data продолжается до конца потока. Установленный (1) бит указывает наличе поля Length.

  • Бит FIN (0x01) указывает, что кадр содержит конец потока. Окончательный размер потока определяет сумма смещения и размера этого кадра.

Конечная точка должна прерывать соединение с ошибкой STREAM_STATE_ERROR при получении кадра STREAM для локально инициированного потока, который ещё не создан, или только передающего потока (send-only). Формат кадра STREAM показан на рисунке 32.

   STREAM Frame {
     Type (i) = 0x08..0x0f,
     Stream ID (i),
     [Offset (i)],
     [Length (i)],
     Stream Data (..),
   }

Рисунок 32. Формат кадра STREAM.


Stream ID

Целое число переменного размера — идентификатор потока (см. параграф 2.1).

Offset

Целое число переменного размера — смещение в потоке данных этого кадра STREAM. Поле присутствует при установленном бите OFF. При отсутствии поля Offset смещение принимается равным 0.

Length

Целое число переменного размера, указывающее размер поля Stream Data в этом кадре STREAM. Поле присутствует при установленном бите LEN. Если LEN = 0, поле Stream Data занимает оставшиеся байты пакета.

Stream Data

Байты указанного потока для доставки.

Когда поле Stream Data имеет размер 0, смещение в кадре STREAM указывает следующий байт, который будет передан. Первый байт потока имеет смещение 0. Наибольшее смещение в потоке (сумма смещения и размера данных) не может быть больше 262-1, поскольку невозможно предоставить кредит управления потоком данных для таких данных. Получение кадра с превышением этого предела должно считаться ошибкой соединения типа FRAME_ENCODING_ERROR или FLOW_CONTROL_ERROR.

19.9. Кадр MAX_DATA

Кадр MAX_DATA (тип 0x10) применяется в управлении потоком данных для указания партнёру максимального объёма данных, которые он может передать в соединении. Формат кадра MAX_DATA показан на рисунке 33.

   MAX_DATA Frame {
     Type (i) = 0x10,
     Maximum Data (i),
   }

Рисунок 33. Формат кадра MAX_DATA.


Maximum Data

Целое число переменного размера — максимальный объем данных (в байтах) для передачи через соединение.

Учитываются все данные, переданные в кадрах STREAM. Сумме окончательных размеров всех потоков, включая потоки в завершающих состояниях, недопустимо превышать значение, анонсированное получателем. Конечная точка должна прерывать соединение с ошибкой FLOW_CONTROL_ERROR при получении данных сверх заданного предела с учётом нарушения запомненных пределов в Early Data (см. параграф 7.4.1).

19.10. Кадр MAX_STREAM_DATA

Кадр MAX_STREAM_DATA (тип 0x11) применяется в управлении потоком данных для указания партнёру максимального объёма данных, которые он может передать в потоке. Кадр MAX_STREAM_DATA можно передавать для потоков в состоянии Recv (см. параграф 3.2). Получение MAX_STREAM_DATA для локально инициированного потока, который ещё не создан, должно считаться ошибкой соединения типа STREAM_STATE_ERROR. Конечная точка, получившая MAX_STREAM_DATA для только принимающего (receive-only) потока, должна прервать соединения с ошибкой STREAM_STATE_ERROR. Формат MAX_STREAM_DATA показан на рисунке 34.

   MAX_STREAM_DATA Frame {
     Type (i) = 0x11,
     Stream ID (i),
     Maximum Stream Data (i),
   }

Рисунок 34. Формат кадра MAX_STREAM_DATA.


Stream ID

Целое число переменного размера — идентификатор потока, на который воздействует кадр.

Maximum Stream Data

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

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

19.11. Кадр MAX_STREAMS

Кадр MAX_STREAMS (тип 0x12 или 0x13) указывает партнёру общее число потоков, которые можно создать. Кадры типа 0x12 относятся к двухсторонним потокам, типа 0x13 — к односторонним. Формат кадров показан на рисунке 35.

   MAX_STREAMS Frame {
     Type (i) = 0x12..0x13,
     Maximum Streams (i),
   }

Рисунок 35. Формат кадра MAX_STREAMS.


Maximum Streams

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

Потери и нарушение порядка могут приводить к получению конечной точкой кадра MAX_STREAMS со значением меньше полученного ранее. Кадры MAX_STREAMS, не увеличивающие предел для потока, должны игнорироваться. Конечной точке недопустимо создавать больше потоков, чем указал партнёр. Например, сервер, получивший для односторонних потоков предел 3, может создать потоки 3, 7 и 11, но не 15. Конечная точка должна прерывать соединение с ошибкой STREAM_LIMIT_ERROR если партнёр превышает заданный предел с учётом нарушения запомненных пределов в Early Data (см. параграф 7.4.1). Отметим, что эти кадры (и соответствующие параметры транспорта) не задают число одновременных потоков. Принимаются во внимание открытые и закрытые потоки.

19.12. Кадр DATA_BLOCKED

Отправителю следует передать кадр DATA_BLOCKED (тип 0x14), когда он хочет передать данные, но управление потоком данных на уровне соединения не позволяет это (см. раздел 4). Кадры DATA_BLOCKED служат входными данными для настройки алгоритмов управления потоком данных (параграф 4.2). Формат кадра показан на рисунке 36.

   DATA_BLOCKED Frame {
     Type (i) = 0x14,
     Maximum Data (i),
   }

Рисунок 36. Формат кадра DATA_BLOCKED.


Maximum Data

Целое число переменного размера — ограничение на уровне соединения, при котором произошла блокировка.

19.13. Кадр STREAM_DATA_BLOCKED

Отправителю следует передать кадр STREAM_DATA_BLOCKED (тип 0x15), когда он хочет передать данные, но управление потоком данных на уровне потока не позволяет это. Этот тип кадров похож на DATA_BLOCKED (параграф 19.12). Конечная точка, получившая STREAM_DATA_BLOCKED для только передающего (send-only) потока, должна прервать соединение с ошибкой STREAM_STATE_ERROR. Формат кадра показан на рисунке 37.

   STREAM_DATA_BLOCKED Frame {
     Type (i) = 0x15,
     Stream ID (i),
     Maximum Stream Data (i),
   }

Рисунок 37. Формат кадра STREAM_DATA_BLOCKED.


Stream ID

Целое число переменного размера — идентификатор потока, заблокированного управлением потоком данных.

Maximum Stream Data

Целое число переменного размера — смещение потока, при котором произошла блокировка.

19.14. Кадр STREAMS_BLOCKED

Отправителю следует передать кадр STREAMS_BLOCKED (тип 0x16 или 0x17), когда он хочет создать поток, но заданное партнёром ограничение не позволяет это (см. параграф 19.11). Кадры типа 0x16 относятся к двухсторонним потокам, типа 0x17 — к односторонним. Кадр STREAMS_BLOCKED не создаёт поток, но информирует партнёра о потребности в новых потоках и достижении заданного им предела. Формат кадра показан на рисунке 38.

   STREAMS_BLOCKED Frame {
     Type (i) = 0x16..0x17,
     Maximum Streams (i),
   }

Рисунок 38. Формат кадра STREAMS_BLOCKED.


Maximum Streams

Целое число переменного размера, указывающее максимальное число потоков соответствующего типа на момент передачи кадра. Это значение не может превышать 260, поскольку невозможно указать идентификатор потока больше 262-1. Приём кадра, указывающего поток с большим номером, должен считаться ошибкой соединения типа STREAM_LIMIT_ERROR или FRAME_ENCODING_ERROR.

19.15. Кадр NEW_CONNECTION_ID

Конечная точка передаёт кадр NEW_CONNECTION_ID (тип 0x18) для предоставления партнёру дополнительных идентификаторов соединения, которые могут служить для предотвращения возможности сопоставлений при переносе соединения (см. параграф 9.5). Формат кадра NEW_CONNECTION_ID показан на рисунке 39.

Sequence Number

Целое число переменного размера — порядковый номер выделенный идентификатору соединения отправителем (параграф 5.1.1).

   NEW_CONNECTION_ID Frame {
     Type (i) = 0x18,
     Sequence Number (i),
     Retire Prior To (i),
     Length (8),
     Connection ID (8..160),
     Stateless Reset Token (128),
   }

Рисунок 39. Формат кадра NEW_CONNECTION_ID.


Retire Prior To

Целое число переменного размера — идентификаторы соединения, которые следует удалить (параграф 5.1.2).

Length

8-битовое целое число без знака, указывающее размер идентификатора соединения. Значения меньше 1 и больше 20 недействительны и должны считаться ошибкой соединения типа FRAME_ENCODING_ERROR.

Connection ID

Идентификатор соединения заданного размера.

Stateless Reset Token

128-битовое значение используемое для сброса без учёта состояния при использовании соответствующего идентификатора соединения (см. параграф 10.3).

Конечной точке недопустимо передавать этот кадр, если она в настоящее время требует от партнёра передачи пакетов с пустым Destination Connection ID. Замена пустого идентификатора соединения непустым и обратно осложняет определение момента смены идентификатора соединения. Конечная точка, передающая пакеты с пустым Destination Connection ID, должна считать получение кадра NEW_CONNECTION_ID ошибкой соединения типа PROTOCOL_VIOLATION.

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

При получении кадра NEW_CONNECTION_ID с ранее заданным идентификатором соединения, но с иным полем Stateless Reset Token, иным значением Sequence Number или порядковым номером, использованным для другого идентификатора соединения конечная точка может считать это ошибкой соединения типа PROTOCOL_VIOLATION.

Поле Retire Prior To применяется к идентификаторам, созданным в процессе организации соединения, и параметру транспорта preferred_address (см. параграф 5.1.2). Значение Retire Prior To должно быть не больше значения поля Sequence Number. Получение Retire Prior To больше Sequence Number должно считаться ошибкой соединения типа FRAME_ENCODING_ERROR. После того, как отправитель указал Retire Prior To, меньшие значения в последующих кадрах NEW_CONNECTION_ID не оказывают влияния. Получатель должен игнорировать поля Retire Prior To, не увеличивающие полученное ранее значение.

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

19.16. Кадр RETIRE_CONNECTION_ID

Конечная точка передаёт кадр RETIRE_CONNECTION_ID (тип 0x19) для указания того, что она больше не будет применять идентификатор соединения, выданный партнёром. Это включает идентификаторы, представленные во время согласования. передача RETIRE_CONNECTION_ID служит также запросом к партнёру на передачу дополнительных идентификаторов соединения на будущее (см. параграф 5.1). Новые идентификаторы могут быть доставлены в кадрах NEW_CONNECTION_ID (параграф 19.15). Удаление идентификатора соединения делает недействительным связанный с ним маркер сброса без учёта состояния. Формат кадра показан на рисунке 40.

   RETIRE_CONNECTION_ID Frame {
     Type (i) = 0x19,
     Sequence Number (i),
   }

Рисунок 40. Формат кадра RETIRE_CONNECTION_ID.


Sequence Number

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

Получение кадра RETIRE_CONNECTION_ID с порядковым номером больше переданных ранее партнёру должно считаться ошибкой соединения типа PROTOCOL_VIOLATION.

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

Конечная точка не может передавать этот кадр, если партнёр предоставил пустой идентификатор соединения. Конечная точка, предоставившая пустой идентификатор соединения, должна считать получение кадра RETIRE_CONNECTION_ID ошибкой соединения типа PROTOCOL_VIOLATION.

19.17. Кадр PATH_CHALLENGE

   PATH_CHALLENGE Frame {
     Type (i) = 0x1a,
     Data (64),
   }

Рисунок 41. Формат кадра PATH_CHALLENGE.


Конечная точка может использовать кадры PATH_CHALLENGE (тип 0x1a) для проверки доступности партнёра и проверки пути при переносе соединения. Формат кадра PATH_CHALLENGE показан на рисунке 41.

Data

8-битовое поле с произвольными данными.

Включение 64 битов энтропии в кадр PATH_CHALLENGE гарантирует, что легче принять кадр, чем угадать значение. Получатель кадра должен генерировать кадр PATH_RESPONSE (параграф 19.18) с тем же значением в поле Data.

19.18. Кадр PATH_RESPONSE

Кадр PATH_RESPONSE (тип 0x1b) передаётся в ответ на PATH_CHALLENGE. Формат кадра показан на рисунке 42.

   PATH_RESPONSE Frame {
     Type (i) = 0x1b,
     Data (64),
   }

Рисунок 42. Формат кадра PATH_RESPONSE.


Если содержимое кадра PATH_RESPONSE не соответствует ранее переданному PATH_CHALLENGE конечная точка может считать это ошибкой соединения типа PROTOCOL_VIOLATION.

19.19. Кадр CONNECTION_CLOSE

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

   CONNECTION_CLOSE Frame {
     Type (i) = 0x1c..0x1d,
     Error Code (i),
     [Frame Type (i)],
     Reason Phrase Length (i),
     Reason Phrase (..),
   }

Рисунок 43. Формат кадра CONNECTION_CLOSE.


Error Code

Целое число переменного размера — код причины закрытия соединения. CONNECTION_CLOSE типа 0x1c использует коды из пространства, определённого в параграфе 20.1, CONNECTION_CLOSE типа 0x1d — определённые прикладным протоколом (см. параграф 20.2).

Frame Type

Целое число переменного размера — тип вызвавшего ошибку кадра. Значение 0 (эквивалентное указанию кадра PADDING) служит для неизвестных типов кадров. Определяемый приложением кадр CONNECTION_CLOSE (тип 0x1d) не использует это поле.

Reason Phrase Length

Целое число переменного размера, указывающее размер объяснения причины в байтах. Поскольку кадр CONNECTION_CLOSE нельзя разделить между пакетами, ограничения на размер пакетов влияют на это поле.

Reason Phrase

Диагностические сведения о причине закрытия. Поле может быть пустым, если отправитель счёл нужным предоставить лишь значение Error Code. В поле следует указывать строку в кодировке UTF-8, хотя в кадре нет информации (такой, как тег языка).

Определяемый приложением вариант CONNECTION_CLOSE (тип 0x1d) может передаваться лишь в кадрах 0-RTT или 1-RTT (см. параграф 12.5). При желании приложения прервать соединение в процессе согласования конечная точка может передать CONNECTION_CLOSE типа 0x1c с кодом APPLICATION_ERROR в пакете Initial или Handshake.

19.20. Кадр HANDSHAKE_DONE

Сервер использует кадр HANDSHAKE_DONE (тип 0x1e) для подтверждения согласования клиенту. Кадр HANDSHAKE_DONE не имеет содержимого, как показано на рисунке 44.

   HANDSHAKE_DONE Frame {
     Type (i) = 0x1e,
   }

Рисунок 44. Формат кадра HANDSHAKE_DONE.


Кадр HANDSHAKE_DONE может передавать только сервер. Серверам недопустимо передавать HANDSHAKE_DONE до завершения согласования. Приём кадра HANDSHAKE_DONE сервером должен считаться ошибкой соединения типа PROTOCOL_VIOLATION.

19.21. Кадры расширения

Кодирование кадров QUIC не описывает себя, поэтому конечной точке нужно понимать синтаксис всех кадров для успешной обработки пакетов. Это позволит эффективно декодировать кадры, но конечная точка не сможет передать кадры, которые неизвестны партнёру. Расширение QUIC, желающее применять кадры нового типа, должно сначала обеспечить понимание этого типа партнёрами. Конечная точка может использовать транспортный параметр для индикации поддержки расширенных типов.

Расширения, меняющие или замещающие базовую функциональность протокола (включая типы кадров), сложно объединить с другими расширениями, которые меняют или замещают те же функции, пока поведение такой комбинации не задано явно. Таким расширениям следует определять их взаимодействие с другими расширениями, меняющими те же компоненты протокола. Для кадров расширения должен обеспечиваться контроль перегрузки и они должны вызывать передачу кадров ACK. Исключением являются расширения кадров, дополняющие или заменяющие кадры ACK. Кадры расширения не включаются в управление потоком данных, пока они не указаны в расширении.

Для управления назначением новых типов кадров служит реестр IANA, описанный в параграфе 22.4.

20. Коды ошибок

Коды транспортных ошибок QUIC и ошибок приложение представляются 62-битовыми целыми числами без знака.

20.1. Коды транспортных ошибок

В этом разделе приведён список ошибок транспорта QUIC, которые могут указываться в кадрах CONNECTION_CLOSE типа 0x1c. Эти ошибки относятся к соединению в целом.

NO_ERROR (0x00)

Конечная точка использует этот код с CONNECTION_CLOSE для информирования о внезапном закрытии соединения без ошибок.

INTERNAL_ERROR (0x01)

Внутренняя ошибка конечной точки, препятствующая работе соединения.

CONNECTION_REFUSED (0x02)

Сервер отверг новое соединение.

FLOW_CONTROL_ERROR (0x03)

Конечная точка получила больше данных, чем задано анонсированным пределом (см. раздел 4).

STREAM_LIMIT_ERROR (0x04)

Конечная точка получила кадр для идентификатора потока, выходящего за пределы ограничения для соответствующего типа потоков.

STREAM_STATE_ERROR (0x05)

Конечная точка получила кадр для потока, находящегося в состоянии, для которого такой кадр не разрешён (см. раздел 3).

FINAL_SIZE_ERROR (0x06)

(1) Конечная точка получила кадр STREAM с данными, выходящими за пределы ранее согласованного общего размера. (2) Конечная точка получила кадр STREAM или RESET_STREAM, содержащий общий размер, который меньше объёма уде принятых в потоке данных. (3) Конечная точка получила кадр STREAM или RESET_STREAM, содержащий общий размер данных, отличающийся от уже согласованного.

FRAME_ENCODING_ERROR (0x07)

Конечная точка получила кадр с ошибкой формата, например, кадр неизвестного типа или кадр ACK, в котором диапазон подтверждения больше, нежели может перенести остальная часть пакета.

TRANSPORT_PARAMETER_ERROR (0x08)

Конечная точка получила транспортные параметры с ошибочным форматом, включая недействительное значение, пропуск обязательного параметра, запрещённый транспортный параметр, или вызвавшие иную ошибку.

CONNECTION_ID_LIMIT_ERROR (0x09)

Число представленных партнёром идентификаторов соединения превышает анонсированное значение active_connection_id_limit.

PROTOCOL_VIOLATION (0x0a)

Конечная точка обнаружила протокольную ошибку, для которой не задано кода.

INVALID_TOKEN (0x0b)

Сервер получил от клиента пакет Initial с недействительным полем Token.

APPLICATION_ERROR (0x0c)

Закрытие соединения, вызванное приложением или прикладным протоколом.

CRYPTO_BUFFER_EXCEEDED (0x0d)

Конечная точка получила в кадрах CRYPTO объем данных, который она не может буферизовать.

KEY_UPDATE_ERROR (0x0e)

Конечная точка обнаружила ошибку при обновлении ключей (см. раздел 6 в [QUIC-TLS]).

AEAD_LIMIT_REACHED (0x0f)

Конечная точка достигла предела защиты конфиденциальности или целостности используемого в соединении алгоритма AEAD.

NO_VIABLE_PATH (0x10)

Конечная точка определила, что путь через сеть не может поддерживать QUIC. Получение конечной точкой кадра CONNECTION_CLOSE с таким кодом маловероятно за исключением случая, когда путь не имеет достаточного MTU.

CRYPTO_ERROR (0x0100-0x01ff)

Отказ при криптографическом согласовании. Диапазон из 256 значений зарезервирован для кодов ошибок используемого криптографического согласования. Коды ошибок при криптографическом согласовании TLS приведены а параграфе [QUIC-TLS].

Регистрация новых кодов ошибок рассмотрена в параграфе 22.5.

При определении кодов применялось несколько принципов. Для ошибочных состояний, которые могут требовать конкретного действия на стороне получателя, выделены уникальные коды. Для ошибок, представляющих общие условия, заданы конкретные коды. При отсутствии какого-либо из этих условий коды ошибок служат для идентификации базовой функции стека, такой как управление потоком данных или обработка параметров транспорта. Ошибки общего типа указывают случаи, когда реализация не может или не хочет указать конкретную ошибку.

20.2. Коды ошибок прикладного протокола

Поддержка кодов ошибок прикладного протокола оставлена этим протоколам. Коды ошибок прикладного протокола используются в кадрах RESET_STREAM (параграф 19.4), STOP_SENDING (параграф 19.5) и CONNECTION_CLOSE типа 0x1d (параграф 19.19).

21. Вопросы безопасности

Целью QUIC является обеспечение защищённых транспортных соединений. В параграфе 21.1 представлен обзор свойств защиты, а далее обсуждаются ограничения и предостережения, связанные с этими свойствами, включая описания известных атак и мер противодействия.

21.1. Обзор защитных свойств

Полный анализ безопасности QUIC выходит за рамки этого документа. В этом параграфе приведено неформальное описание свойств защиты в помощь разработчикам при анализе протокола.

QUIC предполагает модель угроз, описанную в [SEC-CONS], и обеспечивает защиту от соответствующих модели атак. Атаки делятся на активные и пассивные. В пассивных атаках у злоумышленников имеется возможность считывать пакеты из сети, а в активных им доступна также запись. Однако в пассивной атаке может участвовать злоумышленник, способный менять маршрутизацию или иначе влиять на пути прохождения пакетов, составляющих соединение.

Атакующие делятся на размещённых в пути доставки пакетов и вне этого пути. Расположенные на пути злоумышленники могут читать, изменять или удалять любой наблюдаемый пакет так, что он не достигнет адресата. Атакующие извне пути могут наблюдать пакеты, но не способны воспрепятствовать их доставке. Оба типа атакующих могут также передавать произвольные пакеты. Эта классификация отличается от принятой в параграфе 3.5 [SEC-CONS] тем, что находящийся вне пути злоумышленник может наблюдать пакеты.

Свойства согласования, защищённых пакетов и переноса соединений рассматриваются отдельно.

21.1.1. Согласование

Согласование QUIC (handshake) включает согласование TLS 1.3 и наследует криптографические свойства, описанные в Приложении E.1 к [TLS13]. Многие из свойств защиты QUIC зависят от согласования TLS, обеспечивающего эти свойства. Любая атака на TLS может влиять на QUIC.

Любая атака на согласование TLS, ставящая под угрозу секретность или уникальность сеансовых ключей или аутентификацию участвующих партнёров, влияет на предоставляемые QUIC другие гарантии безопасности, зависящие от этих ключей. Например, перенос соединения (раздел 9) зависит от эффективности защиты конфиденциальности как для согласования ключей с использованием согласования TLS, так и для защиты пакетов QUIC, чтобы избежать возможности сопоставления по путям через сеть.

Атака на целостность согласования TLS может позволить злоумышленнику повлиять на выбор прикладного протокола или версии QUIC.

В дополнение к предоставляемым TLS свойствам согласование QUIC обеспечивает некоторую защиту от DoS-атак на согласование.

21.1.1.1. Антиусиление

Для проверки того, что заявивший адрес объект способен принимать пакеты по этому адресу выполняется проверка адресов (раздел 8). Эта проверка ограничивает возможности организации атак с усилением, когда злоумышленник может наблюдать за пакетами. До проверки адреса конечные точки ограничены в возможности передавать по нему и не могут отправить по этому адресу данные, объем которых превышает троекратный размер принятых оттуда данных.

Примечание. Предел антиусиления применяется лишь при ответе конечной точки на пакеты с непроверенного адреса. Это ограничение не используется для клиентов, организующих новое соединение или пытающихся перенести соединение.

21.1.1.2. DoS на стороне сервера

Расчёт первой отправки с сервера для полного согласования может быть затратным, включая расчёт подписи и обмен ключами. Для предотвращения DoS-атак, потребляющих ресурсы сервера, пакеты Retry обеспечивают недорогой механизм обмена маркерами, позволяющий серверу проверить IP-адрес клиента до выполнения затратных расчётов за счёт одного дополнительного кругового обхода. После успешного согласования серев может выпустить для клиента новые маркеры, позволяющие тому организовать новое соединение без дополнительных издержек.

21.1.1.3. Прерывание согласования в пути

Злоумышленник на пути или вне его может вызвать отказ согласования, подменив или разогнав пакеты Initial. После обмена действительными пакетами Initial последующие пакеты Handshake защищаются ключами Handshake и находящийся на пути злоумышленник не может вызвать сбой согласования иной, нежели отбрасывание пакетов, вынуждающее прекратить попытку. Такой атакующий может также заменить адреса в пакетах любой из сторон, вынуждая клиента или сервер видеть некорректный адрес удалённой точки. Такая атака неотличима от преобразований NAT.

21.1.1.4. Согласование параметров

Согласование целиком защищено криптографически, причём пакеты Initial шифруются зависящими от версии ключами, а Handshake и последующие пакеты — ключами, выведенными из обмена TLS. Кроме того, согласование параметров охватывается TLS и для него обеспечивается защита целостности как для обычного согласования TLS. Атакующий может видеть транспортные параметры клиента (если известна зависимая от версии затравка), но не может видеть транспортных параметров сервера и влиять на согласование параметров.

Идентификаторы соединений не шифруются, но охватываются защитой целостности во всех пакетах.

Эта версия QUIC не включает механизма согласования версий и реализации несовместимых версий просто не смогут организовать соединение.

21.1.2. Защищённые пакеты

Для защиты пакетов (параграф 12.1) применяется аутентифицированное шифрование всех пакетов, кроме Version Negotiation, хотя пакеты Initial и Retry имеют ограниченную защиту по причине использования зависимого от версии ключевого материала (см. [QUIC-TLS]). В этом параграфе рассмотрены пассивные и активные атаки на защищённые пакеты.

Атакующие на пути и вне его могут организовать пассивную атаку с сохранением наблюдаемых пакетов для последующего взлома защиты. Это возможно для любого наблюдателя любого пакета в сети.

Злоумышленник, внедряющий пакеты, не имея возможности наблюдать действительные пакеты в соединении, скорей всего не добьётся успеха, поскольку защита гарантирует возможность создания действительных пакетов лишь конечными точками, владеющими ключевым материалом, установленным в процессе согласования (см. раздел 7 и параграф 21.1.1). Точно так же активный атакующий, который наблюдает пакеты и пытается внедрить новые данные или изменить имеющиеся, не сможет создать пакеты, которые принимающая конечная точка сочтёт действительными (кроме пакетов Initial).

Атаки с подменой, где активный злоумышленник переписывает незащищённые части пакета, который он пересылает или внедряет (такие как адрес отправителя или получателя), будут оказывать влияние лишь в том случае, когда злоумышленник может пересылать пакеты исходной точке. Защита пакетов гарантирует, что возможность обработка лишь в конечной точке, выполнившей согласование, а недействительные пакеты игнорируются такими точками.

Атакующий может также изменить границы между пакетами и дейтаграммами UDP, вызывая объединение множества пакетов в одну дейтаграмму или разделение объединённых пакетов на несколько дейтаграмм. Помимо дейтаграмм с пакетами Initial, которые требуют заполнения, смена размещения пакетов в дейтаграммах не оказывает функционального влияния на соединение, хотя может изменить характеристики производительности.

21.1.3. Перенос соединения

Перенос соединения (раздел 9) позволяет конечным точка менять IP-адреса и порты на нескольких путях, используя в каждый момент один путь для передачи и приёма кадров, не являющихся зондами. Проверка пути (параграф 8.2) устанавливает, что партнёр хочет и может принимать пакеты, переданные по конкретному пути. Это помогает снизить влияние фиктивных адресов путём ограничения числа пакетов, передаваемых по такому адресу. В этом параграфе рассмотрены свойства защиты от разных типов DoS-атак при переносе соединения.

21.1.3.1. Активные атаки в пути

Атакующий, способный воспрепятствовать доставке наблюдаемого им пакета предусмотренному получателю, считается находящимся на пути. При наличии злоумышленника между клиентом и сервером, конечным точкам приходится передавать через него пакеты для соединения по данному пути. Находящийся на пути атакующим может:

  • просматривать пакеты;

  • изменять заголовки IP и UDP;

  • внедрять свои пакеты;

  • задерживать пакеты;

  • менять порядок пакетов;

  • отбрасывать пакеты;

  • расщеплять и объединять дейтаграммы по границам пакетов.

Однако он не может менять аутентифицируемые части пакетов так, чтобы получатель воспринял пакет.

Размещённый на пути атакующий имеет возможность менять наблюдаемые пакеты, однако изменение аутентифицируемой части пакета приведёт к его отбрасыванию получателем как недействительного, поскольку данные (payload) в пакете аутентифицируются и шифруются.

QUIC пытается ограничить возможности расположенного на пути злоумышленника несколькими способами.

  1. Атакующий может препятствовать использованию пути для соединения, вызывая отказ, если нет возможности организовать другой путь мимо злоумышленника. Действия атакующего могут включать отбрасывание всех пакетов, их изменение, препятствующее расшифровке, а также иные воздействия.

  2. Атакующий может препятствовать переходу на новый путь, который также проходит через него, вызывая отказ при проверке нового пути.

  3. Атакующий не может препятствовать переходу клиента на новый путь, не проходящий через него.

  4. Злоумышленник может снизить пропускную способность, задерживая или отбрасывая пакеты.

  5. Атакующие не может заставить конечную точку воспринимать пакеты, в которых он изменил аутентифицируемую часть.

21.1.3.2. Активные атаки извне пути

Злоумышленник вне пути не находится непосредственно на пути между клиентом и сервером, но может получать копии всех или части пакетов, передаваемых между ними, а также передавать копии этих пакетов любой из конечных точек. Атакующий может:

  • просматривать пакеты;

  • внедрять новые пакеты;

  • менять порядок внедряемых пакетов.

Атакующий не способен:

  • менять переданные конечными точками пакеты;

  • задерживать пакеты;

  • отбрасывать пакеты;

  • менять порядок исходных пакетов.

Расположенный вне пути злоумышленник может изменять полученные копии пакетов и снова внедрять их в сеть, возможно с фиктивными адресами отправителя и получателя. В этом обсуждении предполагается, что атакующий может внедрять в сеть изменённые копии пакетов, которые придут к получателю раньше оригинала, наблюдаемого злоумышленником. Иными словами, атакующий может «выиграть» соперничество с легитимными пакетами между конечными точками, что может привести к игнорированию исходного пакета получателем. Предполагается также, что у злоумышленника достаточно ресурсов для воздействия на состояние NAT. В частности, он может вынудить конечную точку потерять свою привязку NAT и захватить порт для своего трафика. QUIC пытается ограничить возможности расположенного вне пути злоумышленника.

  1. Атакующий может «разгонять» пакеты и пытаться стать «ограниченным» злоумышленником на пути.

  2. Атакующий может имитировать успешную проверку пути для пересылаемых пакетов с адресом отправителя, указанным как злоумышленник вне пути, если он способен обеспечить лучшее соединение между клиентом и сервером.

  3. Злоумышленник не может закрыть соединение после завершения согласования.

  4. Злоумышленник не может вызвать перенос соединения на новый путь, если он не может наблюдать этот путь.

  5. Атакующий может стать ограниченным злоумышленником на пути в процессе переноса на новый путь, который также не проходит через него.

  6. Атакующий может стать ограниченным злоумышленником на пути, воздействуя на общее состояние NAT так, чтобы отправлять пакеты на сервер с того же адреса и порта, которые изначально использовал клиент.

21.1.3.3. Ограниченные активные атаки на пути

Ограниченным атакующим на пути является расположенный вне пути злоумышленник, который предлагает улучшенную маршрутизацию пакетов, дублируя и пересылая исходные пакеты между клиентом и сервером так, что копии приходят раньше оригиналов и последние отбрасываются получателем.

Ограниченный атакующий на пути отличается от обычного злоумышленника, находящегося на пути, тем, что он не находится на исходном пути между конечными точками и пакеты от отправителя по-прежнему приходят к адресату. Это означает, что будущая неспособность маршрутизировать копии быстрее прохождения оригиналов по исходному пути не будет препятствовать доставке пакетов получателю.

Ограниченный атакующий на пути может:

  • просматривать пакеты;

  • внедрять свои пакеты;

  • менять нешифрованные заголовки пакетов;

  • изменять порядок пакетов.

Однако такой злоумышленник не способен:

  • задерживать пакеты так, чтобы они приходили позже пакетов по исходному пути;

  • отбрасывать пакеты;

  • менять аутентифицированные и шифрованные части пакета, заставляя получателя воспринимать их.

Ограниченный атакующий на пути может задерживать пакеты лишь до момента, когда исходные пакеты прибудут раньше дубликатов, а это значит, что он не может предлагать маршрутизацию с задержкой больше чем на исходном пути. Если такой злоумышленник отбрасывает копии пакетов, исходные пакеты все равно попадают к получателю. QUIC пытается ограничить возможности ограниченного атакующего на пути.

  1. Атакующий не может вынудить соединение закрыться после завершения согласования.

  2. Атакующий не может вынудить бездействующее соединение закрыться, если клиент первым возобновит работу.

  3. Атакующий не может вынудить бездействующее соединение казаться потерянным, если сервер первым возобновит работу.

Отметим, что такие же гарантии обеспечиваются для любого NAT по тем же причинам.

21.2. DoS-атаки на согласование

Как шифрованный транспорт с аутентификацией, QUIC обеспечивает ряд средств защиты от атак типа «отказ в обслуживании» (DoS). После завершения криптографического согласования конечные точки QUIC отбрасывают большинство пакетов, которые не аутентифицированы, существенно ограничивая возможности атакующих нарушить работу имеющихся соединения.

После организации соединения конечные точки QUIC могут воспринимать некоторые неаутентифицированные пакеты ICMP (см. параграф 14.2.1), но использование таких пакетов очень ограничено. Единственный другой тип пакета, воспринимаемый конечной точкой, — это пакет сброса без учёта состояния (параграф 10.3), в котором используется маркер, сохраняемый в секрете до его применения.

В процессе создания соединения QUIC обеспечивает лишь защиту от атак извне пути через сеть. Все пакеты QUIC содержат подтверждение того, что получателю видел предыдущий пакет от партнёра.

Адрес нельзя сменить в процессе согласования, поэтому конечная точка может отбрасывать пакеты, полученные по другому пути через сеть.

Поля Source Connection ID и Destination Connection ID служат основным средством защиты от атак извне пути в процессе согласования (см. параграф 8.1). Они должны соответствовать установленным партнёром значениям. За исключением Initial и Stateless Resets, конечная точка воспринимает лишь пакеты с полем Destination Connection ID, соответствующим значению, которое конечная точка выбрала раньше. Это единственная защита для пакетов Version Negotiation.

Поле Destination Connection ID в пакете Initial клиент выбирает как непредсказуемое, что служит дополнительной цели. Пакеты криптографического согласования защищены с использованием ключа, выведенного из этого идентификатора соединения и затравки, определяемой версией QUIC. Это позволяет конечной точке использовать один процесс для аутентификации получаемых пакетов в процессе и по завершении криптографического согласования. Не прошедшие аутентификацию пакеты отбрасываются. Такая защита пакетов обеспечивает уверенность в том, что отправитель пакета видел пакет Initial и понял его.

Эта защита не эффективна против злоумышленников, способных получать пакеты QUIC до организации соединения. Такой атакующий потенциально может отправить пакеты, которые будут восприняты конечными точками QUIC. Эта версия QUIC пытается обнаруживать такие атаки, но предполагает, что конечные точки не смогут организовать соединение в таких случаях. По большей части протокол криптографического согласования [QUIC-TLS] отвечает за обнаружение подделок в процессе согласования.

Конечным точкам разрешено применять другие методы обнаружения и восстановления при вмешательстве в согласование. Недействительные пакеты можно обнаруживать и отбрасывать другими методами и данный документ не задаёт конкретный метод.

21.3. Атаки с усилением

Атакующий может получить маркер проверки адреса (раздел 8) от сервера, а затем освободить использованный для этого адрес IP. Позднее он может инициировать соединение 0-RTT с сервером, подставив тот же адрес, который фактически может принадлежать другой конечной точке (жертве). После этого атакующий потенциально может вынудить сервер передать этой жертве данные в размере начального окна перегрузки. Серверам следует обеспечивать смягчение таких атак, ограничивая срок действия маркеров проверки адреса (см. параграф 8.1.3).

21.4. Атаки с избыточными подтверждениями

Конечная точка, подтверждающая непринятые пакеты, может заставит контроллер перегрузок разрешить передачу со скоростью, превосходящей возможности сети. Конечная точка может пропускать номера для передаваемых пакетов с целью обнаружить такое поведение. Затем конечная точка может немедленно закрыть соединение с ошибкой типа PROTOCOL_VIOLATION (см. параграф 10.2).

21.5. Атаки с подменой запросов

Атака с подделкой запроса происходит, когда конечная точка вынуждает партнёра ввести запрос к жертве. Контролируемый данной точкой. Такие атаки направлены на получение злоумышленником доступа к возможностям своего партнёра, которые без этого могут быть недоступны атакующему. Для сетевых протоколов атаки с подменой запроса часто применяются для использования неявного предоставления жертвой полномочий партнёру злоумышленника на основе его местоположения в сети.

Для эффективной подделки запросов атакующему нужна возможность влиять на то, какие пакеты и куда отправляет партнёр. Если злоумышленник может нацелить уязвимую службу с контролируемым содержимым (payload), эта служба может выполнить действия, которые невольный атакующий выполнит для злоумышленника. Например, подделка межсайтовых запросов [CSRF] в Web заставляет клиента выдавать запросы, включающие cookie проверки полномочий [COOKIE], что открывает одному сайту доступ к информации и действиям, разрешённым для другого сайта.

Поскольку QUIC работает по протоколу UDP, основная проблема атак заключается в том, что злоумышленник может выбрать адрес, на который его партнёр будет передавать дейтаграммы UDP, и контролировать незащищённое содержимое пакетов. Поскольку большая часть данных, отправляемых конечными точками QUIC, защищена, это включает контроль над шифрованными данными. Атака будет успешной, если злоумышленник может вынудить партнёра передать дейтаграмму UDP хосту, который выполнит некое действие в зависимости от содержимого дейтаграммы.

В этом параграфе описаны возможные способы использования QUIC для атак с поддельными запросами. Описаны также ограниченные меры противодействия, которые могут быть реализованы конечными точками QUIC. Эти меры ослабления могут применяться в одностороннем порядке реализацией или развёртыванием QUIC без принятия каких-либо мер у потенциальных жертв. Однако этих мер может быть недостаточно, если службы на основе UD не проверяют полномочия должным образом.

Поскольку атака с переносом, описанная в параграфе 21.5.4, является достаточно мощное и для неё нет достаточных мер противодействия, реализациям серверов QUIC следует предполагать, что злоумышленники могут заставить их генерировать произвольное содержимое UDP для произвольных получателей. Серверы QUIC не следует развёртывать в сети без фильтрации на входе [BCP38] и с конечными точками UDP без адекватной защиты.

Хотя в общем случае невозможно гарантировать, что клиенты не будут совмещены с уязвимыми конечными точками, эта версия QUIC не позволяет серверам мигрировать для предотвращения атак с ложным переносом на клиентов. Любое будущее расширение, которое разрешит миграцию серверов, должно обеспечивать меры защиты от таких атак.

21.5.1. Возможности управления для конечных точек

QUIC открывает для злоумышленников некоторые возможности влияния на отправку партнёром дейтаграмм UDP:

  • при организации соединения (раздел 7) сервер может указать, куда клиенту следует передавать дейтаграммы (например, путём заполнения записей DNS);

  • с помощью предпочтительных адресов (параграф 9.6) сервер может выбирать, куда клиенту следует передавать дейтаграммы;

  • с помощью фиктивного переноса соединения (параграф 9.3.1) клиент может использовать обмену адреса отправителя для выбора адреса, по которому сервер будет передавать последующие дейтаграммы;

  • обманные пакеты могут вынудить сервер передать пакет Version Negotiation (параграф 21.5.5).

Во всех перечисленных случаях злоумышленник может вынудить партнёра передавать дейтаграммы жертве, которая может не понимать QUIC, т. е. пакеты будут передаваться до проверки адреса (см. раздел 8).

За пределами защищённой части пакета QUIC предоставляет конечной точке несколько возможностей управления содержимым дейтаграмм UDP, передаваемых партнёром. Поле Destination Connection ID предоставляет прямой контроль над байтами в ранних пакетах, передаваемых партнёром (см. параграф 5.1). Поле Token в пакетах Initial открывает серверу контроль над другими байтами в пакетах Initial (см. параграф 17.2.2).

В данной версии QUIC нет мер предотвращения косвенного контроля над защищёнными частями пакетов. Необходимо учитывать возможность конечной точки контролировать содержимое кадров, передаваемых партнёром, особенно для кадров с данными приложения, таких как STREAM. Хотя это в некоторой степени зависит от прикладного протокола, во многих вариантах использования протоколов некоторый контроль возможен. Когда у злоумышленника есть доступ к ключам защиты пакетов, он вероятно сможет угадать, как партнёр будет шифровать последующие пакеты. Для успешного контроля над содержимым дейтаграмм атакующему нужна лишь возможность предсказать номер пакета и размещение кадров в пакете с той или иной достоверностью.

В этом параграфе предполагается, что ограничение контроля над содержимым дейтаграмм неосуществимо. В последующих параграфах основное внимание уделяется ограничению возможностей подделки запросов с помощью дейтаграмм, передаваемых до проверки адреса.

21.5.2. Обманный запрос в клиентских пакетах Initial

Злоумышленник, действующий как сервер, может выбрать IP-адрес и порт, для которых он анонсирует свою доступность, поэтому пакеты Initial от клиента считаются доступными для использования в этом типе атак. Неявная проверка адреса в согласовании (handshake) гарантирует для нового соединения, что клиент не будет передавать другие типы пакетов адресату, которые не понимает QUIC или не желает воспринимать соединения QUIC.

Защита пакетов Initial (параграф 5.2 в [QUIC-TLS]) осложняет для серверов контроль над содержимым пакетов Initial, передаваемых клиентами. Выбор клиентом непредсказуемого значения Destination Connection ID не позволяет серверам контролировать какую-либо шифрованную часть пакетов Initial от клиента. Однако поле Token открыто для сервера и позволяет ему использовать клиентов для организации атак с обманными запросами. Использование маркеров, передаваемых в кадрах NEW_TOKEN (параграф 8.1.3) открывает лишь возможность подделки запроса в процессе организации соединения. Однако клиенты не обязаны использовать кадр NEW_TOKEN. Атаки с поддельными запросами на основе поля Token можно предотвратить, если клиенты передают пустое поле Token при изменении адреса сервера с момента получения кадра NEW_TOKEN. Клиенты могут избегать применения NEW_TOKEN, если адрес сервера изменился. Однако исключение поля Token может негативно влиять на производительность. Серверы могут на основе поля NEW_TOKEN разрешать передачу данных в объёме, превышающем утроенный объем принятых данных (см. параграф 8.1). В частности, это влияет на запросы клиентом дополнительных данных от сервера с использованием 0-RTT.

Передача пакета Retry (параграф 17.2.5) позволяет серверу изменить поле Token. После отправки Retry сервер может также контролировать поле Destination Connection ID в последующих пакетах Initial от клиента. Это также может открыть опосредованный контроль над шифрованным содержимым пакетов Initial. Однако передача Retry подтверждает адрес сервера, предотвращая тем самым использование последующих пакетов Initial для обманных запросов.

21.5.3. Обманный запрос с предпочтительным адресов

Серверы могут указывать предпочтительный адрес, на который клиенты переходят после подтверждения согласования (см. параграф 9.6). Поле Destination Connection ID в пакетах от клиента по предпочтительному адресу можно использовать для обманных запросов. Клиенту недопустимо передавать не являющиеся зондами кадры по предпочтительному адресу до его проверки (см. раздел 8). Это существенно снижает возможности контроля сервера над шифрованными частями дейтаграмм. Этот документ не предлагает дополнительных мер противодействия, связанных с использованием предпочтительных адресов, которые могут быть реализованы конечными точками. Базовые меры из параграфа 21.5.6 могут служить для смягчения атак.

21.5.4. Обманный запрос с фиктивным переносом

Клиент может представить фиктивный адрес отправителя как часть переноса соединения, чтобы вынудить сервер отправлять дейтаграммы по этому адресу. Поле Destination Connection ID во всех пакетах, которые сервер после этого будет передавать по фиктивному адресу, можно использовать для обманных запросов. Клиент может также влиять на шифрованные данные.

Сервер, который до проверки адреса отправляет по нему лишь пакеты зондирования (параграф 9.1), даст злоумышленнику лишь ограниченный контроль над шифрованной частью дейтаграмм. Однако (в частности, при перестройке NAT) это может негативно влиять на производительность. Если сервер передаёт кадры с данными приложения, атакующий сможет контролировать большую часть их содержимого.

Этот документ не предлагает дополнительных мер противодействия, которые могут быть реализованы конечными точками, сверх описанных в параграфе 21.5.6. Однако меры предотвращения подмены адресов на сетевом уровне (в частности, фильтрация на входе [BCP38]) обеспечивают защиту от атак с подменой адресов из внешней сети.

21.5.5. Обманный запрос с Version Negotiation

Клиенты, способные предоставить фиктивный адрес отправителя, могут вынудить сервер передать по этому адресу пакет Version Negotiation (параграф 17.2.1). Отсутствие ограничения размера идентификатора соединения в пакетах неизвестной версии увеличивает объем данных, контролируемых клиентом в дейтаграммах. Первый байт пакета не находится под контролем клиента, а следующие 4 байта содержат нули, но клиент может контролировать 512 байтов, начиная с пятого. Для противодействия таким атакам нет мер, сверх указанных в параграфе параграф 21.5.6. Фильтрация на входе [BCP38] будет работать.

21.5.6. Базовые меры противодействия обманным запросам

Наиболее эффективной защитой от атак с подменой запросов является добавление строгой аутентификации в уязвимые службы. Одно это не всегда попадает в зону контроля развёртывания QUIC. В этом параграфе описаны некоторые шаги, которые конечные точки могут предпринять в одностороннем порядке. Эти шаги являются дискреционными, поскольку в зависимости от обстоятельств могут препятствовать легитимному использованию.

Услуги, предоставляемые через loopback-интерфейс, часто не имеют должной аутентификации. Конечные точки могут предотвращать попытки соединения или переход на loopback-адрес. Конечным точкам не следует разрешать переход на loopback-адрес, если те же услуги были ранее доступны на другом интерфейсе или адрес был предоставлен службой на адресе, не относящемся к loopback. Конечные точки, зависящие от этих возможностей, могут предлагать вариант отключения защиты.

Конечные точки могут считать замену адреса на link-local [RFC4291] или адрес из частного диапазона [RFC1918] вместо глобального, уникального локально [RFC4193] или публичного (non-private) адреса как возможную попытку обманного запроса. Конечные точки могут полностью отказаться от использования таких адресов, но это связано с риском нарушения легитимных вариантов работы. Конечным точкам не следует использовать адрес, пока нет конкретных сведений о сети, указывающих, что передача дейтаграмм по непроверенным адресам из данного диапазона безопасна.

Конечные точки могут снизить риск обманных запросов, не включая значений из кадров NEW_TOKEN в пакеты Initial или передавая лишь пробные пакеты до завершения проверки адреса. Отметим, что это не препятствует использованию для атак поля Destination Connection ID.

Предполагается, что у конечных точек нет конкретной информации о местоположении серверов, которые могут быть уязвимы для атак с подменой запросов. Однако со временем может появиться возможность идентифицировать конкретные порты UDP, являющиеся целями атак, или базовые шаблоны дейтаграмм, используемые в атаках. Конечные точки могут избегать отправки дейтаграмм в такие порты или не передавать дейтаграмм с такими шаблонами до проверки адреса получателя. Конечные точки могут отзывать идентификаторы соединения с шаблонами, использование которых заведомо связано с проблемами.

Примечание. Изменение конечных точек для применения этих средств защиты более эффективно, чем развёртывание сетевых средств защиты, поскольку от конечных точек не требуется выполнение дополнительной обработки при передаче по непроверенным адресам.

21.6. Slowloris-атаки

Атаки, обычно называемые Slowloris [SLOWLORIS], пытаются сохранить множество открытых соединений с целевой конечной точкой как можно дольше. Такие атаки могут быть нацелены на конечную точку QUIC с минимальной активностью, требуемой для сохранения соединения. Это может быть передача небольших объёмов данных, постепенное открытие окон управления потоком данных для управления скоростью передачи или создание кадров ACK, имитирующих высокую скорость потерь. При развёртывании QUIC следует обеспечивать смягчение Slowloris-атак такими способами, как увеличение максимального числа клиентов, поддерживаемого сервером, ограничение числа соединений с одного адреса IP, ограничение на минимальную скорость обмена данные в соединении, ограничение продолжительности соединений по времени.

21.7. Атаки с фрагментацией и сборкой пакетов

Злонамеренный отправитель может осознанно не передать часть данных потока, заставляя получателя выделять ресурсы для неотправленных данных. Это может вызвать у получателя выделение непропорционального приёмного буфера в памяти и/или создание большой и неэффективной структуры данных. Атакующий также может намеренно не подтверждать пакеты в попытке заставить отправителя сохранять неподтвержденные данные потоков для повторной передачи.

Атаки на получателей ослабляются, если окно управления потоком данных соответствует доступной памяти. Однако некоторые получатели будут чрезмерно использовать память и анонсировать смещения управления потоком данных, суммарно превосходящие размер доступной памяти. Стратегия выделения избыточной памяти может повышать производительность при корректном поведении конечной точки, но делает такую точку уязвимой для атак с фрагментацией потока. При развёртывании QUIC следует обеспечивать смягчение атак с фрагментацией потоков. Это может быть предотвращение выделения избыточной памяти, задержка сборки кадров STREAM, реализация эвристики на основе продолжительности пропусков в сборке и комбинации этих методов.

21.8. Атака с представлением потоков

Злонамеренная конечная точка может создать большое число потоков, исчерпав состояния партнёра, а также повторять процесс для организации большого числа соединения в стиле атак SYN flood на протокол TCP. Обычно клиенты создают потоки последовательно, как описано в параграфе 2.1. Однако при запуске нескольких потоков с короткими интервалами потеря или нарушение порядка могут вызвать нарушение порядка доставки кадров STREAM. На приёмной стороне при получении потока с большим номером получатель должен создать все промежуточные потоки того же типа (см. параграф 3.2). таким образом, в новом соединении создание потока 4000000 приведёт к созданию миллиона и одного инициированного клиентом двухстороннего потока. Число активных потоков ограничено транспортными параметрами initial_max_streams_bidi и initial_max_streams_uni, которые обновляются любыми принятыми кадрами MAX_STREAMS, как описано в параграфе 4.6. При разумном выборе эти ограничения смягчают атаки с представлением потока, однако установка слишком низкого предела может повлиять на производительность приложений, ожидающих большого числа потоков.

21.9. DoS-атаки на партнёров

QUIC и TLS содержат кадры или сообщения, легитимные в определённом контексте, но ими можно злоупотреблять для принуждения партнёра расходовать ресурсы для обработки без заметного влияния на состояние соединения.

Сообщения можно также использовать для изменения или восстановления состояния незаметным способом, таким как передача с небольшим превышением ограничений контроля перегрузок. Если затраты на обработку непропорционально превышают расход пропускной способности этот может позволить вредоносному партнёру выйти за пределы возможностей обработки.

Хотя для всех сообщений имеются легитимные способы применения, реализации следует отслеживать расходы на обработку и считать избыток непродуктивных пакетов индикацией атаки. Конечные точки могут отвечать на такие события ошибкой соединения или отбрасыванием пакетов.

21.10. Атаки с явной индикацией перегрузки

Атакующий на пути может менять значения ECN в заголовке IP для воздействия на скорость передачи. В [RFC3168] рассмотрены такие манипуляции и их влияние. Ограниченный атакующий на пути может дублировать и передавать пакеты с изменёнными полями ECN для влияния на скорость передачи. Если дубликаты пакетов получатель отбрасывает, атакующему придётся состязаться с исходными пакетами для успешной атаки. Поэтому конечные точки QUIC игнорируют поле ECN в пакетах IP, если не будет успешно обработан хотя бы один пакет QUIC в этом пакете IP (см. параграф 13.4).

21.11. Предсказание Stateless Reset

Сброс без учёта состояния открывает возможность для атак, похожих на внедрение TCP reset . Такая атака возможна, если злоумышленник способен вызвать генерацию маркера сброса для соединения с выбранным идентификатором.

Если пакет может быть направлен в разные экземпляры с общим статическим ключом, например, путём смены IP-адреса или порта, злоумышленник может вынудить сервер передать сброс без учёта состояния. Для защиты от такой атаки конечные точки, имеющие общий ключ для сброса без учёта состояния (см. параграф 10.3.2), должны быть организованы так, чтобы пакеты с данным идентификатором соединения всегда поступали экземпляру, имеющему статус соединения, если только это соединение не утратило активность.

В более общем смысле серверам недопустимо генерировать сброс без учёта состояния, если соединение с соответствующим идентификатором может быть активным на любой из конечных точек, применяющих общий статический ключ.

В случае кластера с динамическим распределением нагрузки может произойти изменение конфигурации балансировщика при сохранении активным экземпляром статуса соединения. Даже если экземпляр сохраняет состояние соединения, смена маршрутизации и результирующий сброс без учёта состояния будут приводить к разрыву соединения. Если нет никаких шансов направить пакет нужному экземпляру, лучше передать сброс без учёта состояния, чем ждать тайм-аута. Однако это приемлемо лишь в тех случаях, когда атакующий не может влиять на маршрутизацию.

21.12. Понижение версии

В этом документе определены пакеты QUIC Version Negotiation (раздел 6), служащие для согласования версии QUIC между парой конечных точек. Однако документ не задаёт способ согласования данной версии с будущими. В частности, пакеты Version Negotiation не включают механизма предотвращения атак на понижение версии. Будущие версии QUIC при использовании пакетов Version Negotiation должны задать механизм, устойчивый к таким атакам.

21.13. Нацеливание атак через маршрутизацию

При развёртывании следует ограничивать возможность злоумышленников нацелить атаку на конкретных экземпляр сервиса. В идеале решения о маршрутизации следует принимать независимо от выбранных клиентом значений, включая адреса. После выбора экземпляра можно выбрать идентификатор соединения, чтобы последующие пакеты попадали в тот же экземпляр.

21.14. Анализ трафика

Размер пакетов QUIC может раскрывать сведения о размере их содержимого. Кадры PADDING позволяют конечным точкам возможность скрыть размер содержимого пакетов (см. параграф 19.1).

Предотвращение анализа трафика является сложной задачей и предметом активных исследований. Размер не является единственным путём утечки. Конечные точки могут раскрывать деликатные сведения и по другим побочным каналам, включая синхронизацию пакетов.

22. Взаимодействие с IANA

Этот документ создаёт несколько реестров для поддержки кодов, применяемых в QUIC и управляемых одним набором правил, описанных в параграфе 22.1.

22.1. Правила регистрации для реестров QUIC

Во всех реестрах QUIC возможна предварительная и постоянная регистрация кодов в соответствии с приведёнными ниже правилами.

22.1.1. Предварительная регистрация

Предварительная регистрация кодов предназначена для приватного использования и экспериментов с расширениями QUIC. Для предварительной регистрации нужно лишь указать значение кода и контактные данные. Однако выделенные предварительно коды могут быть заявлены повторно и назначены для иных целей.

Предварительная регистрация выполняется по процедуре Expert Review, описанной в параграфе 4.5 [RFC8126]. Назначенным экспертам рекомендуется отвергать лишь регистрации, запрашивающие слишком большую часть оставшегося пространства или первое невыделенное значение (см. параграф 22.1.2). Предварительная регистрация включат поле Date, указывающее дату последнего обновления регистрации. Запрос на обновление предварительной регистрации можно сделать без рецензии назначенных экспертов.

Все реестры QUIC включают указанные ниже поля для поддержки предварительной регистрации.

Value

Назначенный код.

Status

Постоянная (permanent) или предварительная (provisional) регистрация.

Specification

Ссылка на доступную публично спецификацию значения.

Date

дата последнего обновления регистрации.

Change Controller

Субъект, ответственный за определение регистрации.

Contact

Контактные данные регистрирующего лица.

Notes

Дополнительные примечания для регистрации.

В предварительных регистрациях поля Specification и Notes могут быть опущены, равно как дополнительные поля, требуемые для постоянной регистрации. Поле Date не требуется в запросе на регистрацию и устанавливается по факту регистрации или обновления.

22.1.2. Выбор кодов

Для новых запросов выделения кодов из реестров QUIC значения следует выбирать случайно, исключая выделенные значения и первый невыделенный код в соответствующем пространстве. По запросам на выделение нескольких кодов могут предоставляться непрерывные блоки, это минимизирует риск привязки разной семантики одному коду в разных реализациях.

Первый невыделенный код резервируется для назначения по процедуре Standards Action (см. параграф 4.9 в [RFC8126]). Для таких значений можно использовать процесс раннего назначения [EARLY-ASSIGN]. Для кодов, представляемых целыми числами переменного размера (раздел 16), таких как типы кадров, следует использовать коды, представляемые 4 или 8 байтами (значение 214 и выше), если применение не зависит существенно от размера кодирования.

Приложения для регистрации кодов в реестрах QUIC могут включать запрошенные коды как часть регистрации. Агентство IANA должно выделить выбранный код, если он ещё не занят и соблюдается процедура регистрации.

22.1.3. Повторное заявление предварительных кодов

Может быть подан запрос на удаление неиспользованных кодов с предварительной регистрацией для освобождения пространства в реестре или части реестра (например, из диапазона 64-16383 с кодами переменного размера). Это следует применять лишь для кодой с наиболее ранней датой регистрации, а записи, обновлённые менее чем за год до события, не следует заявлять повторно.

Запрос на удаление кода должен рассматриваться назначенными экспертами. Эксперты должны попытаться определить, используется ли удаляемый код. Экспертам рекомендуется связаться с указанными при регистрации контактными лицами, а также с как можно более широким кругом разработчиков протокола для получения сведений о применении кода. Экспертам рекомендуется ждать откликов не менее 4 недель.

Если при поиске обнаружено какое-либо применение кода или сделан запрос на обновление регистрации, повторное заявление кода недопустимо и вместо этого обновляется дата регистрации. В регистрационную запись может быть добавлено примечание с указанием полученных сведений. Если код не используется и заявки на повторное выделение нет, код можно удалить из реестра.

Процесс рецензирования и консультаций применяется также для запросов на перевод предварительной регистрации в постоянную, но в этом случае цель состоит в проверке представления регистрацией какого-либо используемого развёртывания.

22.1.4. Постоянная регистрация

Для постоянной регистрации в реестрах QUIC применяется процедура Specification Required (параграф 4.6 в [RFC8126]), если не указано иное. Назначенные эксперты проверяют наличие и доступность спецификаций. Экспертам рекомендуется быть беспристрастными, одобряя регистрации, если те не являются оскорбительными, легкомысленными или вредоносными (не просто неприятными эстетически или сомнительными архитектурно). При создании реестра могут задаваться дополнительные ограничения для постоянных регистраций.

При создании реестра могут указываться диапазоны кодов, для которых регистрация выполняется по особым правилам. Например, в реестре QUIC Frame Types (параграф 22.4) применяется более строгий подход для кодов из диапазона 0 — 63. Любые более строгие требования к постоянной регистрации не препятствуют предварительной регистрации соответствующих кодов. Например, можно запросить предварительную регистрацию кода типа кадра 61.

Все регистрации в документах Standards Track должны быть постоянными. Всем регистрациям этого документа выделен статус постоянных и список меняет контролёр IETF в контакте с рабочей группой QUIC (quic@ietf.org).

22.2. Реестр версий QUIC

Агентство IANA создало реестр QUIC Versions в разделе QUIC. Реестр QUIC Versions управляет 32-битовым пространством значений (см. раздел 15). Правила регистрации указаны в параграфе 22.1. Постоянная регистрация в этом реестре выполняется по процедуре Specification Required (параграф 4.6 в [RFC8126]).

Код 0x00000001 выделен с постоянным статусом для протокола, описанного в этом документе. Код 0x00000000 задан как постоянный резерв и указывает, что номер версии зарезервирован для согласования версий. Коды, соответствующие шаблону 0x?a?a?a?a являются резервными и IANA недопустимо выделять их, а также недопустимо указывать в списке выделенных значений.

22.3. Реестр транспортных параметров QUIC

Агентство IANA создало реестр QUIC Transport Parameters в разделе QUIC. Реестр QUIC Transport Parameters управляет 62-битовым пространством значений. Правила регистрации указаны в параграфе 22.1. Постоянная регистрация в этом реестре выполняется по процедуре Specification Required (параграф 4.6 в [RFC8126]), за исключением диапазона 0x00 — 0x3f (включительно), где применяется процедура Standards Action или IESG Approval в соответствии с параграфом 4.9 или 4.10 в [RFC8126].

В дополнение к полям, указанным в параграфе 22.1.1, для постоянной регистрации в этом реестре должно указываться поле Parameter Name с кратким мнемоническим обозначением параметра. Исходное содержимое реестра приведено в таблице 6.

Таблица 6. Исходное содержимое реестра параметров транспорта.

Значение

Имя параметра

Документ

0x00

original_destination_connection_id

Параграф 18.2

0x01

max_idle_timeout

Параграф 18.2

0x02

stateless_reset_token

Параграф 18.2

0x03

max_udp_payload_size

Параграф 18.2

0x04

initial_max_data

Параграф 18.2

0x05

initial_max_stream_data_bidi_local

Параграф 18.2

0x06

initial_max_stream_data_bidi_remote

Параграф 18.2

0x07

initial_max_stream_data_uni

Параграф 18.2

0x08

initial_max_streams_bidi

Параграф 18.2

0x09

initial_max_streams_uni

Параграф 18.2

0x0a

ack_delay_exponent

Параграф 18.2

0x0b

max_ack_delay

Параграф 18.2

0x0c

disable_active_migration

Параграф 18.2

0x0d

preferred_address

Параграф 18.2

0x0e

active_connection_id_limit

Параграф 18.2

0x0f

initial_source_connection_id

Параграф 18.2

0x10

retry_source_connection_id

Параграф 18.2

Значения вида 31*N+27 для целых N (т. е. 27, 58, 89 …) являются резервным и их недопустимо выделять IANA и недопустимо включать в список выделенных значений.

22.4. Реестр типов кадров QUIC

Агентство IANA создало реестр QUIC Frame Types в разделе QUIC. Реестр QUIC Frame Types управляет 62-битовым пространством значений. Правила регистрации указаны в параграфе 22.1. Постоянная регистрация в этом реестре выполняется по процедуре Specification Required (параграф 4.6 в [RFC8126]), за исключением диапазона 0x00 — 0x3f (включительно), где применяется процедура Standards Action или IESG Approval в соответствии с параграфом 4.9 или 4.10 в [RFC8126].

В дополнение к полям, указанным в параграфе 22.1.1, для постоянной регистрации в этом реестре должно указываться поле Frame Type Name с кратким мнемоническим обозначением типа кадра.

В дополнение к рекомендациям параграфа 22.1 в спецификации новых постоянных регистраций следует включать описание способов, какими конечная точка может определить возможность передачи данного типа кадров. В большинстве случаев предполагается регистрация сопровождающих транспортных параметров (см. параграф 22.3). В спецификациях для постоянной регистрации требуется также описать формат и семантику полей кадра. Исходное содержимое реестра представлено в таблице 3. Реестр не включает колонки «Пакеты» и «Spec» из таблицы 3.

22.5. Реестр кодов транспортных ошибок QUIC

Агентство IANA создало реестр QUIC Transport Error Codes в разделе QUIC. Реестр QUIC Transport Error Codes управляет 62-битовым пространством значений, разделенным на 3 части. Постоянные регистрации выполняются по процедуре Specification Required (параграф 4.6 в [RFC8126]), за исключением диапазона 0x00 — 0x3f (включительно), где применяется процедура Standards Action или IESG Approval в соответствии с параграфом 4.9 или 4.10 в [RFC8126].

В дополнение к полям, указанным в параграфе 22.1.1, для постоянной регистрации в этом реестре должны указываться перечисленные ниже поля.

Code

Краткое мнемоническое обозначение параметра.

Description

Краткое описание семантики кода ошибки, в качестве которого может служить ссылка на спецификацию.

Исходное содержимое реестра приведено в таблице 7.

Таблица 7. Исходные записи реестра транспортных ошибок QUIC.

Значение

Код

Описание

Документ

0x00

NO_ERROR

Нет ошибок

Раздел 20

0x01

INTERNAL_ERROR

Ошибка реализации

Раздел 20

0x02

CONNECTION_REFUSED

Сервер отклонил соединение

Раздел 20

0x03

FLOW_CONTROL_ERROR

Ошибка управления потоком данных

Раздел 20

0x04

STREAM_LIMIT_ERROR

Открыто слишком много потоков

Раздел 20

0x05

STREAM_STATE_ERROR

Кадр получен в недействительном состоянии потока

Раздел 20

0x06

FINAL_SIZE_ERROR

Изменение окончательного размера

Раздел 20

0x07

FRAME_ENCODING_ERROR

Ошибка кодирования кадра

Раздел 20

0x08

TRANSPORT_PARAMETER_ERROR

Ошибка в транспортных параметрах

Раздел 20

0x09

CONNECTION_ID_LIMIT_ERROR

Получено слишком много идентификаторов соединения

Раздел 20

0x0a

PROTOCOL_VIOLATION

Нарушение базового протокола

Раздел 20

0x0b

INVALID_TOKEN

Получен недействительный маркер

Раздел 20

0x0c

APPLICATION_ERROR

Ошибка приложения

Раздел 20

0x0d

CRYPTO_BUFFER_EXCEEDED

Переполнение буфера данных CRYPTO

Раздел 20

0x0e

KEY_UPDATE_ERROR

Недействительное обновление защиты пакета

Раздел 20

0x0f

AEAD_LIMIT_REACHED

Избыточное применение ключей защиты пакетов

Раздел 20

0x10

NO_VIABLE_PATH

Нет подходящего пути через сеть

Раздел 20

0x0100-0x01ff

CRYPTO_ERROR

Код сигнала TLS

Раздел 20

23. Литература

23.1. Нормативные документы

[BCP38] Ferguson, P. and D. Senie, «Network Ingress Filtering: Defeating Denial of Service Attacks which employ IP Source Address Spoofing», BCP 38, RFC 2827, May 2000. <https://www.rfc-editor.org/info/bcp38>

[DPLPMTUD] Fairhurst, G., Jones, T., Tüxen, M., Rüngeler, I., and T. Völker, «Packetization Layer Path MTU Discovery for Datagram Transports», RFC 8899, DOI 10.17487/RFC8899, September 2020, <https://www.rfc-editor.org/info/rfc8899>.

[EARLY-ASSIGN] Cotton, M., «Early IANA Allocation of Standards Track Code Points», BCP 100, RFC 7120, DOI 10.17487/RFC7120, January 2014, <https://www.rfc-editor.org/info/rfc7120>.

[IPv4] Postel, J., «Internet Protocol», STD 5, RFC 791, DOI 10.17487/RFC0791, September 1981, <https://www.rfc-editor.org/info/rfc791>.

[QUIC-INVARIANTS] Thomson, M., «Version-Independent Properties of QUIC», RFC 8999, DOI 10.17487/RFC8999, May 2021, <https://www.rfc-editor.org/info/rfc8999>.

[QUIC-RECOVERY] Iyengar, J., Ed. and I. Swett, Ed., «QUIC Loss Detection and Congestion Control», RFC 9002, DOI 10.17487/RFC9002, May 2021, <https://www.rfc-editor.org/info/rfc9002>.

[QUIC-TLS] Thomson, M., Ed. and S. Turner, Ed., «Using TLS to Secure QUIC», RFC 9001, DOI 10.17487/RFC9001, May 2021, <https://www.rfc-editor.org/info/rfc9001>.

[RFC1191] Mogul, J. and S. Deering, «Path MTU discovery», RFC 1191, DOI 10.17487/RFC1191, November 1990, <https://www.rfc-editor.org/info/rfc1191>.

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>.

[RFC3168] Ramakrishnan, K., Floyd, S., and D. Black, «The Addition of Explicit Congestion Notification (ECN) to IP», RFC 3168, DOI 10.17487/RFC3168, September 2001, <https://www.rfc-editor.org/info/rfc3168>.

[RFC3629] Yergeau, F., «UTF-8, a transformation format of ISO 10646», STD 63, RFC 3629, DOI 10.17487/RFC3629, November 2003, <https://www.rfc-editor.org/info/rfc3629>.

[RFC6437] Amante, S., Carpenter, B., Jiang, S., and J. Rajahalme, «IPv6 Flow Label Specification», RFC 6437, DOI 10.17487/RFC6437, November 2011, <https://www.rfc-editor.org/info/rfc6437>.

[RFC8085] Eggert, L., Fairhurst, G., and G. Shepherd, «UDP Usage Guidelines», BCP 145, RFC 8085, DOI 10.17487/RFC8085, March 2017, <https://www.rfc-editor.org/info/rfc8085>.

[RFC8126] Cotton, M., Leiba, B., and T. Narten, «Guidelines for Writing an IANA Considerations Section in RFCs», BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017, <https://www.rfc-editor.org/info/rfc8126>.

[RFC8174] Leiba, B., «Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words», BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[RFC8201] McCann, J., Deering, S., Mogul, J., and R. Hinden, Ed., «Path MTU Discovery for IP version 6», STD 87, RFC 8201, DOI 10.17487/RFC8201, July 2017, <https://www.rfc-editor.org/info/rfc8201>.

[RFC8311] Black, D., «Relaxing Restrictions on Explicit Congestion Notification (ECN) Experimentation», RFC 8311, DOI 10.17487/RFC8311, January 2018, <https://www.rfc-editor.org/info/rfc8311>.

[TLS13] Rescorla, E., «The Transport Layer Security (TLS) Protocol Version 1.3», RFC 8446, DOI 10.17487/RFC8446, August 2018, <https://www.rfc-editor.org/info/rfc8446>.

[UDP] Postel, J., «User Datagram Protocol», STD 6, RFC 768, DOI 10.17487/RFC0768, August 1980, <https://www.rfc-editor.org/info/rfc768>.

23.2. Дополнительная литература

[AEAD] McGrew, D., «An Interface and Algorithms for Authenticated Encryption», RFC 5116, DOI 10.17487/RFC5116, January 2008, <https://www.rfc-editor.org/info/rfc5116>.

[ALPN] Friedl, S., Popov, A., Langley, A., and E. Stephan, «Transport Layer Security (TLS) Application-Layer Protocol Negotiation Extension», RFC 7301, DOI 10.17487/RFC7301, July 2014, <https://www.rfc-editor.org/info/rfc7301>.

[ALTSVC] Nottingham, M., McManus, P., and J. Reschke, «HTTP Alternative Services», RFC 7838, DOI 10.17487/RFC7838, April 2016, <https://www.rfc-editor.org/info/rfc7838>.

[COOKIE] Barth, A., «HTTP State Management Mechanism», RFC 6265, DOI 10.17487/RFC6265, April 2011, <https://www.rfc-editor.org/info/rfc6265>.

[CSRF] Barth, A., Jackson, C., and J. Mitchell, «Robust defenses for cross-site request forgery», Proceedings of the 15th ACM conference on Computer and communications security — CCS ’08, DOI 10.1145/1455770.1455782, 2008, <https://doi.org/10.1145/1455770.1455782>.

[EARLY-DESIGN] Roskind, J., «QUIC: Multiplexed Stream Transport Over UDP», 2 December 2013, <https://docs.google.com/document/d/1RNHkx_VvKWyWg6Lr8SZ-saqsQx7rFV-ev2jRFUoVD34/edit?usp=sharing>.

[GATEWAY] Hätönen, S., Nyrhinen, A., Eggert, L., Strowes, S., Sarolahti, P., and M. Kojo, «An experimental study of home gateway characteristics», Proceedings of the 10th ACM SIGCOMM conference on Internet measurement — IMC ’10, DOI 10.1145/1879141.1879174, November 2010, <https://doi.org/10.1145/1879141.1879174>.

[HTTP2] Belshe, M., Peon, R., and M. Thomson, Ed., «Hypertext Transfer Protocol Version 2 (HTTP/2)», RFC 7540, DOI 10.17487/RFC7540, May 2015, <https://www.rfc-editor.org/info/rfc7540>.

[IPv6] Deering, S. and R. Hinden, «Internet Protocol, Version 6 (IPv6) Specification», STD 86, RFC 8200, DOI 10.17487/RFC8200, July 2017, <https://www.rfc-editor.org/info/rfc8200>.

[QUIC-MANAGEABILITY] Kuehlewind, M. and B. Trammell, «Manageability of the QUIC Transport Protocol», Work in Progress, Internet-Draft, draft-ietf-quic-manageability-11, 21 April 2021, <https://tools.ietf.org/html/draft-ietf-quic-manageability-11>.

[RANDOM] Eastlake 3rd, D., Schiller, J., and S. Crocker, «Randomness Requirements for Security», BCP 106, RFC 4086, DOI 10.17487/RFC4086, June 2005, <https://www.rfc-editor.org/info/rfc4086>.

[RFC1812] Baker, F., Ed., «Requirements for IP Version 4 Routers», RFC 1812, DOI 10.17487/RFC1812, June 1995, <https://www.rfc-editor.org/info/rfc1812>.

[RFC1918] Rekhter, Y., Moskowitz, B., Karrenberg, D., de Groot, G. J., and E. Lear, «Address Allocation for Private Internets», BCP 5, RFC 1918, DOI 10.17487/RFC1918, February 1996, <https://www.rfc-editor.org/info/rfc1918>.

[RFC2018] Mathis, M., Mahdavi, J., Floyd, S., and A. Romanow, «TCP Selective Acknowledgment Options», RFC 2018, DOI 10.17487/RFC2018, October 1996, <https://www.rfc-editor.org/info/rfc2018>.

[RFC2104] Krawczyk, H., Bellare, M., and R. Canetti, «HMAC: Keyed-Hashing for Message Authentication», RFC 2104, DOI 10.17487/RFC2104, February 1997, <https://www.rfc-editor.org/info/rfc2104>.

[RFC3449] Balakrishnan, H., Padmanabhan, V., Fairhurst, G., and M. Sooriyabandara, «TCP Performance Implications of Network Path Asymmetry», BCP 69, RFC 3449, DOI 10.17487/RFC3449, December 2002, <https://www.rfc-editor.org/info/rfc3449>.

[RFC4193] Hinden, R. and B. Haberman, «Unique Local IPv6 Unicast Addresses», RFC 4193, DOI 10.17487/RFC4193, October 2005, <https://www.rfc-editor.org/info/rfc4193>.

[RFC4291] Hinden, R. and S. Deering, «IP Version 6 Addressing Architecture», RFC 4291, DOI 10.17487/RFC4291, February 2006, <https://www.rfc-editor.org/info/rfc4291>.

[RFC4443] Conta, A., Deering, S., and M. Gupta, Ed., «Internet Control Message Protocol (ICMPv6) for the Internet Protocol Version 6 (IPv6) Specification», STD 89, RFC 4443, DOI 10.17487/RFC4443, March 2006, <https://www.rfc-editor.org/info/rfc4443>.

[RFC4787] Audet, F., Ed. and C. Jennings, «Network Address Translation (NAT) Behavioral Requirements for Unicast UDP», BCP 127, RFC 4787, DOI 10.17487/RFC4787, January 2007, <https://www.rfc-editor.org/info/rfc4787>.

[RFC5681] Allman, M., Paxson, V., and E. Blanton, «TCP Congestion Control», RFC 5681, DOI 10.17487/RFC5681, September 2009, <https://www.rfc-editor.org/info/rfc5681>.

[RFC5869] Krawczyk, H. and P. Eronen, «HMAC-based Extract-and-Expand Key Derivation Function (HKDF)», RFC 5869, DOI 10.17487/RFC5869, May 2010, <https://www.rfc-editor.org/info/rfc5869>.

[RFC7983] Petit-Huguenin, M. and G. Salgueiro, «Multiplexing Scheme Updates for Secure Real-time Transport Protocol (SRTP) Extension for Datagram Transport Layer Security (DTLS)», RFC 7983, DOI 10.17487/RFC7983, September 2016, <https://www.rfc-editor.org/info/rfc7983>.

[RFC8087] Fairhurst, G. and M. Welzl, «The Benefits of Using Explicit Congestion Notification (ECN)», RFC 8087, DOI 10.17487/RFC8087, March 2017, <https://www.rfc-editor.org/info/rfc8087>.

[RFC8981] Gont, F., Krishnan, S., Narten, T., and R. Draves, «Temporary Address Extensions for Stateless Address Autoconfiguration in IPv6», RFC 8981, DOI 10.17487/RFC8981, February 2021, <https://www.rfc-editor.org/info/rfc8981>.

[SEC-CONS] Rescorla, E. and B. Korver, «Guidelines for Writing RFC Text on Security Considerations», BCP 72, RFC 3552, DOI 10.17487/RFC3552, July 2003, <https://www.rfc-editor.org/info/rfc3552>.

[SLOWLORIS] «RSnake» Hansen, R., «Welcome to Slowloris — the low bandwidth, yet greedy and poisonous HTTP client!», June 2009, <https://web.archive.org/web/20150315054838/http://ha.ckers.org/slowloris/>.

Приложение A. Псевдокод

В этом приложении описан псевдокод примеров алгоритмов с упором на корректность и ясность, а не производительность. Сегменты псевдокода лицензируются как компоненты кода (Code Component, см. «Авторские права»).

A.1. Пример декодирования целого числа с переменным размером

Псевдокод на рисунке 45 иллюстрирует считывание целого числа переменного размера из потока байтов. Функция ReadVarint принимает один аргумент — последовательность байтов, которая может быть прочитана в сетевом порядке.

   ReadVarint(data):
     // Размер целых чисел кодируется 2 первыми битами первого байта.
     v = data.next_byte()
     prefix = v >> 6
     length = 1 << prefix

     // Когда размер известен, эти биты удаляются и считываются
     // остальные байты.
     v = v & 0x3f
     повтор length-1 раз:
       v = (v << 8) + data.next_byte()
     return v

Рисунок 45. Пример декодирования целого числа с переменным размером.


Например, 8-байтовая последовательность 0xc2197c5eff14e88c декодируется в десятичное число 151288809941952652, 4-байтовая последовательность 0x9d7f3e7d — в 494878333, 2-байтовая последовательность 0x7bbd — в 15293, а однобайтовая последовательность 0x25 — в 37 (как и двухбайтовая 0x4025).

A.2. Пример алгоритма кодирования номеров пакетов

Псевдокод на рисунке 46 показывает, как реализация может выбрать подходящий размер для кодирования номера пакета. Функция EncodePacketNumber принимает 2 аргумента — full_pn задаёт полный номер пакета, который будет передан, largest_acked — наибольший номер пакета, подтверждённый партнёром в текущем пространстве номеров.

  EncodePacketNumber(full_pn, largest_acked):
     // Число битов должно быть по меньшей мере на 1 больше 
     // двоичного логарифма числа непрерывных неподтвержденных
     // номеров пакетов, включая новый пакет.
     if largest_acked is None:
       num_unacked = full_pn + 1
     else:
       num_unacked = full_pn - largest_acked

     min_bits = log(num_unacked, 2) + 1
     num_bytes = ceil(min_bits / 8)

     // Кодирование целого числа и отсечка до num_bytes
     // младших байтов.
     return encode(full_pn, num_bytes)

Рисунок 46. Простой алгоритм декодирования номера пакета.


Например, если конечная точка получила подтверждение для пакета 0xabe8b3 и передаёт пакет с номером 0xac5c02, имеется 29519 (0x734f) остающихся пакетов. Для представления по меньшей мере удвоенного диапазона (59038 пакетов или 0xe69e) требуется 16 битов. В том же состоянии при отправке пакета с номером 0xace8fe применяется 24-битовое кодирование, поскольку нужно не менее 18 битов для представления удвоенного диапазона (131222 пакетов или 0x020096).

A.3. Пример алгоритма декодирования номеров пакетов

   DecodePacketNumber(largest_pn, truncated_pn, pn_nbits):
      expected_pn  = largest_pn + 1
      pn_win       = 1 << pn_nbits
      pn_hwin      = pn_win / 2
      pn_mask      = pn_win - 1
      // Входящему пакету следует быть больше expected_pn — pn_hwin,
      // но не больше expected_pn + pn_hwin. Это означает, что
      // нельзя просто вырезать биты после expected_pn и добавить
      // truncated_pn, поскольку значение может выйти из окна.
      //
      // Следующий код рассчитывает значение-кандидат и проверяет
      // его попадание в окно номеров. Дополнительная проверка
      // предотвращает переполнение и опустошение.
      candidate_pn = (expected_pn & ~pn_mask) | truncated_pn
      if candidate_pn <= expected_pn - pn_hwin and
         candidate_pn < (1 << 62) - pn_win:
         return candidate_pn + pn_win
      if candidate_pn > expected_pn + pn_hwin and
         candidate_pn >= pn_win:
         return candidate_pn - pn_win
      return candidate_pn

Рисунок 47. Пример алгоритма декодирования номера пакета.


Псевдокод на рисунке 47 показывает пример алгоритма декодирования номера пакета после снятия защиты заголовка. Функция DecodePacketNumber принимает 3 аргумента — largest_pn указывает наибольший номер успешно обработанного пакета из текущего пространства номеров, truncated_pn содержит значение поля Packet Number, pn_nbits указывает число битов в поле Packet Number (8, 16, 24 или 32). Например, если максимальный номер успешно аутентифицированного пакета составляет 0xa82f30ea, 16-битовое значение 0x9b32 будет декодировано как 0xa82f9b32.

A.4. Пример алгоритма проверки ECN

Каждый раз, когда конечная точка начинает передачу пакетов по новому пути, она проверяет поддержку ECN на этом пути (см. параграф 13.4). Если путь поддерживает ECN, ставится цель использовать ECN. Конечные точки могут также периодически снова проверять путь, который указал отсутствие поддержки ECN. В этом параграфе описан один из методов проверки пути, но конечные точки могут применять и другие методы.

Пути назначается одно из состояний — testing (проверка), unknown (неизвестно), failed (отказ), capable (поддержка). На путях с состоянием testing или capable конечная точка по умолчанию передаёт пакеты с маркировкой ECT(0), в остальных случаях пакеты не маркируются. Для начала проверки пути устанавливается статус ECN testing и имеющиеся значения счётчиков ECN запоминаются как базовые. Период тестирования ограничивается числом пакетов или временем, задаваемым конечной точкой. Цель состоит не в ограничении продолжительности тестирования, а в обеспечении передачи достаточного числа маркированных пакетов для получения значений счётчиков ECN, обеспечивающих чёткую индикацию трактовки маркированных пакетов на пути. В параграфе 13.4.2 предлагается устанавливать ограничение в 10 пакетов или 3 интервала PTO.

По завершении тестирования статус ECN для пути становится unknown. Из этого состояния успешная проверка счётчиков ECN в кадре ACK (см. параграф 13.4.2.1) меняет состояние ECN для пути на capable, если не был подтверждён ни один маркированный пакет. При отказе проверки счётчиков ECN статус ECN для пути становится failed. Конечная точка может установить этот статус также в случае обнаружения потери маркированных пакетов или установки для всех таких пакетов маркера ECN-CE.

Применение этого алгоритма гарантирует редкое отключение ECN на путях с корректной поддержкой ECN. Любой путь с некорректным изменением маркировки будет приводить к отключению ECN. В редких случаях, когда маркированные пакеты отбрасываются на пути незначительная продолжительность периода тестирования позволит потерять лишь небольшое число пакетов.

Участники работы

Первоначальное устройство и обоснование этого протокола в значительной степени основаны на работе Jim Roskind [EARLY-DESIGN]. Рабочая группа IETF QUIC получила огромную поддержку от многих людей. Ниже перечислены люди, внёсшие существенный вклад в этот документ.

Alessandro Ghedini

Alyssa Wilk

Antoine Delignat-Lavaud

Brian Trammell

Christian Huitema

Colin Perkins

David Schinazi

Dmitri Tikhonov

Eric Kinnear

Eric Rescorla

Gorry Fairhurst

Ian Swett

Igor Lubashev

奥 一穂 (Kazuho Oku)

Lars Eggert

Lucas Pardue

Magnus Westerlund

Marten Seemann

Martin Duke

Mike Bishop

Mikkel Fahnøe Jørgensen

Mirja Kühlewind

Nick Banks

Nick Harper

Patrick McManus

Roberto Peon

Ryan Hamilton

Subodh Iyengar

Tatsuhiro Tsujikawa

Ted Hardie

Tom Jones

Victor Vasiliev

Адреса авторов

Jana Iyengar (editor)

Fastly

Email: jri.ietf@gmail.com

Martin Thomson (editor)

Mozilla

Email: mt@lowentropy.net

Перевод на русский язык

Николай Малых

nmalykh@protokols.ru


1Internet Engineering Task Force — комиссия по решению инженерных задач Internet.

2Internet Engineering Steering Group — комиссия по инженерным разработкам Internet.

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 — максимальный размер передаваемого блока для пути.

12Congestion Experienced — наличие перегрузки.

13ECN-Capable Transport — транспорт с поддержкой ECN.

14Path Maximum Transmission Unit Discovery — определение MTU на пути.

15Datagram Packetization Layer PMTU Discovery — определение MTU на пути для пакетизации дейтаграмм.

Рубрика: RFC | Оставить комментарий

RFC 8990 GeneRic Autonomic Signaling Protocol (GRASP)

Internet Engineering Task Force (IETF)                        C. Bormann
Request for Comments: 8990                        Universität Bremen TZI
Category: Standards Track                              B. Carpenter, Ed.
ISSN: 2070-1721                                        Univ. of Auckland
                                                             B. Liu, Ed.
                                            Huawei Technologies Co., Ltd
                                                                May 2021

GeneRic Autonomic Signaling Protocol (GRASP)

Базовый протокол автономной сигнализации GRASP

PDF

Аннотация

В этом документе определён протокол GRASP, позволяющий автоматическим1 узлам и автоматическим агентам служб (Autonomic Service Agent или ASA) динамически обнаруживать партнёров для синхронизации состояний и согласования параметров. GRASP зависит от внешней среды защиты, которая описана в отдельных документах. Технические задачи и параметры для конкретных вариантов применения также описываются в отдельных документах. В приложениях кратко рассмотрены требования к протоколу, а также другие протоколы со сравнимыми свойствами.

Статус документа

Документ содержит проект стандарта Internet (Standards Track).

Документ является результатом работы IETF2 и представляет согласованный взгляд сообщества IETF. Документ прошёл открытое обсуждение и был одобрен для публикации IESG3. Дополнительную информацию о стандартах Internet можно найти в разделе 2 в RFC 7841.

Информацию о текущем статусе документа, ошибках и способах обратной связи можно найти по ссылке https://www.rfc-editor.org/info/rfc8990.

Авторские права

Copyright (c) 2021. Авторские права принадлежат IETF Trust и лицам, указанным в качестве авторов документа. Все права защищены.

К этому документу применимы права и ограничения, перечисленные в BCP 78 и IETF Trust Legal Provisions и относящиеся к документам IETF (http://trustee.ietf.org/license-info), на момент публикации данного документа. Прочтите упомянутые документы внимательно, поскольку в них описаны права и ограничения, относящиеся к данному документу. Фрагменты программного кода, включённые в этот документ, распространяются в соответствии с упрощённой лицензией BSD, как указано в параграфе 4.e документа IETF Trust Legal Provisions, без каких-либо гарантий (как указано в Simplified BSD License).

1. Введение

Успех Internet сделал сети IP больше и сложнее. Крупные ISP и сети предприятий становятся все более сложными для управления людьми, эксплуатационные расходы быстро растут. Это ведёт к росту потребности в самоуправлении сетей. Общие аспекты автоматических сетей (Autonomic Network или AN) рассмотрены в [RFC7575] и [RFC7576].

Один из подходов заключается в децентрализации логики управления сетью путём её переноса в элементы сети. Эталонная модель сетей с самоуправлением (AN) на этой основе представлена в [RFC8993]. С этим документом следует ознакомиться для понимания совместной работы различных автоматических элементов. Для самоуправления устройства, в которых реализованы автоматические агенты служб (Autonomic Service Agent или ASA, [RFC7575]), предъявляют свои требования к сигнализации. В частности, им нужно обнаруживать друг друга, синхронизировать состояния, а также согласовывать параметры и ресурсы напрямую. Для типов параметров и ресурсов нет никаких ограничений и они могут включать базовую информацию, нужную для адресации и маршрутизации, а также все остальное, что может настраиваться в традиционных сетях без самоуправления. Неделимый элемент обнаружения, синхронизации или согласования называется технической задачей, т. е. настраиваемым параметром или набором параметров (см. определения в параграфе 2.1).

Процесс согласования выполняется в несколько итераций и требует нескольких обменов сообщениями, образующих замкнутый цикл между согласующимися объектами. Фактически эти объекты являются агентами ASA, которые обычно, но не обязательно, размещаются в разных устройствах. Синхронизацию состояний при необходимости можно считать согласованием без итераций. Согласование и синхронизация логически следуют за обнаружением. Более подробно требования описаны в Приложении B. В параграфе 2.3 рассмотрена модель поведения для протокола, предназначенного для обнаружения, синхронизации и согласования. Устройство протокола GRASP, описано в разделе 2 на основе этой модели поведения. Соответствующие возможности имеющихся протоколов рассмотрены в Приложении C.

Предложенный механизм обнаружения ориентирован на синхронизацию и согласование задач. Он основан на процессе обнаружения соседей по локальному каналу, но поддерживает перенаправление на партнёров в других каналах. Какая-либо определённая топология сети не предполагается. Когда устройство запускается без подготовленной конфигурации, топология ему неизвестна. Протокол можно применять как в небольшой и/или плоской сети, такой как небольшая сеть дома или в офис, так и в крупной сети с профессиональным управлением. Поэтому механизм обнаружения должен быть способен разрешать устройствам начальную загрузку самостоятельно без каких-либо предварительных допущений о структуре сети.

Поскольку протокол GRASP может применяться в процессе принятия решений между распределенными устройствами или сетями, он должен работать в безопасной среде со строгой проверкой подлинности (аутентификацией).

В реальных системах не все устройства будут поддерживать GRASP, поэтому некоторые агенты ASA будут напрямую управлять группами неавтоматических узлов, а иные узлы без самоуправления будут управляться традиционными способами. Такие варианты смешанного использования в спецификации не рассматриваются.

2. Обзор протокола

2.1. Терминология

Ключевые слова должно (MUST), недопустимо (MUST NOT), требуется (REQUIRED), нужно (SHALL), не следует (SHALL NOT), следует (SHOULD), не нужно (SHOULD NOT), рекомендуется (RECOMMENDED), не рекомендуется (NOT RECOMMENDED), возможно (MAY), необязательно (OPTIONAL) в данном документе интерпретируются в соответствии с BCP 14 [RFC2119] [RFC8174] тогда и только тогда, когда они выделены шрифтом, как показано здесь.

В документе используются термины, определённые в [RFC7575], а ниже даны определения ещё ряда терминов.

Discovery — обнаружение

Процесс, в котором агент ASA находит партнёров в соответствии с заданной задачей обнаружения. Результаты обнаружения могут различаться при разных задачах. Обнаруженные партнёры могут позднее участвовать в согласовании или выступать источником при синхронизации данных.

Negotiation — согласование

Итеративное взаимодействие двух ASA для согласования параметров, подходящих для задач обоих ASA.

State Synchronization — синхронизация состояний

Процесс взаимодействия агентов ASA для получения текущего состояния параметров, хранящихся в других ASA. Это особый случай согласования, в котором информация передаётся, но агенты ASA не запрашивают у своих партнёров изменение настройки параметров. Все остальные определения применимы как для согласования, так и для синхронизации.

Technical Objective (Objective) — техническая задача (задача)

Технической задачей является структура данных, основным содержимым которой является имя и значение. Значение состоит из одного параметра конфигурации или набора параметров того или иного типа. Формат задачи определён в параграфе 2.10.1. Задачи применяются в 3 контекстах: обнаружение, согласование и синхронизация. Обычно данная задача не связана сразу с контекстом согласования и синхронизации.
Один агент ASA может поддерживать несколько независимых задач.
Параметры в значении данной задачи применяются к соответствующей службе, функции или действию. В принципе они могут быть чем угодно, что сетевой узел может задать конкретным логическим, числовым или строковым значением или более сложной структурой данных. Предполагается, что каждый узел содержит один или несколько агентов ASA, которые сами могут управлять вспомогательными неавтоматическими узлами.

Discovery Objective — задача обнаружения

Задача обнаружения. Значение может быть неопределённым.

Synchronization Objective — задача синхронизации

Задача, для которой конкретное техническое содержимое должно синхронизироваться между двумя или несколькими ASA. Таким образом, каждый агент ASA будет поддерживать свою копию задачи.

Negotiation Objective — задача согласования

Задача, техническое содержание которой должно быть определено в координации с другим ASA. Каждый агент ASA будет поддерживать свою копию задачи.
Подробное обсуждение задач, включая их формат, приведено в параграфе 2.10.

Discovery Initiator — инициатор обнаружения

Агент ASA, запускающий обнаружение передачей сообщения Discovery, указывающего конкретную задачу для обнаружения.

Discovery Responder — ответчик при обнаружении (обнаруживаемый)

Партнёр, который содержит ASA, поддерживающий цель обнаружения, указанную инициатором, или кэширующий местоположение агентов ASA, поддерживающих эту цель. Ответчик передаёт сообщение Discovery Response.

Synchronization Initiator — инициатор синхронизации

Агент ASA, запускающий синхронизацию отправкой запроса, указывающего конкретную задачу для синхронизации.

Synchronization Responder — ответчик при синхронизации (опорное устройство)

Агент ASA, отвечающий значением запрошенной задачи.

Negotiation Initiator — инициатор согласования

Агент ASA, запускающий согласование отправкой запроса, указывающего конкретную задачу для согласования.

Negotiation Counterpart — вторая сторона согласования

Партнёр, с которым инициатор согласует конкретную задачу.

GRASP Instance — экземпляр GRASP

Экземпляр протокольной машины GRASP, вероятно включающий потоки или процессы, а также динамические структуры данных, такие как кэш обнаружения, и работающий в данной защищённой среде на одном устройстве.

GRASP Core — ядро GRASP

Код и общие структуры данных экземпляра GRASP, взаимодействующие с отдельными ASA через подходящий интерфейс прикладных программ (Application Programming Interface или API).

Interface (GRASP Interface) — интерфейс GRASP

Если явно не указано иное, это обозначает сетевой интерфейс (физический или виртуальный), используемый в настоящее время конкретным экземпляром GRASP. Устройство может иметь другие интерфейсы, не используемые GRASP, а также не участвующие в работе автоматической сети AN.

2.2. Высокоуровневая модель развёртывания

Реализация GRASP будет частью инфраструктуры автоматической сети (Autonomic Networking Infrastructure или ANI) в автоматическом узле, которая должна также обеспечивать подходящую защищённую среду. В соответствии с [RFC8993] этой среде следует быть автоматической плоскостью управления (Autonomic Control Plane или ACP) [RFC8994]. В результате все автоматические узлы в ACP могут доверять друг другу. Предполагается, что GRASP будет иметь доступ к ACP через типовой интерфейс программных сокетов и ACP сделает доступными лишь сетевые интерфейсы внутри сети AN. При отсутствии ACP применяются соображения, приведённые в параграфе 2.5.1.

Имеется также один или несколько автоматических агентов служб (ASA). В случае специализированного для одной задачи (single-purpose) устройства эти компоненты могут быть полностью интегрированы с GRASP и ACP. Предполагается, что более распространены будут многоцелевые устройства, содержащие несколько ASA, такие как маршрутизатор или крупный коммутатор. В таких случаях предполагается, что ACP, GRASP и агенты ASA будут реализованы как отдельные процессы, которые могут поддерживать асинхронные и одновременные операции, например, на основе многопоточности.

В некоторых случаях может разворачиваться ограниченная модель согласования на основе отношений частичного доверия, например, между двумя административными доменами. Агенты ASA в этом случае могут обмениваться ограниченной информацией и согласовывать некоторые конкретные конфигурации.

Протокол GRASP разработан специально для работы в одной области адресации. Его механизмы обнаружения и лавинной рассылки не поддерживают автоматические операции через какие-либо трансляторы адресов или прокси вышележащего уровня.

Требуется подходящий интерфейс API между GRASP и агентами ASA. В некоторых реализациях агенты ASA будут работать в пользовательском пространстве с библиотекой GRASP, предоставляющей API, а эта библиотека будет взаимодействовать с ядром GRASP через системные вызовы. Детали интерфейсов API выходят за рамки этого документа. Возможные модели развёртывания подробно описаны в [RFC8993].

Экземпляр GRASP должен знать сетевые интерфейсы, которые он будет использовать, а также соответствующие глобальные и локальные для канала адреса. При наличии ACP такая информация будет доступна из таблицы смежности, описанной в [RFC8993]. В иных случаях протокол GRASP должен сам определить эту информацию. Детали такого определения зависят от устройства и операционной системы. Далее в документе термины «интерфейс» и «интерфейс GRASP» относятся лишь к набору сетевых интерфейсов, используемых конкретным экземпляром GRASP.

Поскольку GRASP нужно работать с очень высокой надёжностью, особенно при начальной загрузке и во время отказов, важно, чтобы каждая реализация продолжала работать в таких условиях. Например, отказам при обнаружении или каким-либо сбоям в сокетах недопустимо приводить к невосстановимым сбоям в протоколе GRASP и протокол должен возвращать подходящий код ошибки через API, чтобы агенты ASA также могли восстановиться.

Недопустима зависимость GRASP от энергонезависимого хранилища. Все условия ошибок при работе и такие события, как смена адресов, отказы сетевых интерфейсов, циклы сна и пробуждения CPU, должны обрабатываться так, чтобы протокол GRASP продолжал корректную и защищённую работу (параграф 2.5.1).

Автоматический узел обычно использует один экземпляр GRASP, который является общим для нескольких агентов ASA. Возможные исключения рассмотрены ниже.

2.3. Высокоуровневое устройство протокола

В этом параграфе рассматривается модель поведения и общее устройство GRASP, поддерживающее обнаружение, синхронизацию и согласование при работе в качестве платформы для разных технических целей.

Базовая платформа

Устройство протокола является достаточно общим и не зависит от содержимого синхронизации или согласования. Техническое содержимое меняется в соответствии с целями и парами партнёров.

Множество экземпляров

Обычно на автоматическом узле будет использоваться один основной экземпляр протокольной машины GRASP, а каждый агент ASA будет запускать независимый асинхронный процесс. Однако возможен запуск на одном узле нескольких экземпляров GRASP, возможно с разными параметрами защиты (параграф 2.5.2). В таких случаях каждый экземпляр должен независимо прослушивать групповые адреса link-local для GRASP и все экземпляры должны пробуждаться такими групповыми пакетами для корректной работы обнаружения и лавинной рассылки.

Инфраструктура защиты

Как отмечено выше, протокол не имеет встроенных функций защиты и опирается на внешнюю инфраструктуру.

Однотипное обнаружение, синхронизация и согласование

Метод обнаружения, а также методы синхронизации и согласования устроены одинаково и могут комбинироваться, когда это полезно, обеспечивая быстрый режим работы, как описано в параграфе 2.5.4. Эти процессы могут выполняться и независимо.
Для некоторых целей (особенно связанных со службами прикладного уровня) можно применять иные механизмы обнаружения, например, основанные на DNS [RFC7558]. Выбор остаётся за разработчиками отдельных ASA.

Однородный шаблон для технических задач

Объекты синхронизации и согласования определены по однородным шаблонам. Содержащиеся в задачах значения передаются в простом двоичном формате или в виде комплексного объекта. Базовый протокол использует краткое двоичное представление (Concise Binary Object Representation или CBOR) [RFC8949], которое можно легко расширить в соответствии с будущими требованиями.

Гибкая модель для синхронизации

GRASP поддерживает синхронизацию между двумя узлами, которую можно применять неоднократно для синхронизации небольшого числа устройств. Протокол также поддерживает лавинный режим без запроса (unsolicited flooding), когда большой группе устройств (возможно всем автоматическим узлам) нужна одна и та же техническая задача.
Для некоторых параметров сети могут лучше подойти традиционные механизмы лавинной рассылки, такие как протокол DNCP (Distributed Node Consensus Protocol) [RFC7787]. GRASP может сосуществовать с DNCP.

Простая модель «инициатор-ответчик» для согласования

Многочисленные согласования очень сложно моделировать и сходимость их не гарантируется. GRASP использует простую двухстороннюю модель и может косвенно поддерживать многостороннее согласование.

Организация контекста согласования или синхронизации

Технические задачи, передаваемые GRASP, организуются в соответствии с функцией или службой. Задачи разных функций и служб хранятся раздельно, поскольку они могут согласовываться и синхронизироваться разными сторонами или иметь разные времена откликов. Обычно один агент ASA управляет небольшим набором тесно связанных задач с версией этого ASA в каждом соответствующем автоматическом узле. Более подробное рассмотрение этого вопроса выходит за рамки документа.

Запросы и отклики в процедурах согласования

Инициатор может согласовать конкретную задачу с соответствующими агентами ASA. Он может запросить относящуюся к делу информацию для корректировки своей локальной конфигурации, а также попросить партнёра установить соответствующую конфигурацию. Инициатор также может запросить моделирование или предсказание результатов, отправляя некоторые условия пробного прогона (dry-run).
Кроме традиционного отклика «да» или «нет» ответчик может возвратить значение предлагаемого варианта для соответствующей задачи. Это приведёт к началу двухстороннего согласования, завершающегося компромиссом между парой ASA.

Схождение процедур согласования

Для обеспечения сходимости, когда ответчик предлагает новое значение или условие в ответе при согласовании, такому предложению следует быть как можно ближе к исходному запросу или предыдущему предложению. Предлагаемое на следующем этапе согласования значение следует выбирать между парой значений двух предшествующих этапов. GRASP предоставляет механизмы, гарантирующие схождение (или отказ) за небольшое число шагов, ограниченное тайм-аутом или максимальным числом итераций.

Расширяемость

Протокол GRASP осознанно не имеет номера версии и может быть расширен путём добавления новых типов сообщений или опций. Сообщение Invalid (M_INVALID) применяется для обозначения нераспознанных сообщений или опций, переданных другой реализацией. При обычном использовании новая семантика добавляется путём определения новых задач для синхронизации или согласования.

2.4. Краткий обзор операций

Предполагается, что экземпляр GRASP работает как отдельный модуль ядра, обеспечивающий интерфейс API (такой как [RFC8991]) для различных агентов ASA. Эти ASA могут работать без специальных привилегий, если они не требуются по иным причинам (таким как настройка адресов IP или манипуляции с таблицами маршрутизации).

Используемые ASA механизмы GRASP строятся на основе задач GRASP, определённых как структуры данных с административной информацией, такой как уникальные имена задач и их текущие значения. Протокол не ограничивает формат и размер значений за исключением того, что они должны быть пригодны для последовательной передачи в CBOR, и на практике это ограничений не задаёт.

GRASP обеспечивает несколько механизмов, перечисленных ниже.

  • Механизм обнаружения (M_DISCOVERY, M_RESPONSE), позволяющий агенту ASA найти другие ASA, которые поддерживают данную задачу.

  • Механизм запроса согласования (M_REQ_NEG), который позволяет ASA запустить согласования задачи с другим ASA. После запуска согласования процесс становится симметричным и имеется сообщение пошагового согласования (M_NEGOTIATE) для каждого ASA. Для согласования поддерживаются также функции M_WAIT, M_END.

  • Механизм синхронизации (M_REQ_SYN), с помощью которого агент ASA может запросить текущее значение объекта у другого ASA. Функция M_SYNCH позволяет ASA ответить на запрос синхронизации.

  • Лавинный механизм (M_FLOOD) позволяет агенту ASA разослать текущее значение задачи через сеть AN так, что любой ASA может получить его. Одним из применений являются анонсы, избавляющие от необходимости обнаруживать широко применяемые задачи.

Некоторые примеры сообщений и простого потока представлены в Приложении A.

2.5. Базовые свойства и механизмы GRASP

2.5.1. Требование внешнего механизма защиты

Протокол GRASP не задаёт транспортную защиту, поскольку он предназначен для применения в разных средах. Каждое решение по адаптации GRASP должно задавать «подложку» защиты и транспорта, используемую GRASP в этом решении. Подложка должна обеспечивать передачу и приём сообщений GRASP лишь между членами группы с взаимным доверием, в которой работает GRASP. Каждый член такой группы является экземпляром GRASP и узлом связанного графа. Группа и граф создаются подложкой защиты и транспорта и называется доменом GRASP. Подложка должна поддерживать индивидуальные (unicast) сообщения между любыми членами группы и групповые (link-local) сообщения между смежными членами. Сообщения между членами группы и не входящими в группу элементами должны отвергаться. В этой модели защита обеспечивается через включение в группу, но любой член группы доверия может атаковать всю сеть, пока не будет отозван (исключён) из группы.

Подложка должна применять криптографическую аутентификацию членов группы и контролировать целостность сообщений GRASP. Это может быть реализовано в домене сквозным или поэтапным (hop by hop) способом. Подложка защиты и транспорта должна обеспечивать механизмы удаления из группы потерявших доверие членов. Если подложка не требует и не применяет шифрования сообщений GRASP, любая служба, применяющая GRASP в таком решении, должна обеспечивать защиту и шифрование элементов сообщения, раскрытие которых может создавать угрозу атаки.

Подложкой защиты и транспорта для GRASP в инфраструктуре ANI служит плоскость управления ACP. Если явно не сказано иное, далее в документе предполагается именно эта подложка. ACP требует использовать шифрование, поэтому GRASP в инфраструктуре ANI может считать свои сообщения шифрованными. Доменом GRASP служит ACP, где все узлы автоматического домена соединены шифрованными виртуальными каналами. ACP использует для сообщений защиту hop-by-hop (проверка подлинности и шифрование). Для удаления узлов применяется стандартный отзыв сертификатов PKI или завершение срока действия для краткосрочных сертификатов. Более подробное описание приведено в [RFC8994].

Как отмечено в параграфе 2.3, некоторые операции GRASP по взаимному соглашению могут выполняться через границу административного домена без использования ACP. Такие операции должны быть ограничены отдельным экземпляром GRASP со своей копией всех структур данных GRASP, работающим в отдельном домене GRASP со своей подложкой защиты и транспорта. В наиболее простом случае каждое междоменное соединение GRASP (точка-точка) может использовать свой домен, а подложка защиты и транспорта может создаваться на основе протокола защиты транспортного или сетевого уровня. Этот вопрос оставлен для будущих спецификаций.

Имеются исключения из правил для подложки защиты и транспорта в сильно ограниченных подмножествах GRASP, рассчитанных на организацию подложки защиты и транспорта, описанную в следующем параграфе.

2.5.2. DULL GRASP

Некоторым службам может потребоваться использование незащищённых сообщений GRASP для обнаружения, откликов и лавинной отправки без возможности использования имеющихся защищённых связей как часть процесса организации защищённых связей, таких как защищённая подложка GRASP.

Такие операции не защищены по своей природе и их необходимо настраивать для работы на локальном канале (link-local), чтобы минимизировать риск вредоносных воздействий. Возможные примеры включают обнаружение кандидатов в соседи по ACP [RFC8994], прокси начальной загрузки [RFC8995], службы инициализации в сетях, использующих GRASP, но не являющихся полностью автоматическими (т. е. без ACP). Такое использование должно ограничиваться операциями на локальном канале одного интерфейса, а также должно ограничиваться одним незащищённым экземпляром GRASP со своей копией всех структур данных GRASP. Этот экземпляр называют DULL (Discovery Unsolicited Link-Local).

Правила для экземпляра DULL приведены ниже.

  • Инициатор может передавать групповые (link-local) сообщения Discovery или Flood Synchronization, в которых должно быть задано значение счётчика интервалов пересылки (loop count) 1 для предотвращения операций вне локального канала (off-link). Передача незапрошенных сообщений GRASP иных типов недопустима.

  • Ответчик должен отбрасывать без уведомления все сообщения, где счётчик интервалов отличается от 1.

  • Ответчик должен отбрасывать без уведомления все сообщения для задачи GRASP, не являющейся напрямую частью частью службы, требующей этого незащищённого режима.

  • Ответчику недопустимо ретранслировать групповые сообщения.

  • Сообщение Discovery Response должно указывать адрес link-local.

  • В сообщение Discovery Response недопустимо включать опцию Divert.

  • Узел должен отбрасывать без уведомления все сообщения, отправленные с адреса, отличного от link-local.

Для минимизации доступности трафика посторонним следует снижать трафик GRASP, используя лишь сообщения Flood Synchronization для анонсирования задач и соответствующих локаторов (адресов) вместо отправки сообщений Discovery и Discovery Response. Детали этого выходят за рамки этого документа.

2.5.3. Использование транспортного уровня

Все сообщения GRASP после их преобразования в строку байтов CBOR передаются с использованием выбранного транспортного протокола. Транспортные протоколы для домена GRASP определяет подложка защиты и транспорта, как описано в параграфе 2.5.1.

Сообщения GRASP для обнаружения и лавинной отправки разработаны для лавинной передачи (flooding) в масштабе домена GRASP с использованием поэтапной (hop-by-hop) групповой (link-local) пересылки между смежными узлами GRASP. Подложка защиты и транспорта GRASP нужна для задания способа транспортировки групповых пакетов link-local. Это может быть транспорт без гарантии доставки (UDP), но следует выбирать надёжный транспорт (например, TCP). Если подложка задаёт для сообщений обнаружения и лавинной передачи транспорт без гарантии доставки, такой как UDP, недопустимо использовать фрагментацию IP по причине возможных потерь, особенно в случае лавинной рассылки через несколько этапов. Поэтому протокол GRASP должен на уровне пользовательского API задать предельный размер сообщений при обнаружении и лавинной отправке, чтобы не возникало фрагментации. Для транспорта IPv6 это означает, что размер пакетов IPv6 с такими сообщениями должен быть не более 1280 байтов (если нет информации о том, что MTU во всем домене GRASP имеет большее значение).

Все остальные сообщения GRASP передаются индивидуально между членами группы из домена GRASP. Для них должен применяться транспорт с гарантией доставки, поскольку протокол GRASP не поддерживает обнаружения ошибок, повтора передачи и управления потоком данных. Если подложка защиты и транспорта не задаёт иное, должен применяться протокол TCP.

Подложкой защиты и транспорта для GRASP в инфраструктуре ANI является плоскость управления ACP. Если явно не указано иное, в этом документе при описании сообщений GRASP предполагается такая подложка. В ACP для индивидуальных сообщений GRASP применяется протокол TCP. Сообщения GRASP для обнаружения и лавинной передачи также используют TCP, эти сообщения link-local пересылаются путём репликации всем смежным узлам GRASP на канале через соединения TCP с этими узлами GRASP. Поэтому GRASP в ANI не ограничивает размер сообщений для обнаружения и лавинной отправки из за фрагментации. При создании ACP с использованием экземпляра DULL GRASP, применяется естественная групповая передача UDP для обнаружения соседей ACP и GRASP на каналах.

Для групповых (link-local) пакетов UDP протокол GRASP прослушивает стандартный порт GRASP Listen (параграф 2.6). Транспортные соединения для обнаружения и лавинной передачи на узлах-трансляторах завершаются в экземплярах GRASP (например, GRASP ASA) так, что групповая (link-local) адресация с поэтапной лавинной рассылкой сообщений M_DISCOVERY и M_FLOOD, а также поэтапная пересылка откликов M_RESPONSE и их кэширование на пути работают корректно.

Индивидуальные транспортные соединения, используемые для синхронизации и согласования, могут завершаться непосредственно в агентах ASA, реализующих задачи, поэтому такому трафику не нужно проходить через экземпляры GRASP. Для этого ASA прослушивают свой динамически выделенный порт, который сообщается партнёру в процессе обнаружения. Можно завершать индивидуальные транспортные соединения в экземплярах GRASP и передавать трафик агенту ASA или от него, если это удобней для реализации (например, для отвязывания агентов ASA от сетевых соединений).

2.5.4. Механизм и процедуры обнаружения

2.5.4.1. Разделение механизмов обнаружения и согласования

Хотя обнаружение и согласование или синхронизация определены с GRASP, это отдельные механизмы. Процесс обнаружения может работать независимо от процесса согласования или синхронизации. При получении сообщения Discovery (параграф 2.8.4) узлу следует передать в ответ Discovery Response, в котором указать себя как ответчика при обнаружении или перенаправить инициатора к более подходящему агенту ASA. Однако этот отклик можно отложить, если получателю нужно ретранслировать сообщение Discovery дальше, как описано в параграфе 2.5.4.4.

За действием по обнаружению (M_DISCOVERY) обычно следует действие для согласования (M_REQ_NEG) или синхронизации (M_REQ_SYN). Результат обнаружения может применяться протоколом согласования для выбора ASA, с которым инициатор будет выполнять согласование.

Инициатор обнаружения для данной цели не обязан реагировать на эту цель как участник согласования, ответчик при синхронизации или источник лавинной передачи. Например, ASA может выполнить обнаружение даже если он хочет выступать лишь инициатором синхронизации или согласования. Такому агенту ASA не требуется отвечать на сообщения Discovery.

Обнаружение GRASP можно применять без последующего согласования или синхронизации. В этом случае обнаруженная задача просто используется как имя в процессе обнаружения, а последующие операции между партнёрами выполняются без участия GRASP.

2.5.4.2. Обзор процесса обнаружения

Полный процесс обнаружения начинается с передачи группового сообщения Discovery (M_DISCOVERY) в локальный канал. Поддерживающие задачу соседи по локальному каналу будут напрямую отвечать сообщениями Discovery Response (M_RESPONSE). Соседи с несколькими интерфейсами могут отвечать кэшированными сообщениями Discovery Response. При отсутствии кэшированного отклика такой сосед будет транслировать сообщение Discovery в другие свои интерфейсы GRASP. Если получивший ретранслированное сообщение Discovery узел поддерживает задачу для обнаружения, он будет отвечать на полученное сообщение Discovery. При наличии кэшированного отклика будет он передаваться в ответ, а при отсутствии будет повторяться ретрансляция другим узлам. Счётчик интервалов и тайм-аут обеспечивают завершение итерационного процесса. Дополнительные детали приведены в параграфе 2.5.4.4.

Сообщение Discovery может передаваться по индивидуальному адресу соседу и тому следует обрабатывать сообщение как в случае групповой передачи, за исключением того, что при использовании TCP отклик будет в том же сокете, который принял запрос. Однако этом метод не гарантирует успешной доставки в общем случае.

2.5.4.3. Процедуры обнаружения

Обнаружение запускается как операция на канале (on-link). Опция Divert может предложить инициатору связаться для обнаружения с расположенным вне канала агентом ASA. Если подложка защиты и транспорта в домене GRASP (параграф 2.5.3) использует групповую адресацию UDP link-local, инициатор передаёт сообщение по групповому адресу ALL_GRASP_NEIGHBORS (link-local, параграф 2.6), который должны прослушивать все узлы GRASP, чтобы выступать при обнаружении в качестве ответчиков. Поскольку этот порт уникален на устройстве, это относится к функциям экземпляра GRASP, а не отдельных ASA. В результате каждому агенту ASA нужно зарегистрировать поддерживаемые им задачи в локальном экземпляре GRASP.

Если ASA в соседнем устройстве поддерживает запрошенную задачу для обнаружения, устройству следует отвечать на групповой пакет индивидуальным сообщением Discovery Response (параграф 2.8.5) с опциями адреса (locator, параграф 2.9.5), если адрес не является временно недоступным. В ином случае при наличии у соседа кешированных данных об агенте ASA, поддерживающем задачу для обнаружения (найденную раньше), ему следует отвечать сообщением Discovery Response с опцией Divert, указывающей нужного ответчика. Однако не следует возвращать кэшированный отклик через интерфейс, получивший эти сведения, поскольку искомый партнёр будет отвечать напрямую, если он продолжает работать.

Если у устройства нет сведений о запрошенной задаче и он не является ретранслятором при обнаружении (см. параграф 2.5.4.4), он должен просто отбросить сообщение Discovery.

Инициатор обнаружения должен установить для процесса обнаружения разумный тайм-аут. Предлагается использовать значение 100 мсек, умноженное на счётчик интервалов (loop count), встроенный в задачу. Если в течение заданного времени не получено сообщение Discovery Response, можно повторить Discovery с генерацией нового Session ID (параграф 2.7). Следующие повторы следует выполнять с экспоненциальным ростом интервала для снижения нагрузки в пиковые периоды. Детали алгоритма увеличения интервалов зависят от варианта применения для искомой задачи, но должны соответствовать рекомендациям [RFC8085] для объёмного группового трафика. Частые повторы могут быть признаком DoS-атаки (denial-of-service).

После того, как устройство GRASP обнаружит локатор (адрес) ответчика, поддерживающего искомую задачу, ему следует кэшировать эту информацию, включая индекс интерфейса [RFC3493], через который она получена. Эта кэш-запись может использоваться в будущем для согласования или синхронизации, а локатор следует передавать, когда это уместно, в опции Divert инициаторам других обнаружений. Механизм кэширования должен включать срок действия каждой записи. Это время выводится из параметра ttl в каждом сообщении Discovery Response. Кэшированные записи должны игнорироваться или удаляться по истечении срока действия. В некоторых средах могут незапланированно меняться адреса. В таких случаях срок действия записей следует делать коротким по сравнению со средним сроком действия адресов. Механизм обнаружения должен отслеживать текущий адрес узла, чтобы сообщения Discovery Response всегда указывали корректные адреса.

Если для одной задачи найдено несколько ответчиков, следует кэшировать все, если это не ведёт к нехватке ресурсов. Метод выбора ответчиков для кэширования зависит от реализации и должен быть доступен каждому агенту ASA, а реализации GRASP следует задавать принятый по умолчанию выбор.

Поскольку кэш для ответчиков при обнаружении имеет конечный размер, записи могут удаляться в любой момент. В таких случаях потребуется повторять обнаружения. Если агент ASA по какой-либо причине завершает работу, его локатор может некоторое время сохраняться в кэше, а попытки соединения будут приводить к отказу. Агенты ASA должны быть устойчивы к таким отказам.

2.5.4.4. Ретрансляция при обнаружении

Экземпляр GRASP с несколькими интерфейсами канального уровня (обычно работает как маршрутизатор) должен поддерживать обнаружение на всех интерфейсах GRASP. Такие экземпляры называются ретрансляторами (relaying instance). Экземпляры DULL (параграф 2.5.2) всегда имеют лишь 1 интерфейс, поэтому им недопустимо ретранслировать сообщения при обнаружении.

Если ретранслятор получает на данном интерфейсе сообщение Discovery для конкретной задачи, которую он не поддерживает и для которой в данный момент нет кэшированного отклика, он должен транслировать запрос, передав новое сообщение Discovery по групповому адресу link-local через другие свои интерфейсы GRASP. Ретранслируемое сообщение Discovery должно иметь такой же идентификатор Session ID и поле initiator, что и в принятом сообщении (см. параграф 2.8.4). Адрес IP в поле initiator служит лишь для устранения неоднозначности Session ID и никогда не применяется для адресации сообщений Response. Пакеты откликов передаются ретранслирующему экземпляру, а не исходному инициатору.

Сообщение M_DISCOVERY не кодирует транспортный адрес инициатора или ретранслятора. Поэтому пакеты откликов должны передаваться по адресу транспортного уровня в соединении, где получено сообщение M_DISCOVERY. Если сообщение M_DISCOVERY транслировалось через надёжное поэтапное (hop-by-hop) транспортное соединение, отклик просто возвращается в то же соединение.

Если ретрансляция M_DISCOVERY была групповой (link-local, например, UDP), отклик возвращается через надёжное транспортное соединение hop-by-hop с тем же номером порта отправителя в групповой передаче link-local. Поэтому , если применяется групповая передача link-local и требуются сообщения M_RESPONSE (это происходит практически во всех экземплярах GRASP, за исключением ограниченного применения экземпляров DULL в инфраструктуре ANI), протокол GRASP должен быть способен связать номер порта UDP, откуда были отправлены исходные групповые (link-local) сообщения M_DISCOVERY с тем же номером порта гарантированного транспорта hop-by-hop (например, TCP), чтобы иметь возможность отвечать на транспортные соединения ответчиков, которые хотят передать сообщения M_RESPONSE назад. Отметим, что это не обязательно порт GRASP_LISTEN_PORT.

Ретранслирующий экземпляр должен уменьшить значение loop count в задаче и ему недопустимо транслировать сообщение Discovery если значение счётчика снизилось до 0. Ретранслятор также должен ограничивать общую скорость трансляции сообщений Discovery разумным значением, чтобы смягчить возможные DoS-атаки. Например, в качестве предельной скорости можно установить кратное небольшому числу значение наблюдаемой скорости сообщений Discovery в процессе нормальной работы. Транслирующий экземпляр должен кэшировать значение Session ID и адрес инициатора из каждого транслируемого сообщения Discovery, пока не будет получено сообщение Discovery Response или процесс обнаружения не завершится по тайм-ауту. Чтобы не возникало петель, недопустимо транслировать сообщения Discovery с данными Session ID и адресом инициатора более одного раза. Это предотвратит петли при обнаружении и смягчит возможную перегрузку.

Поскольку ретранслятор не знает значения тайм-аута, установленного исходным инициатором, ему следует устанавливать подходящий тайм-аут для транслируемого сообщения Discovery. Предлагается использовать значение 100 мсек, умноженное на остающееся значение счётчика интервалов (loop count).

Результаты обнаружения, полученные транслирующим экземпляром, должны передаваться как сообщение Discovery Response в ответ на вызвавшее ретрансляцию сообщение Discovery.

2.5.4.5. Быстрый режим — обнаружение с согласованием или синхронизацией

Сообщение Discovery может включать опцию задачи, что позволяет применять быстрый режим согласования (параграф 2.5.5.1) или синхронизации (параграф 2.5.6.3). Быстрый режим в настоящее время ограничен одной целью для простоты проектирования и реализации. В будущем возможны расширения, позволяющие использовать в быстром режиме несколько целей для повышения эффективности.

2.5.5. Процедуры согласования

Инициатор согласования создаёт транспортное соединение с агентом ASA на другой стороне, используя адрес, протокол и порт, полученные при обнаружении. Затем он передаёт запрос согласования (используя M_REQ_NEG), включая в него конкретную задачу для согласования. Можно запросить у партнёра создание конкретной конфигурации, а также запросить то или иное моделирование или предсказание результата, передав пробную (dry-run) конфигурацию. Детали, включая отличие между пробным запуском и реальным изменением конфигурации, будут описаны отдельно для каждого типа целей согласования. Любое состояние, связанное с пробным прогоном, такое как временное резервирование ресурсов для последующего применения в реальной работе, полностью зависит от разработчика соответствующего агента ASA.

Для каждого сеанса согласования в целом применяется тайм-аут (по умолчанию GRASP_DEF_TIMEOUT мсек, см. параграф 2.6), инициализируемый при отправке запроса (параграф 2.8.6). Если в течение заданного времени не получен какой-либо отклик, запрос согласования можно повторить с новым Session ID (параграф 2.7). При последующих повторах интервал следует экспоненциально увеличивать. Детали алгоритма роста интервалов зависят от варианта применения и цели запроса.

Если партнёр может сразу же применить запрошенную конфигурацию, он будет незамедлительно давать положительный ответ (O_ACCEPT) в сообщении Negotiation End (M_END), который завершает фазу согласования. В иных случаях согласование продолжается с использованием M_NEGOTIATE. Партнёр может ответить предлагаемой конфигурацией, которую он может применить (обычно с использованием меньших по сравнению с запросом ресурсов). Далее происходит взаимное согласования с использованием сообщений Negotiate (M_NEGOTIATE), пока между агентами ASA не будет достигнут компромисс.

Процедура согласования завершается, когда один из партнёров отправит сообщение Negotiation End (M_END) с опцией Accept (O_ACCEPT) или Decline (O_DECLINE), которое не требует отклика. Согласование может также завершиться по сбою (эквивалентно Decline), если возникнет тайм-аут или счётчик интервалов достигнет 0. При завершении по любой причине транспортное соединение следует закрыть. Отказ в транспортной сессии считается сбоем согласования.

Процедура согласования относится к одной задаче и одному партнёру. Обе стороны согласования могут в то же время выполнять согласование с другими ASA или согласовывать между собой другую задачу. Таким образом, предполагается использование GRASP в многопотоковом режиме или его логическом эквиваленте. У некоторых задач согласования могут быть ограничения на использование нескольких потоков, например, для предотвращения чрезмерного выделения ресурсов.

Некоторые конфигурационные действия, например, переключение длины волны в оптической сети, могут выполняться достаточно долго. Соответствующие агенты ASA должны учитывать это, а протокол GRASP позволяет при необходимости вносить задержку в процесс согласования (параграф 2.8.9, M_WAIT).

2.5.5.1. Быстрый режим

Сообщение Discovery может включать опцию Negotiation Objective. Это соответствует отправке инициатором последовательности M_DISCOVERY за которой сразу следует M_REQ_NEG. Это влияет на ядро GRASP, поскольку оно должно аккуратно передавать содержимое опции Negotiation Objective агенту ASA, чтобы он мог оценить задачу напрямую. При наличии опции Negotiation Objective агент ASA отвечает сообщением M_NEGOTIATE (или M_END с O_ACCEPT, если предложение сразу подходит ему) вместо M_RESPONSE. Если принявший узел не поддерживает быстрый режим, обнаружение происходит как обычно.

Сообщение Discovery Response может прийти от ответчика, не поддерживающего быстрый режим, до того, как прибудет сообщение Negotiation. В этом случае быстрый режим не сработает.

Этот быстрый режим может сократить взаимодействие между узлами, что позволит повысить эффективность. Однако в сети, где быстрый режим поддерживает лишь часть узлов, поведение усложняется и может зависеть от времени. Поэтому функцию быстрого согласования по умолчанию следует отключать.

2.5.6. Синхронизация и процедуры лавинной рассылки

2.5.6.1. Синхронизация по индивидуальным адресам

Инициатор синхронизации создаёт транспортное соединение с агентом ASA на другой стороне, используя адрес, протокол и порт, полученные при обнаружении. Затем он передаёт партнёру сообщение Request Synchronization (M_REQ_SYN, параграф 2.8.6), указывающую конкретную задачу для синхронизации. Партнёр отвечает сообщением Synchronization (M_SYNCH, параграф 2.8.10) с текущим значением синхронизируемой задачи. Других сообщений не требуется и транспортное соединение следует закрыть. Отказ в транспортном соединении считается сбоем синхронизации.

Если не получено никакого отклика в течение заданного времени (по умолчанию GRASP_DEF_TIMEOUT мсек, параграф 2.6), запрос синхронизации можно повторить с новым Session ID (параграф 2.7). При последующих повторах интервал между ними следует экспоненциально увеличивать. Детали алгоритма увеличения интервалов зависят от варианта применения для соответствующей задачи.

2.5.6.2. Лавинная рассылка

В только что описанном случае обмен сообщениями происходит по индивидуальным адресам и связан лишь с одной задачей для синхронизации. Для больших групп узлов, которым нужно синхронизировать одни данные, можно применять лавинную синхронизацию. Для этого инициатор может передать незапрошенное сообщение Flood Synchronization (параграф 2.8.11) с одной или несколькими опциями Synchronization Objective, если спецификация соответствующих задач разрешает это. Сообщение передаётся по групповому адресу ALL_GRASP_NEIGHBORS (параграф 2.6). Приём групповых лавинных сообщений является функцией ядра GRASP, как при групповом обнаружении (параграф 2.5.4.3).

Чтобы при лавинной передаче не возникало петель, отправитель сообщения Flood Synchronization должен установить подходящее значение счётчика интервалов (loop count) в задачах (по умолчанию GRASP_DEF_LOOPCT). Также нужен специальный механизм для предотвращения избыточного группового трафика, которых должен определяться как часть спецификации соответствующих задач для синхронизации. Это может быть простое ограничение скорости или более сложный механизм вроде алгоритма Trickle [RFC6206].

Устройство GRASP с несколькими интерфейсами канального уровня (обычно маршрутизатор) должно поддерживать лавинную синхронизацию на всех интерфейсах GRASP. При получении группового сообщения Flood Synchronization на данном интерфейсе оно должно транслироваться как групповое (link-local) сообщение Flood Synchronization во все остальные интерфейсы GRASP. Транслируемое сообщение должно иметь то же значение Session ID, что и принятое сообщение, а также должно помечаться IP-адресом исходного инициатора.

Лавинная рассылка на канальном уровне поддерживается GRASP путём установки для loop count значения 1 и передачи с адресом отправителя link-local. Лавинная передача с адресом отправителя link-local и счётчиком интервалов, отличным от 1 недопустима и такие сообщения должны отбрасываться.

Трансляторы должны уменьшать loop count в первой задаче и недопустимо транслировать сообщение Flood Synchronization при достижении счётчиком 0. Трансляторы также должны ограничивать скорость ретрансляции Flood Synchronization разумным значением для смягчения возможных DoS-атак. Например, скорость можно ограничить значением наблюдаемой скорости лавинной передачи, умноженным на небольшой коэффициент. Транслятор должен кэшировать Session ID и адрес инициатора для каждого ретранслируемого сообщения Flood Synchronization на время, не превышающее 2*GRASP_DEF_TIMEOUT мсек. Для предотвращения петель недопустимо транслировать сообщения Flood Synchronization с кэшированными значениями Session ID и адреса инициатора более 1 раза. Это позволит избежать петель при синхронизации и смягчит возможную перегрузку.

Этот механизм надёжен в случае спящих узлов, новых узлов, присоединяющихся к сети, а также узлов, возвращающихся в сеть после отказа. Агенту ASA, инициирующему лавинную передачу, следует повторять её с подходящей частотой, которая должна соответствовать рекомендациям [RFC8085] для группового трафика с невысоким объёмом. ASA также следует выступать ответчиком при синхронизации для соответствующих задач. Таким образом, узлы, которым нужна задача, вовлечённая в лавинную передачу, могут подождать следующей лавинной отправки или запросить индивидуальную (unicast) синхронизацию для этой задачи.

Для групповых сообщений лавинной синхронизации применимы правила безопасности параграфа 2.5.1. На практике это означает, что такие сообщения недопустимо передавать и они должны игнорироваться при получении, если не нет работающей плоскости управления ACP или эквивалентной по силе защиты. Однако по причине слабой защиты групповых сообщение link-local (раздел 3), задачам, участвующим в лавинной синхронизации, не следует включать нешифрованных приватных данных, а принимающему агенту ASA следует проверять действительность этих задач.

2.5.6.3. Быстрый режим (связывание обнаружения и синхронизации)

Сообщение Discovery может включать опцию Synchronization Objective. В этом случае сообщение Discovery выступает одновременно как Request Synchronization для индикации ответчику при обнаружении возможности ответить инициатору обнаружения напрямую сообщением Synchronization (параграф 2.8.10) с данными синхронизации для быстрой обработки, если цель обнаружения поддерживает соответствующую задачу для синхронизации. Влияние организации сети аналогично описанному в параграфе 2.5.5.1.

Возможны случаи, когда сообщение Discovery Response будет приходить от ответчика, не поддерживающего быстрый режим, до прихода сообщения Synchronization. В этом случае быстрый режим не сработает.

Этот быстрый режим может сократить взаимодействие между узлами, что позволит повысить эффективность. Однако в сети, где быстрый режим поддерживает лишь часть узлов, поведение усложняется и может зависеть от времени. Поэтому функцию быстрой синхронизации по умолчанию следует отключать и можно включать или отключать через Intent.

2.6. Константы GRASP

ALL_GRASP_NEIGHBORS

Групповой адрес с зоной действия на локальном канале (link-local), используемый поддерживающими GRASP устройствами для обнаружения соседей с поддержкой GRASP (т. е. включённых в канал — on-link). Все поддерживающие GRASP устройства являются членом этой группы.
  • Групповой адрес IPv6 — ff02::13.
  • Групповой адрес IPv4 — 224.0.0.119.

GRASP_LISTEN_PORT (7017)

Общеизвестный пользовательский порт UDP которое каждое устройство с поддержкой GRASP должно прослушивать на предмет групповых (link-local) сообщений при использовании экземпляром GRASP протокола UDP для сообщений M_DISCOVERY или M_FLOOD. Этот порт можно также использовать для прослушивания индивидуальных сообщений TCP или UDP в простых реализациях GRASP (параграф 2.5.3).

GRASP_DEF_TIMEOUT (60000 мсек)

Принятый по умолчанию тайм-аут, используемый для определения незавершённых операций (отказов).

GRASP_DEF_LOOPCT (6)

Принятое по умолчанию значение счётчика интервалов (loop count), используемое для определения незавершённых операций и предотвращения петель.

GRASP_DEF_MAX_SIZE (2048)

Принятый по умолчанию максимальный размер сообщения в байтах.

2.7. Идентификатор сессии (Session ID)

Идентификатором сессии служит 32-битовое необрабатываемое (opaque) значение, используемое для различения сессий между парой устройств. Новое значение Session ID должно создаваться инициатором для каждого нового сообщения Discovery, Flood Synchronization, Request. Все отклики и последующие сообщения в той же процедуре обнаружения, синхронизации или согласования должны применять одно значение Session ID.

Для Session ID следует обеспечивать очень низкую вероятность локальных конфликтов. Идентификаторы должны создаваться генератором псевдослучайных чисел (pseudorandom number generator или PRNG) с использованием созданной локально затравки (seed), которая вряд ли будет использована другим устройством в той же сети. PRNG следует быть криптостойким [RFC4086]. При выделении нового Session ID протокол GRASP должен проверять, не используется ли это значение, а также следует проверить, что оно не применялось недавно (просмотр кэша сессий). В маловероятном случае конфликта GRASP должен создать новое значение идентификатора. Однако имеется ненулевая вероятность того, что два узла сгенерируют одно значение Session ID. Поэтому при обмене Session ID через GRASP принимающая сторона должна пометить идентификатор IP-адресом инициатора, чтобы предотвратить неоднозначность. В крайне маловероятном случае создание двумя партнёрами сессий с одним значением Session ID тег позволит различить эти сессии. Групповые сообщения GRASP и отклики на них, транслируемые между каналами, по этой причине включают глобальный (публичный) IP-адрес инициатора.

С крайне малой вероятностью два партнёра могут начать одновременные сеансы согласования с одним Session ID. В зависимости от реализации это может привести к путанице между сессиями. Меры предотвращения этого описаны в параграфе 2.8.6.

2.8. Сообщения GRASP

2.8.1. Обзор сообщений

В этом параграфе определён формат и типы сообщений GRASP. Не указанные здесь типы являются резервными. Определённые в настоящее время сообщения перечислены ниже.

Discovery и Discovery Response (M_DISCOVERY, M_RESPONSE).

Request Negotiation, Negotiation, Confirm Waiting, Negotiation End (M_REQ_NEG, M_NEGOTIATE, M_WAIT, M_END).

Request Synchronization, Synchronization, Flood Synchronization (M_REQ_SYN, M_SYNCH, M_FLOOD).

No Operation и Invalid (M_NOOP, M_INVALID).

2.8.2. Формат сообщений GRASP

Сообщения GRASP используют идентичные заголовки и область опций с меняющимся форматом. Заголовки и опции передаются в сжатом двоичном представлении (Concise Binary Object Representation или CBOR) [RFC8949]. В этой спецификации они описываются на языке краткого определения данных CDDL (Concise Data Definition Language) [RFC8610]. Для каждого элемента в этом описании применяется фрагментарный формат CDDL. Полная нормативная спецификация CDDL для протокола GRASP приведена в разделе 4 и включает константы, такие как типы сообщений.

Каждое сообщение GRASP (кроме No Operation) содержит Session ID (параграф 2.7). Затем размещается цепочка опций. Во фрагментарной форме CDDL каждое сообщение GRASP имеет показанный ниже вид.

     grasp-message = (message .within message-structure) / noop-message

     message-structure = [MESSAGE_TYPE, session-id, ?initiator, *grasp-option]

     MESSAGE_TYPE = 0..255
     session-id = 0..4294967295 ; до 32 битов
     grasp-option = any

MESSAGE_TYPE указывает тип сообщения, который определяет ожидаемые опции. Любые полученные опции, которые не соответствуют MESSAGE_TYPE следует просто отбрасывать.

Сообщение No Operation (noop — нет операций) описано в параграфе 2.8.13. Значения MESSAGE_TYPE определены в разделе 4. Остальные элементы сообщений описаны ниже и формально определены в разделе 4.

При получении неизвестного MESSAGE_TYPE в индивидуальном (unicast) сообщении можно передавать в ответ сообщение Invalid (параграф 2.8.12). В ином случае сообщение может быть записано в системный журнал (log) и должно быть отброшено. Если неизвестный тип MESSAGE_TYPE получен в групповом сообщении это может быть записано в системный журнал, а сообщение должно быть отброшено.

2.8.3. Размер сообщения

Узлы GRASP должны поддерживать приём индивидуальных сообщений размером по меньшей мере GRASP_DEF_MAX_SIZE байтов. Узлам GRASP недопустимо передавать индивидуальные сообщения размером больше GRASP_DEF_MAX_SIZE, если больший размер явно не разрешён для соответствующей задачи. Например, можно использовать согласование GRASP для установки большего размера сообщений.

Используемому в GRASP синтаксическому анализатору сообщений следует знать GRASP_DEF_MAX_SIZE или согласованный больший размер, чтобы можно было защититься от чересчур больших сообщений.

Максимальный размер групповых сообщений M_DISCOVERY и M_FLOOD зависит от технологии канального уровня или используемого уровня адаптации канала.

2.8.4. Сообщение Discovery

Фрагментарная форма CDDL для сообщения Discovery имеет вид

     discovery-message = [M_DISCOVERY, session-id, initiator, objective]

Инициатор обнаружения передаёт сообщение Discovery для запуска обнаружения конкретной задачи. Инициатор передаёт все сообщения Discovery по протоколу UDP через порт GRASP_LISTEN_PORT по групповому адресу link-local ALL_GRASP_NEIGHBORS на каждом интерфейсе канального уровня, используемом протоколом GRASP. Затем он прослушивает индивидуальные отклики TCP на данном порту и сохраняет результаты обнаружения, включая задачи и соответствующие индивидуальные адреса (локаторы).

Прослушиваемый порт TCP должен совпадать с портом UDP, используемым для групповой передачи Discovery на данном интерфейсе. В реализации с одним экземпляром GRASP на узле это может быть порт GRASP_LISTEN_PORT. Для поддержки на узле нескольких экземпляров механизму обнаружения в каждом экземпляре GRASP требуется найти на каждом интерфейсе динамический порт для передачи групповых пакетов (link-local) UDP и прослушивания откликов TCP до запуска обнаружения.

Поле initiator в сообщении содержит уникальный в глобальном масштабе IP-адрес инициатора с единственной целью — устранить неоднозначность Session ID (совпадение с другими узлами). Если у инициатора нет такого адреса IP, он должен использовать адрес link-local, который с высокой вероятностью будет уникальным для этой цели (например, использовать [RFC7217]). Определение для узла глобально уникального адреса IP зависит от реализации.

Сообщение Discovery должно включать в точности 1 из указанных ниже опций.

  • Опция Discovery (параграф 2.10.1). Для loop count должно быть установлено подходящее значение, чтобы предотвратить петли при обнаружении (по умолчанию GRASP_DEF_LOOPCT). Если инициатору обнаружения нужны отклики или от его канала, для loop count должно устанавливаться значение 1.

  • Опция Negotiation (параграф 2.10.1) применяется для обнаружения и указания того, что цель обнаружения может напрямую отвечать инициатору сообщением Negotiation для быстрой обработки, если она может выступать партнёром соответствующего согласования. Отправитель такого сообщения Discovery должен запустить таймер согласования и установить для loop count, как это делается для сообщения Request Negotiation (параграф 2.8.6).

  • Опция Synchronization (параграф 2.10.1) применяется для обнаружения и указания того, что цель обнаружения может напрямую отвечать инициатору сообщением Synchronization для быстрой обработки, если она может выступать партнёром соответствующей синхронизации. Для loop count должно устанавливаться подходящее значение, чтобы предотвратить петли при обнаружении (по умолчанию GRASP_DEF_LOOPCT).

Как отмечено в параграфе 2.5.4.2, сообщения Discovery можно передавать по индивидуальному адресу партнёра, при этом его следует обрабатывать так же как при групповой передаче.

2.8.5. Сообщение Discovery Response

Фрагментарная форма CDDL для сообщения Discovery Response имеет вид

     response-message = [M_RESPONSE, session-id, initiator, ttl,
                         (+locator-option // divert-option), ?objective]

     ttl = 0..4294967295 ; в миллисекундах

Получившему сообщение Discovery узлу следует передавать ответное сообщение Discovery Response тогда и только тогда, когда он может ответить на запрос обнаружения.

Сообщение должно содержать Session ID и поле initiator из сообщения Discovery.

Сообщение должно содержать поле ttl, указывающее срок действия отклика целым положительным числом миллисекунд. для того, чтобы отклик был действительным. Значение 0 предполагает срок действия значительно больше GRASP_DEF_TIMEOUT (параграф 2.6). Рекомендуется значение в 10 раз больше GRASP_DEF_TIMEOUT.

Сообщение может включать копию задачи обнаружения из сообщения Discovery.

Сообщение передаётся отправителю Discovery по протоколу TCP через порт, использованный для Discovery, как описано в параграфе 2.8.4. При ответе на ретранслированное сообщение Discovery Response передаётся транслятору, а не исходному инициатору. Во всех случаях транспортную сессию следует закрывать после передачи Discovery Response. Отказ в транспортной сессии считается отсутствием отклика.

Если отвечающий узел поддерживает задачу для обнаружения, он должен включить хотя бы одну опцию локации любого типа (параграф 2.9.5) для указания своего местоположения. Допускается последовательность разнотипных опций локации (например, адрес IP и имя FQDN).

Если отвечающий узел сам не поддерживает задачу для обнаружения, но знает его локатор, следует ответить на сообщение Discovery опцией Divert (параграф 2.9.2), содержащей опцию локации или комбинацию таких опций, указывающую искомую задачу. Обработка Discovery Response описана более подробно в параграфе 2.5.4.

2.8.6. Запросы согласования и синхронизации

Фрагментарные формы CDDL для сообщений Request Negotiation и Request Synchronization имеют вид

   request-negotiation-message = [M_REQ_NEG, session-id, objective]
   request-synchronization-message = [M_REQ_SYN, session-id, objective]

Запрашивающий синхронизацию или согласование узел передаёт соответствующий запрос по индивидуальному адресу партнёра, используя подходящий протокол и номер порта (по результату обнаружения). Если при обнаружении была возвращено доменное имя FQDN, сначала выполняется распознавание (определение адреса).

Сообщение Request должно включать относящуюся к делу опцию задачи. В случае Request Negotiation эта опция должна содержать запрашиваемое значение.

При отправке Request Negotiation инициатор должен запустить таймер согласования для нового потока. По умолчанию для таймера установлено значение GRASP_DEF_TIMEOUT мсек. Если этот тайм-аут не был изменён сообщением Confirm Waiting (параграф 2.8.9), инициатор по завершении отсчёта таймера будет считать согласование неудачным.

При отправке Request Synchronization инициатору следует запустить таймер синхронизации (по умолчанию GRASP_DEF_TIMEOUT мсек). По завершении отсчёта таймера инициатор считает синхронизацию неудачной.

При отправке запроса инициатор должен установить для loop count в опции задачи значение, заданное спецификацией опции или (если оно не задано) установить GRASP_DEF_LOOPCT.

При получении узлом запроса для цели, которую в данный момент не прослушивает ни один агент ASA, он должен сразу же закрыть соответствующий сокет для индикации инициатору. Это позволяет избежать ненужных тайм-аутов, если, например, ASA преждевременно завершил работу, но ядро GRASP прослушивает сокеты от его имени.

Для предотвращения крайне маловероятного конфликта, когда два узла одновременно запрашивают между собой сессии с одним Session ID (параграф 2.7), узел при получении запроса должен проверить, что полученное значение Session ID не используется локально. В случае конфликта узел должен отбросить запрос, а инициатор обнаружит это по тайм-ауту.

2.8.7. Сообщение Negotiation

Фрагментарный формат CDDL для сообщения Negotiation имеет вид

     negotiation-message = [M_NEGOTIATE, session-id, objective]

Партнёр по согласованию передаёт Negotiation в ответ на Request Negotiation, Negotiation или Discovery в быстром режиме. Процесс согласования может выполняться в несколько этапов.

Сообщение Negotiation должно включать подходящую опцию Negotiation Objective с обновлением значения в соответствии с ходом согласования. Отправитель должен уменьшить значение loop count на 1. Если этот счётчик достигает 0, передавать сообщение недопустимо. В этом случае сеанс согласования завершается по тайм-ауту.

2.8.8. Сообщение Negotiation End

Фрагментарный формат CDDL для сообщения Negotiation End имеет вид

     end-message = [M_END, session-id, accept-option / decline-option]

Партнёр по согласованию передаёт Negotiation End для завершения процедуры согласования. Сообщение должно включать опцию Accept (параграф 2.9.3) или Decline (параграф 2.9.4). Сообщение может передать любой из партнёров.

2.8.9. Сообщение Confirm Waiting

Фрагментарный формат CDDL для сообщения Confirm Waiting имеет вид

     wait-message = [M_WAIT, session-id, waiting-time]
     waiting-time = 0..4294967295 ; в миллисекундах

Отвечающий узел передаёт Confirm Waiting, чтобы попросить запросивший узел дождаться последующего ответа на согласование. Это может быть связано с тем, что локальному узлу требуется больше времени на согласование или это согласование зависит от другого выполняемого в данный момент. В сообщение недопустимо включать какие-либо опции. При получении указанное в сообщении время переопределяет время ожидания с перезапуском таймера текущего согласования (параграф 2.8.6).

Отвечающему узлу следует передавать Negotiation, Negotiation End или другое сообщение Confirm Waiting до завершения отсчёта таймера согласования. В противном случае при завершении отсчёта у инициатора тот должен будет счесть процедуру согласования неудачной.

2.8.10. Сообщение Synchronization

Фрагментарный формат CDDL для сообщения Synchronization имеет вид

     synch-message = [M_SYNCH, session-id, objective]

Узел, принявший Request Synchronization или Discovery в быстром режиме, возвращает индивидуальное сообщение Synchronization с данными синхронизации в форме опции GRASP для конкретной задачи синхронизации из Request Synchronization.

2.8.11. Сообщение Flood Synchronization

Фрагментарный формат CDDL для сообщения Flood Synchronization имеет вид

     flood-message = [M_FLOOD, session-id, initiator, ttl,
                      +[objective, (locator-option / [])]]

     ttl = 0..4294967295 ; в миллисекундах

Узел может инициировать лавинную передачу, отправляя незапрошенное сообщение Flood Synchronization с данными синхронизации. Его можно передать в порт GRASP_LISTEN_PORT по групповому (link-local) адресу ALL_GRASP_NEIGHBORS в соответствии с правилами параграфа 2.5.6. Адрес инициатора указывается в соответствии с описанием для сообщения Discovery (параграф 2.8.4) лишь для устранения неоднозначности Session ID.

Сообщение должно содержать поле ttl для проверки действительности содержимого в форме положительного целого числа миллисекунд. Принятого по умолчанию значение нет, 0 означает неограниченный срок действия.

Данные синхронизации представляются в форме опций GRASP для конкретных задач синхронизации. В счётчиках интервалов (loop count) должны устанавливаться подходящие значения для предотвращения петель (по умолчанию GRASP_DEF_LOOPCT).

За каждой опцией задачи может следовать опция локации (параграф 2.9.5), связанная с этой задачей. При отсутствии локации должна включаться пустая опция.

Получивший сообщение Flood Synchronization узел должен кэшировать задачи из него для использования локальными агентами ASA. Каждая кэшированная задача должна помечаться опцией локации, откуда она была получена, или пустым тегом, если была передана пустая опция локации. Если последующее сообщение Flood Synchronization содержит задачу с тем же именем и тегом, соответствующая кэшированная копия задачи должна переписываться. Если последующее сообщение Flood Synchronization для задачи с тем же именем имеет другой тег, в кэше должна создаваться новая запись.

Примечание. Цель этого механизма заключается в том, чтобы позволить получателю лавинных значений различать отправителей для одной задачи и при необходимости взаимодействия использовать локатор, протокол и порт из опции локации. Для многих задач это механизм не нужен и они будут рассылаться с пустой опцией локации.

Кэшированные записи должны игнорироваться или удаляться по истечении срока действия.

2.8.12. Сообщение Invalid

Фрагментарный формат CDDL для сообщения Invalid имеет вид

     invalid-message = [M_INVALID, session-id, ?any]

Реализация может передавать это сообщение в ответ на принятое индивидуальное сообщение, которое сочтено недействительным. Значение Session ID должно копироваться из полученного сообщения. В содержимом сообщения следует указывать диагностические данные, такие как частичная копия недействительного сообщения, вплоть до максимального размера сообщения. Получатель M_INVALID может просто отбрасывать такие сообщения. Однако их можно применять для поддержки расширяемости, поскольку они показывают, что удалённый узел не поддерживает новое или устаревшее сообщение или опцию. Сообщение M_INVALID недопустимо передавать в ответ на M_INVALID.

2.8.13. Сообщение No Operation

Фрагментарный формат CDDL для сообщения No Operation имеет вид

     noop-message = [M_NOOP]

Реализация может передавать это сообщение при практической необходимости инициализировать сокет. Получатель должен просто игнорировать сообщение.

2.9. Опции GRASP

В этом параграфе определены опции GRASP для сигнализации при согласовании и синхронизации. В будущем могут быть добавлены новые опции.

2.9.1. Формат опций GRASP

Опциям GRASP следует быть массивами CBOR, которые должны начинаться с целого числа без знака, указывающего тип опции. Формальные определения типов даны в разделе 4. Могут определяться опции GRASP, инкапсулирующие другие опции GRASP.

2.9.2. Опция Divert

Опция Divert служит для перенаправления запроса GRASP на другой узел, который более подходит для данного согласования или синхронизации. Это может быть перенаправление на объект, известный как партнёр для конкретного согласования или синхронизации (на канале или вне его), или принятый по умолчанию шлюз. Опция Divert должна инкапсулироваться лишь в сообщения Discovery Response. В других местах эту опцию следует просто игнорировать.

Инициатор обнаружения может игнорировать опцию Divert, если ему нужны лишь прямые сообщения Discovery Response.

Фрагментарная форма CDDL для опции Divert имеет вид

     divert-option = [O_DIVERT, +locator-option]

Вложенные опции локации (параграф 2.9.5) указывают перенаправленные цели в отклике на сообщение Discovery.

2.9.3. Опция Accept

Опция Accept применяется для указания партнёру по согласованию, что предложенные параметры приемлемы. Опция Accept должна инкапсулироваться лишь в сообщения Negotiation End, в других сообщениях её следует просто игнорировать.

Фрагментарная форма CDDL для опции Accept имеет вид

     accept-option = [O_ACCEPT]

2.9.4. Опция Decline

Опция Decline применяется для указания партнёру по согласованию, что предложенные параметры приемлемы и согласование на этом завершается. Опция Decline должна инкапсулироваться лишь в сообщения Negotiation End, в других сообщениях её следует просто игнорировать.

Фрагментарная форма CDDL для опции Decline имеет вид

     decline-option = [O_DECLINE, ?reason]
     reason = text  ; необязательное сообщение об ошибке (UTF-8)

Примечание. Агент ASA может отказаться от предложенного значения и повторно запустить согласование. При этом реализация может передать опцию Decline или продолжить согласование сообщением Negotiation с опцией задачи, содержащей пустое значение или новое значение, которое может привести к сходимости согласования.

2.9.5. Опции локации

Опции локации служат для представления сведений о доступности для ASA, устройства или интерфейса. Опции включают Locator IPv6 Address, Locator IPv4 Address, Locator FQDN, Locator URI.

Поскольку агенты ASA обычно работают как независимые пользовательские программы, опции локации нужны для указания локатора сетевого уровня, а также транспортного протокола и номера порта для доступа к задаче. По этой причине опции локации для адресов IP и имён FQDN включают эти сведения явно. В опции Locator URI эта информация встроена в URI.

Примечание. Предполагается, что все локаторы в этих опциях входят в область действия домена GRASP. Как сказано в параграфе 2.2, протокол GRASP не предназначен для работы в несвязанных областях адресации и именования.

2.9.5.1. Опция Locator IPv6 Address

Фрагментарная форма CDDL для опции Locator IPv6 Address имеет вид

     ipv6-locator-option = [O_IPv6_LOCATOR, ipv6-address, transport-proto, port-number]
     ipv6-address = bytes .size 16

     transport-proto = IPPROTO_TCP / IPPROTO_UDP
     IPPROTO_TCP = 6
     IPPROTO_UDP = 17
     port-number = 0..65535

Опция содержит двоичное представление адреса IPv6, за которым указаны номера протокола и порта.

Примечание 1. Адрес IPv6 должен обычно иметь глобальную область действия. Однако во время инициализации для конкретных задач может применяться адрес link-local (параграф 2.5.2). В этом случае соответствующее сообщение Discovery Response должно передаваться через интерфейс, к которому относится адрес link-local.

Примечание 2. Адрес IPv6 link-local недопустимо применять в этой опции, когда она включена в опцию Divert.

Примечание 3. Значения IPPROTO берутся из существующего реестра IANA Protocol Numbers для протоколов TCP и UDP. Если для GRASP потребуются отсутствующие в реестре значения, потребуется новый реестр для значений вне диапазона 0 — 255.

2.9.5.2. Опция Locator IPv4 Address

Фрагментарная форма CDDL для опции Locator IPv4 Address имеет вид

     ipv4-locator-option = [O_IPv4_LOCATOR, ipv4-address, transport-proto, port-number]
     ipv4-address = bytes .size 4

Опция содержит двоичное представление адреса IPv4, за которым указаны номера протокола и порта.

Примечание. Если оператор применяет внутреннюю трансляцию адресов IPv4, эту опцию недопустимо включать в опцию Divert.

2.9.5.3. Опция Locator FQDN

Фрагментарная форма CDDL для опции Locator FQDN имеет вид

     fqdn-locator-option = [O_FQDN_LOCATOR, text, transport-proto, port-number]

Опция содержит полное доменное имя FQDN, за которым указаны номера протокола и порта.

Примечание 1. Имена FQDN, которые могут быть недействительны в сети, такие как имена Multicast DNS [RFC6762], недопустимо применять для опции, помещаемой в опцию Divert.

Примечание 2. При обычной работе GRASP применение этой опции не предполагается. Она предназначена для специальных задач, таких как обнаружение внешних служб.

2.9.5.4. Опция Locator URI

Фрагментарная форма CDDL для опции Locator URI имеет вид

     uri-locator-option = [O_URI_LOCATOR, text, transport-proto / null, port-number / null]

Опция содержит идентификатор URI для цели, за которым указаны номера протокола и порта (или пустые значения, если номера не нужны) [RFC3986].

Примечание 1. Идентификаторы URI, которые могут быть недействительны в сети, такие как имена Multicast DNS [RFC6762], недопустимо применять для опции, помещаемой в опцию Divert.

Примечание 2. При обычной работе GRASP применение этой опции не предполагается. Она предназначена для специальных задач, таких как обнаружение внешних служб, поэтому не описана подробно в спецификации.

2.10. Опции задачи

2.10.1. Формат опций задачи

Опция objective служит для идентификации задачи в целях обнаружения, согласования или синхронизации. Все задачи должны иметь фрагментарный формат CDDL

   objective = [objective-name, objective-flags, loop-count, ?objective-value]

   objective-name = text
   objective-value = any
   loop-count = 0..255

Все задачи указываются уникальным именем в форме строки UTF-8 [RFC3629] с побайтовым сравнением. В имена базовых задач недопустимо включать двоеточие (:) и они должны регистрироваться в IANA (раздел 5). Имена заданных приватно задач должны включать хотя бы одно двоеточие. Строка, предшествующая последнему двоеточию в имени, должна быть уникальной в глобальном масштабе и тем или иным способом идентифицировать организацию или лицо, определившее задачу. Для создания уникальных в глобальном масштабе строк можно применять три указанных ниже варианта.

  1. Строка, представляющая десятичное значение 32-битового идентификатора организации (Private Enterprise Number или PEN) [RFC5612], однозначно указывающего организацию, определившую задачу.

  2. Строка имени FQDN, однозначно указывающая организацию или лицо, определившее задачу.

  3. Строка адреса электронной почты, однозначно указывающая организацию или лицо, определившее задачу.

GRASP считает имя задачи необрабатываемой (opaque) строкой. Например, EX1, 32473:EX1, example.com:EX1, example.org:EX1, user@example.org:EX1 указывают 5 различных задач.

Поле objective-flags описано в параграфе 2.10.2.

Поле loop-count служит для прерывания согласования, как описано в параграфе 2.8.7, а также для прерывания обнаружения, как описано в параграфе 2.5.4, и лавинной отправки, как описано в параграфе 2.5.6.2. Оно помещается в objective, а не в сообщение GRASP, поскольку для ASA является свойством самой задачи.

Поле objective-value указывает действительное значение задачи для согласования или синхронизации. Его формат определяет спецификация задачи и это может быть простое значение или структура данных любого типа, если её можно представить в CBOR. Поле является необязательным в сообщениях Discovery и Discovery Response.

2.10.2. Поле objective-flags

Задача может относиться лишь к обнаружению, обнаружению и согласованию или обнаружению и синхронизации. Это указывается в задаче логическими полями флагов.

     objective-flags = uint .bits objective-flag
     objective-flag = &(
       F_DISC: 0    ; действителен для обнаружения
       F_NEG: 1     ; действителен для согласования
       F_SYNCH: 2   ; действителен для синхронизации
       F_NEG_DRY: 3 ; согласование является «пробным прогоном»
     )

Эти биты независимы и могут комбинироваться, например (F_DISC и F_SYNCH), (F_DISC и F_NEG), (F_DISC, F_NEG и F_NEG_DRY).

Отметим, что в данной сессии согласования задача должна использоваться для согласования или пробного прогона. Смешивание этих двух режимов не допускается.

2.10.3. Общее рассмотрение опций объекта

Как отмечено выше, опциям задач должны выделяться уникальные имена. Пока определённые частным образом опции следуют приведённым выше правилам, этот документ не ограничивает выбор имён, но заинтересованным сторонам следует публиковать используемые имена. Имена задаются строками UTF-8 для удобства разработки локализованных опций задач. Для общего применения рекомендуется применять для имён подмножество символов ASCII в кодировке UTF-8. Разработчикам, планирующим использовать имена с символами, отличными от ASCII, настоятельно рекомендуется ознакомиться с [RFC8264] или его преемником для понимания возникающих сложностей. Поскольку GRASP сравнивает имена побайтово, все проблемы профилирования и канонизации Unicode должны быть указаны в спецификации опции.

Все опции задач должны соответствовать шаблонам CBOR, определенным выше как objective, а также должны заменять все поля any действительными определениями данных CBOR для соответствующего применения. Опции задач, не содержащие полей кроме loop-count, могут применяться лишь для задач обнаружения и должны включаться лишь в сообщения Discovery и Discovery Response.

Опции Negotiation Objective содержат задачи для согласования, которые меняются в зависимости от функций и услуг. Они должны передаваться лишь в сообщениях Discovery, Request Negotiation или Negotiation. Инициатор согласования должен устанавливать исходное значение loop-count в соответствии со спецификацией задачи или GRASP_DEF_LOOPCT (если спецификация не задаёт значение). Для большинства случаев в запросах согласования следует указывать начальные значения. Поэтому опции Negotiation Objective должны всегда полностью включаться в сообщение Request Negotiation или сообщение Discovery в быстром режиме. При отсутствии начального значения в поле value следует устанавливать значение null, определённое в CBOR.

Опции Synchronization Objective похожи, но должны передаваться лишь в сообщениях Discovery, Discovery Response, Request Synchronization или Flood Synchronization. Они включают поле value только в сообщениях Synchronization и Flood Synchronization.

Задачи разными путями взаимодействуют с агентами ASA, которые используют их. Вопросы проектирования ASA рассмотрены в [ASA-GUIDELINES].

2.10.4. Организация опций задачи

Базовые опции задач должны быть заданы в общедоступных документах и их следует разрабатывать для применения в механизмах согласования или синхронизации, описанных выше. Как уже было отмечено, каждым потоком GRASP обрабатывается одна задача для согласования. Поэтому задаче для согласования, основанной на конкретной функции или действии, следует быть организованной в виде отдельной опции GRASP. Не рекомендуется объединять несколько задач для согласования в одну опцию, а также разделять одну функцию или или действие между несколькими опциями согласования.

Важно понимать, что согласование GRASP не поддерживает целостность транзакций. Если такая целостность нужна для конкретной задачи, она должна обеспечиваться агентом ASA. Например, ASA может потребоваться обеспечить участие в каждый момент лишь в одном потоке согласования. Такому ASA потребуется прекратить прослушивание входящих запросов на согласование перед созданием исходящего запроса согласования.

Задачи для синхронизации следует организовывать в одну опцию GRASP.

Некоторые задачи поддерживают не один режим работы. Примером может служить задача для согласования с режимом пробного запуска (dry-run), где согласование заключается в проверке возможности реализации запрошенных изменений на другой стороне, и реальным рабочим режимом (live), как описано в параграфе 2.5.5. Семантика таких режимов определяется в спецификации задачи. Таким задачам следует включать флаги, задающие режим.

Особо следует обращать внимание на то, что GRASP сам по себе не является протоколом защищённых транзакций. Любое состояние, связанное с пробным запуском, такое как временное резервирование ресурсов для последующего использования в рабочем режиме, полностью определяет разработчик соответствующего агента ASA.

Как отмечено в параграфе 2.1, значение задачи может включать множество параметров. Эти параметры можно разделить на два класса — обязательные, которые представляются фиксированными полями, и необязательные, представленные в какой-либо форме структуры данных, встроенной в CBOR. Формат может наследоваться от имеющихся протоколов управления и настройки, при этом опция задачи служит носителем формата. Структура данных может определяться формальным языком, но это задаёт спецификация задачи. В зависимости от контекста может применяться ABNF, RBNF, XML Schema, YANG и п., протокол GRASP может работать с разными формами. Единственным ограничением является необходимость отображения формата в CBOR.

Не рекомендуется смешивать в одной задаче параметры, сильно различающиеся по времени отклика. Для них лучше задавать отдельные задачи.

Все задачи должны поддерживать обнаружение GRASP. Однако, как отмечено в параграфе 2.3, агенты ASA могут применять иные методы обнаружения.

Обычно задача GRASP будет относиться к конкретным техническим параметрам, как разъяснено в параграфе 2.1. Однако можно определять абстрактные задачи для управления и координации агентов ASA. Можно также определять специальные задачи для таких целей, как доверенная начальная загрузка и формирование ACP.

Для гарантированного схождения требуется ограниченное число циклов обмена или время ожидания у каждой задачи для согласования. Поэтому в определении каждой задачи следует чётко указывать это, например, принятым по умолчанию значением loop count или тайм-аутом, чтобы согласование всегда можно было завершить корректно. В ином случае будут применяться принятые по умолчанию настройки GRASP.

Должна быть чётко определённая процедура принятия решения о невозможности согласования и определения в таких случаях последующих событий (например, устранение тупика, возврат к услугам best-effort). Это должно задаваться в спецификациях задач для согласования.

2.10.5. Опции для экспериментов и примеров

Имена EX0 — EX9 зарезервированы для экспериментальных опций. Выделение нескольких имён обусловлено тем, что в эксперименте может одновременно участвовать несколько опций. Весьма вероятно, что эти опции будут иметь разный смысл в различных приложениях, поэтому не следует их использовать без явного рассмотрения человеком и недопустимо применять эти опции в неуправляемых сетях, таких как домашние.

Эти имена рекомендуются также для примеров в документации.

3. Вопросы безопасности

Успех атаки на узел с поддержкой согласования может быть чрезвычайно опасным, поскольку может сделать конфигурацию узла совершенно нежелательной и оказать негативное влияние на партнёров узла. Поэтому для узлов и сообщений GRASP требуется полная защита. Как отмечено в параграфе 2.5.1, протокол GRASP должен работать в защищённой среде, такой как плоскость управления ACP [RFC8994], за исключением ограниченных экземпляров, описанных в параграфе 2.5.2.

Проверка подлинности

Для автоматических сетей (AN) требуется криптографически аутентифицированное отождествление (identity) каждого устройства. Небезопасно полагать, что большая сеть физически защищена от вредных воздействий или всему персоналу можно доверять. Каждый автоматический узел должен быть способен предоставить своё отождествление и подтвердить подлинность своих сообщений. Протокол GRASP полагается на отдельный внешний механизм защиты для поддержки аутентификации, защиты целостности данных и предотвращения повторного использования (replay).
Поскольку протокол GRASP должен разворачиваться в имеющейся защищённой среде, он сам не определяет ничего, относящегося к привязкам доверия и удостоверяющим центрам. Например, в ACP [RFC8994] все узлы могут доверять друг другу и агенты ASA устанавливаются на них. Если GRASP применяется временно без внешних механизмов защиты, например, при начальной загрузке системы (параграф 2.5.1), Session ID (параграф 2.7) будет служить одноразовым значением (nonce) для обеспечения ограниченной защиты от внедрения откликов посторонними. Полный анализ защиты процесса начальной загрузки приведён в [RFC8995].

Проверка полномочий и роли

GRASP не зависит от ролей и возможностей отдельных ASA и задач, которые уполномочены поддерживать конкретные ASA. Реализация может поддерживать меры предосторожности, позволяя лишь одному агенту ASA на данном узле менять данную задачу, но в некоторых случаях это может оказаться неуместным. Например, для работы может быть полезно разрешить одновременную работу старой и новой версии на одном ASA в течение переходного периода. Рассмотрение таких вопросов выходит за рамки этой спецификации.

Приватность и конфиденциальность

Протокол GRASP предназначен для управления сетью, включающего элементы сети, но не конечные хосты. Поэтому наличие персональных данных в сигнальном протоколе не предполагается и протокол не должен влиять на персональную приватность. Тем не менее, передающие персональные данные приложения нельзя исключать. Кроме того, могут согласовываться потоки трафика, VPN и т. п., что может представлять интерес для анализа трафика. Операторы обычно хотят скрыть от посторонних детали топологии сети и плотность трафика. Внутренние атаки нельзя исключить в большой сети, поэтому механизм защиты для протокола должен обеспечивать конфиденциальность сообщений. По этой причине параграф 2.5.1 требует использования ACP или иной защиты.

Защита группового трафика на локальном канале

У GRASP нет разумной замены групповой (link-local) сообщений Discovery и Flood Synchronization, которые передаются в открытом виде без аутентификации. Сообщения передаются лишь через интерфейсы в автоматическую сеть AN (см. параграфы 2.1 и 2.5.1), однако они доступны для перехвата на канале и могут быть подделаны подключёнными к каналу злоумышленниками. При обнаружении сообщения Discovery Response являются индивидуальными и защищены (параграф 2.5.1), поэтому не могут быть перехвачены посторонними. В случае лавинной синхронизации перехватчик на канале может получить рассылаемые лавинно задачи, но на такие сообщения ответы не передаются. Некоторые предосторожности для Flood Synchronization рассмотрены в параграфе 2.5.6.2.

Защита от DoS-атак

Обнаружение в GRASP частично полагается на незащищённые групповые (link-local) сообщения. Поскольку участвующие в GRASP маршрутизаторы иногда передают сообщения Discovery из одного канала в другой, это может быть использовано для организации DoS-атак. Некоторые меры снижения угроз описаны в параграфе 2.5.4. Однако вредоносный код, размещённый в ACP, всегда может организовать DoS-атаку, состоящую из ложных сообщений Discovery, либо из ложных откликов Discovery Response. Важно, чтобы межсетевые экраны предотвращали вход в домен сообщений GRASP от неизвестных источников.

Защита при начальной загрузке и обнаружении

Узел не может доверять трафику GRASP от других узлов, пока среда защиты (например, ACP) не задаст привязки доверия и не обеспечит аутентификацию трафика путём проверки сертификатов других узлов. Кроме того, пока узел не будет зарегистрирован [RFC8995], о не может считать, что другие узлы способны проверить подлинность его трафика. Поэтому обнаружение GRASP в фазе начальной загрузки нового устройства не будет защищённым. Защита согласования и синхронизации невозможна до завершения регистрации (см. параграф 2.5.2).

Защита обнаруженных локаторов

Возвращаемый GRASP адрес IP должен относиться к защищённой среде (параграф 2.5.1). Если возвращается FQDN или URI, получившему его агенту ASA недопустимо считать, что локатор находится в защищённой среде.

4. CDDL-спецификация GRASP

   <CODE BEGINS> file "grasp.cddl"
   grasp-message = (message .within message-structure) / noop-message

   message-structure = [MESSAGE_TYPE, session-id, ?initiator, *grasp-option]

   MESSAGE_TYPE = 0..255
   session-id = 0..4294967295 ; до 32 битов
   grasp-option = any

   message /= discovery-message
   discovery-message = [M_DISCOVERY, session-id, initiator, objective]

   message /= response-message ; отклик на Discovery
   response-message = [M_RESPONSE, session-id, initiator, ttl,
                       (+locator-option // divert-option), ?objective]

   message /= synch-message ; отклик на запрос синхронизации
   synch-message = [M_SYNCH, session-id, objective]

   message /= flood-message
   flood-message = [M_FLOOD, session-id, initiator, ttl,
                    +[objective, (locator-option / [])]]

   message /= request-negotiation-message
   request-negotiation-message = [M_REQ_NEG, session-id, objective]

   message /= request-synchronization-message
   request-synchronization-message = [M_REQ_SYN, session-id, objective]

   message /= negotiation-message
   negotiation-message = [M_NEGOTIATE, session-id, objective]

   message /= end-message
   end-message = [M_END, session-id, accept-option / decline-option]

   message /= wait-message
   wait-message = [M_WAIT, session-id, waiting-time]

   message /= invalid-message
   invalid-message = [M_INVALID, session-id, ?any]

   noop-message = [M_NOOP]

   divert-option = [O_DIVERT, +locator-option]

   accept-option = [O_ACCEPT]

   decline-option = [O_DECLINE, ?reason]
   reason = text  ; необязательное сообщение об ошибке (UTF-8)

   waiting-time = 0..4294967295 ; в миллисекундах
   ttl = 0..4294967295 ; в миллисекундах

   locator-option /= [O_IPv4_LOCATOR, ipv4-address, transport-proto, port-number]
   ipv4-address = bytes .size 4

   locator-option /= [O_IPv6_LOCATOR, ipv6-address,
                      transport-proto, port-number]
   ipv6-address = bytes .size 16

   locator-option /= [O_FQDN_LOCATOR, text, transport-proto,
                      port-number]

   locator-option /= [O_URI_LOCATOR, text,
                      transport-proto / null, port-number / null]

   transport-proto = IPPROTO_TCP / IPPROTO_UDP
   IPPROTO_TCP = 6
   IPPROTO_UDP = 17
   port-number = 0..65535

   initiator = ipv4-address / ipv6-address

   objective-flags = uint .bits objective-flag

   objective-flag = &(
     F_DISC: 0    ; действительно для обнаружения
     F_NEG: 1     ; действительно для согласования
     F_SYNCH: 2   ; действительно для синхронизации
     F_NEG_DRY: 3 ; согласование является пробным прогоном
   )

   objective = [objective-name, objective-flags, loop-count, ?objective-value]

   objective-name = text ; см. параграф "Формат опций задачи"

   objective-value = any

   loop-count = 0..255

   ; Константы для типов сообщений и опций
   M_NOOP = 0
   M_DISCOVERY = 1
   M_RESPONSE = 2
   M_REQ_NEG = 3
   M_REQ_SYN = 4
   M_NEGOTIATE = 5
   M_END = 6
   M_WAIT = 7
   M_SYNCH = 8
   M_FLOOD = 9
   M_INVALID = 99

   O_DIVERT = 100
   O_ACCEPT = 101
   O_DECLINE = 102
   O_IPv6_LOCATOR = 103
   O_IPv4_LOCATOR = 104
   O_FQDN_LOCATOR = 105
   O_URI_LOCATOR = 106
   <CODE ENDS>

5. Взаимодействие с IANA

Документ определяет базовый протокол автоматической сигнализации GRASP (GeneRic Autonomic Signaling Protocol).

В параграфе 2.6 указаны приведённые ниже групповые адреса link-local, выделенные IANA для GRASP.

Субреестр Link-Local Scope Multicast Addresses в реестре IPv6 Multicast Address Space

   Address(es):  ff02::13
   Description:  ALL_GRASP_NEIGHBORS
   Reference:  RFC 8990

Субреестр Local Network Control Block (224.0.0.0 — 224.0.0.255 (224.0.0/24)) в реестре IPv4 Multicast Address Space

   Address(es):  224.0.0.119
   Description:  ALL_GRASP_NEIGHBORS
   Reference:  RFC 8990

В параграфе 2.6 указан пользовательский порт GRASP_LISTEN_PORT, выделенный IANA для использования GRASP с протоколами UDP и TCP

   Service Name:  grasp
   Port Number:  7017
   Transport Protocol:  udp, tcp
   Description  GeneRic Autonomic Signaling Protocol
   Assignee:  IESG <iesg@ietf.org>
   Contact:  IETF Chair <chair@ietf.org>
   Reference:  RFC 8990

Агентство IANA создало реестр GeneRic Autonomic Signaling Protocol (GRASP) Parameters с двумя субреестрами GRASP Messages and Options и GRASP Objective Names. Субреестр GRASP Messages and Options содержит пары, состоящие из имени и десятичного целого числа. Новые значений должны выделяться по процедуре Standards Action, определённой в [RFC8126]. Назначенные этим документом значение приведены в таблице .

Таблица . Значения субреестра GRASP Messages and Options.

Значение

Сообщение или опция

0

M_NOOP

1

M_DISCOVERY

2

M_RESPONSE

3

M_REQ_NEG

4

M_REQ_SYN

5

M_NEGOTIATE

6

M_END

7

M_WAIT

8

M_SYNCH

9

M_FLOOD

99

M_INVALID

100

O_DIVERT

101

O_ACCEPT

102

O_DECLINE

103

O_IPv6_LOCATOR

104

O_IPv4_LOCATOR

105

O_FQDN_LOCATOR

106

O_URI_LOCATOR

Субреестр GRASP Objective Names содержит строки UTF-8, в которых недопустимо включение двоеточий (:), согласно параграфу 2.10.1. Новые значения должны выделяться по процедуре Specification Required, заданной в [RFC8126].

Для облегчения экспертной оценки новых задач в их спецификации следует включать точное описание формата задачи и достаточными для независимой реализации разъяснениями семантики (см. параграф 2.10.3). Если новая задача похожа именем или назначением на ранее зарегистрированную, в спецификации следует обосновать необходимость этого.

Начальные значения, выделенные в этом документе, приведены в таблице .

Таблица . Исходные значения субреестра GRASP Objective Names.

Имя

Документ

EX1

RFC 8990

EX2

RFC 8990

EX3

RFC 8990

EX4

RFC 8990

EX5

RFC 8990

EX6

RFC 8990

EX7

RFC 8990

EX8

RFC 8990

EX9

RFC 8990

6. Литература

6.1. Нормативные документы

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>.

[RFC3629] Yergeau, F., «UTF-8, a transformation format of ISO 10646», STD 63, RFC 3629, DOI 10.17487/RFC3629, November 2003, <https://www.rfc-editor.org/info/rfc3629>.

[RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, «Uniform Resource Identifier (URI): Generic Syntax», STD 66, RFC 3986, DOI 10.17487/RFC3986, January 2005, <https://www.rfc-editor.org/info/rfc3986>.

[RFC4086] Eastlake 3rd, D., Schiller, J., and S. Crocker, «Randomness Requirements for Security», BCP 106, RFC 4086, DOI 10.17487/RFC4086, June 2005, <https://www.rfc-editor.org/info/rfc4086>.

[RFC7217] Gont, F., «A Method for Generating Semantically Opaque Interface Identifiers with IPv6 Stateless Address Autoconfiguration (SLAAC)», RFC 7217, DOI 10.17487/RFC7217, April 2014, <https://www.rfc-editor.org/info/rfc7217>.

[RFC8085] Eggert, L., Fairhurst, G., and G. Shepherd, «UDP Usage Guidelines», BCP 145, RFC 8085, DOI 10.17487/RFC8085, March 2017, <https://www.rfc-editor.org/info/rfc8085>.

[RFC8174] Leiba, B., «Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words», BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[RFC8610] Birkholz, H., Vigano, C., and C. Bormann, «Concise Data Definition Language (CDDL): A Notational Convention to Express Concise Binary Object Representation (CBOR) and JSON Data Structures», RFC 8610, DOI 10.17487/RFC8610, June 2019, <https://www.rfc-editor.org/info/rfc8610>.

[RFC8949] Bormann, C. and P. Hoffman, «Concise Binary Object Representation (CBOR)», STD 94, RFC 8949, DOI 10.17487/RFC8949, December 2020, <https://www.rfc-editor.org/info/rfc8949>.

[RFC8994] Eckert, T., Ed., Behringer, M., Ed., and S. Bjarnason, «An Autonomic Control Plane (ACP)», RFC 8994, DOI 10.17487/RFC8994, May 2021, <https://www.rfc-editor.org/info/rfc8994>.

6.2. Дополнительная литература

[ADNCP] Stenberg, M., «Autonomic Distributed Node Consensus Protocol», Work in Progress, Internet-Draft, draft-stenberg-anima-adncp-00, 5 March 2015, <https://tools.ietf.org/html/draft-stenberg-anima-adncp-00>.

[ASA-GUIDELINES] Carpenter, B., Ciavaglia, L., Jiang, S., and P. Peloso, «Guidelines for Autonomic Service Agents», Work in Progress, Internet-Draft, draft-ietf-anima-asa-guidelines-00, 14 November 2020, <https://tools.ietf.org/html/draft-ietf-anima-asa-guidelines-00>.

[IGCP] Behringer, M. H., Chaparadza, R., Xin, L., Mahkonen, H., and R. Petre, «IP based Generic Control Protocol (IGCP)», Work in Progress, Internet-Draft, draft-chaparadza-intarea-igcp-00, 25 July 2011, <https://tools.ietf.org/html/draft-chaparadza-intarea-igcp-00>.

[RFC2205] Braden, R., Ed., Zhang, L., Berson, S., Herzog, S., and S. Jamin, «Resource ReSerVation Protocol (RSVP) — Version 1 Functional Specification», RFC 2205, DOI 10.17487/RFC2205, September 1997, <https://www.rfc-editor.org/info/rfc2205>.

[RFC2334] Luciani, J., Armitage, G., Halpern, J., and N. Doraswamy, «Server Cache Synchronization Protocol (SCSP)», RFC 2334, DOI 10.17487/RFC2334, April 1998, <https://www.rfc-editor.org/info/rfc2334>.

[RFC2608] Guttman, E., Perkins, C., Veizades, J., and M. Day, «Service Location Protocol, Version 2», RFC 2608, DOI 10.17487/RFC2608, June 1999, <https://www.rfc-editor.org/info/rfc2608>.

[RFC2865] Rigney, C., Willens, S., Rubens, A., and W. Simpson, «Remote Authentication Dial In User Service (RADIUS)», RFC 2865, DOI 10.17487/RFC2865, June 2000, <https://www.rfc-editor.org/info/rfc2865>.

[RFC3416] Presuhn, R., Ed., «Version 2 of the Protocol Operations for the Simple Network Management Protocol (SNMP)», STD 62, RFC 3416, DOI 10.17487/RFC3416, December 2002, <https://www.rfc-editor.org/info/rfc3416>.

[RFC3493] Gilligan, R., Thomson, S., Bound, J., McCann, J., and W. Stevens, «Basic Socket Interface Extensions for IPv6», RFC 3493, DOI 10.17487/RFC3493, February 2003, <https://www.rfc-editor.org/info/rfc3493>.

[RFC4861] Narten, T., Nordmark, E., Simpson, W., and H. Soliman, «Neighbor Discovery for IP version 6 (IPv6)», RFC 4861, DOI 10.17487/RFC4861, September 2007, <https://www.rfc-editor.org/info/rfc4861>.

[RFC5612] Eronen, P. and D. Harrington, «Enterprise Number for Documentation Use», RFC 5612, DOI 10.17487/RFC5612, August 2009, <https://www.rfc-editor.org/info/rfc5612>.

[RFC5971] Schulzrinne, H. and R. Hancock, «GIST: General Internet Signalling Transport», RFC 5971, DOI 10.17487/RFC5971, October 2010, <https://www.rfc-editor.org/info/rfc5971>.

[RFC6206] Levis, P., Clausen, T., Hui, J., Gnawali, O., and J. Ko, «The Trickle Algorithm», RFC 6206, DOI 10.17487/RFC6206, March 2011, <https://www.rfc-editor.org/info/rfc6206>.

[RFC6241] Enns, R., Ed., Bjorklund, M., Ed., Schoenwaelder, J., Ed., and A. Bierman, Ed., «Network Configuration Protocol (NETCONF)», RFC 6241, DOI 10.17487/RFC6241, June 2011, <https://www.rfc-editor.org/info/rfc6241>.

[RFC6733] Fajardo, V., Ed., Arkko, J., Loughney, J., and G. Zorn, Ed., «Diameter Base Protocol», RFC 6733, DOI 10.17487/RFC6733, October 2012, <https://www.rfc-editor.org/info/rfc6733>.

[RFC6762] Cheshire, S. and M. Krochmal, «Multicast DNS», RFC 6762, DOI 10.17487/RFC6762, February 2013, <https://www.rfc-editor.org/info/rfc6762>.

[RFC6763] Cheshire, S. and M. Krochmal, «DNS-Based Service Discovery», RFC 6763, DOI 10.17487/RFC6763, February 2013, <https://www.rfc-editor.org/info/rfc6763>.

[RFC6887] Wing, D., Ed., Cheshire, S., Boucadair, M., Penno, R., and P. Selkirk, «Port Control Protocol (PCP)», RFC 6887, DOI 10.17487/RFC6887, April 2013, <https://www.rfc-editor.org/info/rfc6887>.

[RFC7558] Lynn, K., Cheshire, S., Blanchet, M., and D. Migault, «Requirements for Scalable DNS-Based Service Discovery (DNS-SD) / Multicast DNS (mDNS) Extensions», RFC 7558, DOI 10.17487/RFC7558, July 2015, <https://www.rfc-editor.org/info/rfc7558>.

[RFC7575] Behringer, M., Pritikin, M., Bjarnason, S., Clemm, A., Carpenter, B., Jiang, S., and L. Ciavaglia, «Autonomic Networking: Definitions and Design Goals», RFC 7575, DOI 10.17487/RFC7575, June 2015, <https://www.rfc-editor.org/info/rfc7575>.

[RFC7576] Jiang, S., Carpenter, B., and M. Behringer, «General Gap Analysis for Autonomic Networking», RFC 7576, DOI 10.17487/RFC7576, June 2015, <https://www.rfc-editor.org/info/rfc7576>.

[RFC7787] Stenberg, M. and S. Barth, «Distributed Node Consensus Protocol», RFC 7787, DOI 10.17487/RFC7787, April 2016, <https://www.rfc-editor.org/info/rfc7787>.

[RFC7788] Stenberg, M., Barth, S., and P. Pfister, «Home Networking Control Protocol», RFC 7788, DOI 10.17487/RFC7788, April 2016, <https://www.rfc-editor.org/info/rfc7788>.

[RFC8040] Bierman, A., Bjorklund, M., and K. Watsen, «RESTCONF Protocol», RFC 8040, DOI 10.17487/RFC8040, January 2017, <https://www.rfc-editor.org/info/rfc8040>.

[RFC8126] Cotton, M., Leiba, B., and T. Narten, «Guidelines for Writing an IANA Considerations Section in RFCs», BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017, <https://www.rfc-editor.org/info/rfc8126>.

[RFC8264] Saint-Andre, P. and M. Blanchet, «PRECIS Framework: Preparation, Enforcement, and Comparison of Internationalized Strings in Application Protocols», RFC 8264, DOI 10.17487/RFC8264, October 2017, <https://www.rfc-editor.org/info/rfc8264>.

[RFC8368] Eckert, T., Ed. and M. Behringer, «Using an Autonomic Control Plane for Stable Connectivity of Network Operations, Administration, and Maintenance (OAM)», RFC 8368, DOI 10.17487/RFC8368, May 2018, <https://www.rfc-editor.org/info/rfc8368>.

[RFC8415] Mrugalski, T., Siodelski, M., Volz, B., Yourtchenko, A., Richardson, M., Jiang, S., Lemon, T., and T. Winters, «Dynamic Host Configuration Protocol for IPv6 (DHCPv6)», RFC 8415, DOI 10.17487/RFC8415, November 2018, <https://www.rfc-editor.org/info/rfc8415>.

[RFC8991] Carpenter, B., Liu, B., Ed., Wang, W., and X. Gong, «GeneRic Autonomic Signaling Protocol Application Program Interface (GRASP API)», RFC 8991, DOI 10.17487/RFC8991, May 2021, <https://www.rfc-editor.org/info/rfc8991>.

[RFC8993] Behringer, M., Ed., Carpenter, B., Eckert, T., Ciavaglia, L., and J. Nobre, «A Reference Model for Autonomic Networking», RFC 8993, DOI 10.17487/RFC8993, May 2021, <https://www.rfc-editor.org/info/rfc8993>.

[RFC8995] Pritikin, M., Richardson, M., Eckert, T., Behringer, M., and K. Watsen, «Bootstrapping Remote Secure Key Infrastructure (BRSKI)», RFC 8995, DOI 10.17487/RFC8995, May 2021, <https://www.rfc-editor.org/info/rfc8995>.

Приложение A. Примеры формата сообщений

Для читателей, не знакомых с CBOR, в этом приложении даны примеры сообщений GRASP в соответствии с синтаксисом CDDL, заданным в разделе 4. Каждое сообщение приведено трижды в разных форматах:

  1. диагностическая нотация CBOR;

  2. похожая нотация с указанием имён константами (детали представления флагов опущены);

  3. шестнадцатеричное представление формата CBOR в линии передачи.

Длинные строки разделены на несколько строк.

A.1. Discovery

Инициатор (2001:db8:f000:baaa:28cc:dc4c:9703:6781) передаёт групповое сообщение Discovery для поиска задачи EX1

   [1, 13948744, h'20010db8f000baaa28ccdc4c97036781', ["EX1", 5, 2, 0]]
   [M_DISCOVERY, 13948744, h'20010db8f000baaa28ccdc4c97036781',
                 ["EX1", F_SYNCH_bits, 2, 0]]
   h'84011a00d4d7485020010db8f000baaa28ccdc4c970367818463455831050200'

Партнёр (2001:0db8:f000:baaa:f000:baaa:f000:baaa) отвечает на сообщение, указывая локатор

   [2, 13948744, h'20010db8f000baaa28ccdc4c97036781', 60000,
                 [103, h'20010db8f000baaaf000baaaf000baaa', 6, 49443]]
   [M_RESPONSE, 13948744, h'20010db8f000baaa28ccdc4c97036781', 60000,
                 [O_IPv6_LOCATOR, h'20010db8f000baaaf000baaaf000baaa',
                  IPPROTO_TCP, 49443]]
   h'85021a00d4d7485020010db8f000baaa28ccdc4c9703678119ea6084186750
     20010db8f000baaaf000baaaf000baaa0619c123'

A.2. Лавинная синхронизация

Инициатор передаёт групповое сообщение Flood Synchronization. Одна задача имеет пустой локатор. Отклика нет.

[9, 3504974, h'20010db8f000baaa28ccdc4c97036781', 10000,
             [["EX1", 5, 2, ["Example 1 value=", 100]],[] ] ]
[M_FLOOD, 3504974, h'20010db8f000baaa28ccdc4c97036781', 10000,
             [["EX1", F_SYNCH_bits, 2, ["Example 1 value=", 100]],[] ] ]
h'85091a00357b4e5020010db8f000baaa28ccdc4c97036781192710
  828463455831050282704578616d706c6520312076616c75653d186480'

A.3. Синхронизация

После обнаружения задачи EX2 инициатор передаёт сообщение Request Synchronization

   [4, 4038926, ["EX2", 5, 5, 0]]
   [M_REQ_SYN, 4038926, ["EX2", F_SYNCH_bits, 5, 0]]
   h'83041a003da10e8463455832050500'

Партнёр возвращает значение

 [8, 4038926, ["EX2", 5, 5, ["Example 2 value=", 200]]]
 [M_SYNCH, 4038926, ["EX2", F_SYNCH_bits, 5, ["Example 2 value=", 200]]]
 h'83081a003da10e8463455832050582704578616d706c6520322076616c75653d18c8'

A.4. Пример простого согласования

После обнаружения задачи EX3 инициатор передаёт сообщение Request Negotiation

   [3, 802813, ["EX3", 3, 6, ["NZD", 47]]]
   [M_REQ_NEG, 802813, ["EX3", F_NEG_bits, 6, ["NZD", 47]]]
   h'83031a000c3ffd8463455833030682634e5a44182f'

Партнёр сразу же принимает предложенное. Отметим, что задачу можно не указывать, поскольку запрос воспринят.

   [6, 802813, [101]]
   [M_END , 802813, [O_ACCEPT]]
   h'83061a000c3ffd811865'

A.5. Пример полного согласования

Инициатор передаёт индивидуальное сообщение Request Negotiation

   [3, 13767778, ["EX3", 3, 6, ["NZD", 410]]]
   [M_REQ_NEG, 13767778, ["EX3", F_NEG_bits, 6, ["NZD", 410]]]
   h'83031a00d214628463455833030682634e5a4419019a'

Ответчик начинает согласование (внося предложение)

   [5, 13767778, ["EX3", 3, 6, ["NZD", 80]]]
   [M_NEGOTIATE, 13767778, ["EX3", F_NEG_bits, 6, ["NZD", 80]]]
   h'83051a00d214628463455833030682634e5a441850'

Инициатор продолжает согласование (понижая запрос и уменьшая значение loop count)

   [5, 13767778, ["EX3", 3, 5, ["NZD", 307]]]
   [M_NEGOTIATE, 13767778, ["EX3", F_NEG_bits, 5, ["NZD", 307]]]
   h'83051a00d214628463455833030582634e5a44190133'

Ответчик просит дополнительное время

   [7, 13767778, 34965]
   [M_WAIT, 13767778, 34965]
   h'83071a00d21462198895'

Ответчик продолжает согласование (снижая своё предложение)

   [5, 13767778, ["EX3", 3, 4, ["NZD", 120]]]
   [M_NEGOTIATE, 13767778, ["EX3", F_NEG_bits, 4, ["NZD", 120]]]
   h'83051a00d214628463455833030482634e5a441878'

Инициатор продолжает согласование (понижая запрос)

   [5, 13767778, ["EX3", 3, 3, ["NZD", 246]]]
   [M_NEGOTIATE, 13767778, ["EX3", F_NEG_bits, 3, ["NZD", 246]]]
   h'83051a00d214628463455833030382634e5a4418f6'

Ответчик отвергает согласование

   [6, 13767778, [102, "Insufficient funds"]]
   [M_END , 13767778, [O_DECLINE, "Insufficient funds"]]
   h'83061a00d2146282186672496e73756666696369656e742066756e6473'

Согласование завершается отказом. Если любая из сторон передаст [M_END, 13767778, [O_ACCEPT]], согласование будет успешным, сходясь к значению из предыдущего M_NEGOTIATE. За исключением исходного M_REQ_NEG процесс является симметричным.

Приложение B. Требования к Discovery, Synchronization, Negotiation

В этом приложении рассматриваются требования к возможностям обнаружения, согласования и синхронизации. Основными пользователями протокола являются автоматические агенты служб (ASA), поэтому требования в основном выражаются функциями, необходимыми для ASA. Одно физическое устройство может включать несколько ASA, а один агент ASA может управлять несколькими техническими задачами. Если техническая задача управляется несколькими ASA, их нужно координировать вне протокола GRASP. Более того, требования к самим ASA, такие как обработка Intent [RFC7575], выходят за рамки этого документа.

B.1. Требования к обнаружению

D1

ASA могут быть разработаны для управления любым настраиваемым устройством или программой, как указано в приложении B.2. Базовое требование заключается в том, чтобы протокол мог представлять и обнаруживать технические задачи любого сорта (как определено в параграфе 2.1) среди произвольного набора узлов.
В сети AN приходится считать, что при первом запуске устройства оно не имеет сведений о партнёрах, структуре сети и своей роли в сети. Агент(ы) ASA внутри устройства находятся в такой же ситуации. В некоторых случаях при запуске в устройстве новой прикладной сессии устройству или ASA также может не хватать информации о соответствующих партнёрах. Например, может потребоваться настройка ресурсов на множестве других устройств, скоординированных и согласованных между собой, чтобы не тратить лишних ресурсов. Может потребоваться обновление параметров защиты для нового устройства или пользователя. Относящиеся к делу партнёры могут различаться для разных технических задач. Поэтому обнаружение приходится повторять, чтобы найти партнёров, подходящих для каждой задачи, которую инициатору обнаружения нужно обслуживать. Из этих соображений выводятся следующие 3 требования.

D2

При первом запуске ASA у агента может не быть сведений о конкретной сети, к которой агент подключён. Поэтому процесс обнаружения должен быть способен поддерживать любой сетевой сценарий, предполагая лишь, что устройство загружается с заводскими настройками.

D3

При запуске агента ASA он не должен требовать настройки сведений о местоположении партнёров для их обнаружения.

D4

Если ASA поддерживает несколько технических задач, соответствующие партнёры при поиске могут быть разными для различных задач. Таким образом, требуется механизм, с помощью которого агент ASA может раздельно обнаруживать партнерские ASA для каждой из технических задач, которыми нужно управлять.

D5

После обнаружения ASA обычно выполняет согласование или синхронизацию для соответствующих задач. Это следует разрешать, удобно связывая обнаружение с согласованием и синхронизацией. Можно предоставлять дополнительный механизм, позволяющий объединить обнаружение с согласованием или синхронизацией в одном протокольном обмене.

D6

Некоторые задачи могут быть значимыми лишь на локальном канале, о другие сохраняют значимость в маршрутизируемой сети и требуют операций вне канала (off-link). Таким образом, партнёры могут быть прямыми соседями по каналу L2 или более удалёнными, доступными лишь через уровень L3. Поэтому нужны механизмы обнаружения агентов ASA, поддерживающих определённые технические задачи, на локальном канале и за его пределами.

D7

Процессу обнаружения следует быть достаточно гибким для особых случаев, таких как указанные ниже.
  • В процессе инициализации устройство должно быть способно организовать взаимное доверие с автоматическими узлами в сети и участвовать в механизме проверки подлинности. Хотя это неизбежно начинается с обнаружения, случай является особым, поскольку доверие ещё не организовано. Этот вопрос рассматривается в [RFC8995]. Требуется, чтобы после организации доверия с устройством все агенты ASA в нем наследовали свидетельства устройства и также становились доверенными. Это не препятствует наличию у устройства нескольких свидетельств (credential).
  • В зависимости от типа сети может потребоваться обнаружение других централизованных функций, таких как операционный центр (Network Operations Center или NOC) [RFC8368]. Протокол должен быть способен поддерживать такое обнаружение в процессе инициализации, как и обнаружение в процессе работы.

D8

Процессу обнаружение недопустимо создавать избыточный трафик и он должен учитывать спящие узлы.

D9

Требуется механизм обслуживания устаревших результатов обнаружения.

B.2. Требования к синхронизации и согласованию

Сети AN должны быть способны управлять разнотипными параметрами и учитывать множество измерений, таких как задержки, нагрузка, неиспользуемые или ограниченные ресурсы, конфликты запроса ресурсов, настройки защиты, экономия энергии, балансировка нагрузки и т. п. Информацию о состоянии и метрику ресурсов узлам требуется использовать совместно для динамической настройки и мониторинга ресурсов. Хотя это может быть достигнуты с помощью имеющихся протоколов (если они есть), новый протокол должен быть способен поддерживать обмен параметрами, включая взаимную синхронизацию, даже если согласование, как таковое, не требуется. В общем случае эти параметры применяются не ко всем участвующим узлам, а лишь к их части.

SN1

Базовым требованием к протоколу является способность представлять, обнаруживать, синхронизировать и согласовывать почти любой тип сетевых параметров между выбранными подмножествами участвующих узлов.

SN2

Согласование выполняется с помощью итераций запросов и откликов, которые гарантированно должны завершаться (успех или отказ). Хотя для каждого случая должны быть определены правила разрыва (tie-breaking), протоколу следует иметь некие общие механизмы для предотвращения петель или «зависания», такие как ограничение числа пересылок или тайм-ауты.

SN3

Синхронизация должна быть возможна для малых и больших групп устройств.

SN4

Чтобы не «изобретать велосипед», протоколу следует поддерживать инкапсуляцию форматов данных, используемых имеющимися протоколами настройки (такими как NETCONF и YANG), когда это удобно.

SN5

Вмешательство человека в сложных ситуациях дорого и чревато ошибками, поэтому желательна синхронизация и согласование параметров множества устройств без участия человека, когда координация устройств может повысить общую производительность сети. Отсюда следует, что требования протокола к ресурсам должны быть достаточно скромными, чтобы протокол можно было реализовать на любом устройстве, которое без этого требовало бы привлечения человека. Работа протокола на узлах с ограниченными возможностями рассмотрена в [RFC8993].

SN6

Вмешательство людей в больших сетях часто заменяется использованием вертикальных (top-down) систем сетевого управления (network management system или NMS). Поэтому протоколу, как части инфраструктуры сетей AN, следует поддерживать возможность работы на любом устройстве, которому иначе потребовалось бы привлечение NMS, а также сосуществования с NMS и такими протоколами, как SNMP и NETCONF.

SN7

Предполагается, что автоматические функции будут реализованы в отдельных ASA, но протокол должен быть достаточно общим, чтобы позволять это. Некоторые примеры представлены ниже.
  • Зависимости и конфликты. При выборе конфигурации для данного устройства может потребоваться информация от соседей. Это можно реализовать через согласование или синхронизацию, если этого достаточно. Однако элемент в соседнем узле может зависеть от информации от его соседей, для получения которой может потребоваться другая синхронизация или согласование. В результате могут возникать зависимости и конфликты между процедурами согласования и синхронизации. Разрешение таких зависимостей и конфликтов является делом вовлечённого в них ASA. Для этого нужны чёткие границы и механизмы схождения при согласовании, а также те или иные механизмы предотвращения циклических зависимостей и неконтролируемого роста дерева зависимостей. Разработчики ASA должны обеспечить такие механизмы. Роль протокола ограничивается двухсторонней сигнализацией между агентами ASA и предотвращением петель в этой сигнализации.
  • Восстановление после отказов и обнаружение неисправных устройств следует обеспечивать автоматически, насколько это возможно. Роль протокола ограничивается обнаружением, синхронизацией и согласованием. Эти процессы могут выполняться в любое время и ASA может потребоваться повторение любого из них при обнаружении таких событий, как отказ партнёра по согласованию.
  • Поскольку основной целью является минимизация участия человека, нужно, чтобы сеть могла «думать наперёд» перед изменением своих параметров. Одним из аспектов этого является использование агентами ASA базы знаний для предсказания поведения сети, выходящее за рамки сигнального протокола. Другим аспектом является прогнозирование эффекта изменений путём пробного прогона (dry run) согласования до фактического внесения изменений. Поэтому сигнализация пробного прогона является желательным свойством протокола.
Отметим, что требуется поддерживать журнал управления (log), мониторинг, предупреждения и инструменты для вмешательства. Однако это связано скорее со свойствами отдельных ASA, а не самого протокола. В документе [RFC8368] рассматривается связывание агентов с традиционными системами OAM (Operations, Administration, and Maintenance) через автоматическую плоскость управления ACP [RFC8994].

SN8

Протокол сможет работать с широким спектром технических задач, охватывая все типы сетевых параметров. Поэтому протоколу нужен гибкий и легко расширяемый формате для описания задач. На более позднем этапе может оказаться желательным принятие явной информационной модели. Один из вопросов заключается в приспособлении имеющейся модели или разработке новой.

B.3. Конкретные технические требования

T1

Следует обеспечить разработчикам ASA удобство определения новых технических задач, а программистам — их выражения без чрезмерного влияния на эффективность исполнения и размер кода. В частности, должно быть удобно реализовать агенты ASA независимо один от другого как программы пользовательского пространства, а не код ядра, если возможна такая модель программирования. Классы устройств, на которых может работать протокол, рассматриваются в[RFC8993].

T2

Протоколу следует быть просто расширяемым в случаях, когда изначально заданных механизмов обнаружения, синхронизации и согласования окажется недостаточно.

T3

Для универсальности платформы формату данных (payload) протокола следует быть независимым от транспортного протокола и версии IP. В частности, следует поддерживать работу по протоколу IPv6 и IPv4. Однако некоторые функции, такие как групповая адресация на канале, могут зависеть от версии IP. По умолчанию предпочтительней IPv6.

T4

Протокол должен обеспечивать возможность доступа к партнёрам вне канала (off-link) по маршрутизируемым адресам, т. е. не должен ограничиваться операциями на локальном канале (link-local).

T5

Должна обеспечиваться возможность применения внешнего механизма обнаружения, если он подходит для данной технической задачи. Иными словами, обнаружение GRASP не должно быть предварительным условием для согласования и синхронизации GRASP.

T6

Протокол должен быть способен различать одновременные операции с одним или несколькими партнёрами, особенно при возникновении ожидания.

T7

Распространение Intent выходит за рамки этого документа, однако протокол не должен исключать его использования для распространения Intent.

T8

Устройствам следует предоставлять возможность передачи отчётов системе управления. Для некоторых событий должна быть возможность генерации сигналов оператору, а также должна быть предусмотрена возможность экстренного вмешательства (например, для приостановки синхронизации или согласования на некорректно работающем устройстве). Эти функции могут не использовать сам протокол сигнализации, но устройство протокола не должно исключать такое использование.

T9

Поскольку протокол может напрямую менять конфигурацию устройств и оказывать существенное влияние на работу сети, все протокольные обмены должны быть полностью защищены от подставных сообщений и MITM-атак, а также максимально защищены от DoS-атак. Требуется также механизм шифрования для защиты от нежелательного мониторинга. Однако наличие функций защиты в самом протоколе не требуется и можно использовать имеющуюся защищённую среду.

Приложение C. Анализ возможностей современных протоколов

В этом приложении рассматриваются имеющиеся протоколы, связанные с требованиями Приложения B, с целью оценки возможности их выполнения отельным протоколом или их комбинацией.

Многие протоколу включают ту или иную форму обнаружения, но все они представляются предназначенными лишь для определённого применения. Протокол обнаружения служб (Service Location Protocol или SLP) [RFC2608] обеспечивает обнаружение сервиса в управляемых сетях, но требует настройки своих серверов. Обнаружение служб через DNS (DNS-Based Service Discovery или DNS-SD) [RFC6763] в комбинации с Multicast DNS (mDNS) [RFC6762] обеспечивает обнаружение служб для небольших сетей с одним канальным уровнем. В [RFC7558] предпринята попытка расширить это для более крупных автоматических сетей, но решение ещё не стандартизовано. Однако SLP и DNS-SD представляются ориентированными в первую очередь на службы уровня приложений, а не на задачи L2 и L3, относящиеся к базовой настройке сети. Протоколы SLP и DNS-SD основаны на передаче текста.

Простой протокол сетевого управления (Simple Network Management Protocol или SNMP) [RFC3416] использует модель «запрос-отклик», не подходящую для согласования между партнёрами. В NETCONF [RFC6241] применяется модель RPC, позволяющая позитивные и негативные отклики от целевой системы, но этого недостаточно для согласования.

Имеется много протоколов с элементарными возможностями согласования, например, DHCPv6 (Dynamic Host Configuration Protocol for IPv6) [RFC8415], ND (Neighbor Discovery) [RFC4861], PCP (Port Control Protocol) [RFC6887], RADIUS (Remote Authentication Dial-In User Service) [RFC2865], Diameter [RFC6733] и т. п. Большинство из них относится к протоколам настройки или управления, однако они предоставляют лишь простую модель «запрос-отклик» в контексте «ведущий-ведомый» или очень ограниченные возможности согласования.

Есть несколько протоколов сигнализации с элементами согласования. Например, протокол резервирования ресурсов (Resource ReSerVation Protocol или RSVP) [RFC2205] был разработан для согласования параметров качества обслуживания на пути групповых или индивидуальных потоков. Протокол RSVP специализирован для сквозных потоков. Более общее решение предлагает протокол GIST (General Internet Signalling Transport) [RFC5971], однако он пытается решить слишком много проблем, что делает протокол сложным, а также нацелен на передачу сигналов для потока через большое число узлов пересылки (hop), а не на сигнализацию между парой устройств. Тем не менее, не следует полностью исключать возможность расширения RSVP или GIST в качестве протокола синхронизации и согласования. Эти протоколы не представляются подходящими напрямую для обнаружения партнёров.

Протокол RESTCONF [RFC8040] предназначен для передачи сведений NETCONF, представленных на языке YANG, по протоколу HTTP, включая прохождение через узлы-посредники HTML. Хотя протокол обеспечивает эффективное решение в контексте централизованной настройки сложных сетей, он не приспособлен для интерактивного согласования между устройствами-партнерами, особенно простыми, которые могут не обрабатывать YANG.

Протокол DNCP (Distributed Node Consensus Protocol) [RFC7787] определён в качестве базового протокола синхронизации состояний с предложенным профилем использования для управления домашней сетью (Home Networking Control Protocol или HNCP) [RFC7788] при настройке маршрутизаторов Homenet. Применение DNCP для автоматических сетей AN предложено в [ADNCP]. Согласно [RFC7787]:

  • протокол DNCP разработан для обеспечения каждому участвующему узлу возможности публиковать набор TLV (Type-Length-Value) размером до 64 Кбайт и обеспечивать общее представление публикуемых данных;

  • DNCP подходит в основном для данных, которые меняются нечасто;

  • при необходимости часто и быстро менять состояния предпочтительно использовать дополнительный канал «точка-точка».

Протокол DNCP имеет ряд специфических свойств,

  • Каждый участвующий узел имеет уникальный идентификатор.

  • Сообщения DNCP представляются последовательностью объектов TLV и передаются в индивидуальных пакетах UDP или TCP с необязательной защитой (D)TLS.

  • Групповая адресация применяется только для обнаружения соседей DNCP, когда можно снизить уровень защиты.

  • Синхронизация состояний поддерживается лавинной рассылкой с использованием алгоритма Trickle. Взаимная синхронизация и согласование не поддерживаются.

  • Профиль HNCP для DNCP разработан для применения между соединёнными напрямую соседями на общем канале с использованием UDP и адресов IPv6 link-local.

DNCP не соответствует требованиям к протоколу согласования общего назначения, поскольку он разработан специально для лавинной синхронизации. В профиле HNCP этот протокол ограничен сообщениями link-local и протоколом IPv6. Тем не менее, это по меньшей мере интересный пример такого стиля взаимодействия между устройствами без центрального органа, обеспечивающий проверенный метод синхронизации в масштабе сети за счёт лавинной рассылки.

Протокол синхронизации серверных кэшей (Server Cache Synchronization Protocol или SCSP) [RFC2334] описывает метод синхронизации и репликации кэшей между группой узлов.

Несколько лет назад был предложен основанный на IP базовый протокол управления (Generic Control Protocol или IGCP) [IGCP], предназначенный для обмена информацией и согласования, но без прямого обнаружения партнёров. У этого протокола много общего с описанным здесь.

Ни одно из упомянутых выше решений не соответствует полностью требованиям к базовому обнаружению, синхронизации состояний и согласованию в едином решении. Многие из протоколов предполагают работу в традиционном вертикальном (top-down) сценарии или модели «север-юг», а не в гибком варианте однорангового (партнерского) взаимодействия. Многие из протоколов так или иначе специализированы. В результате не удалось найти комбинацию существующих протоколов, соответствующую требованиям Приложения B. Не найдено также путей расширения имеющихся протоколов в соответствии с этими требованиями.

Благодарности

Основной вклад в предварительные версии этого документа внёс Sheng Jiang, а также важно было участие Toerless Eckert. Существенная часть первоначального рецензирования была представлена Joel Halpern, Barry Leiba, Charles E. Perkins, Michael Richardson. William Atwood оказал значительную помощь в отладке прототипа реализации.

Важные комментарии внесли Michael Behringer, Jéferson Campos Nobre, Laurent Ciavaglia, Zongpeng Du, Yu Fu, Joel Jaeggli, Zhenbin Li, Dimitri Papadimitriou, Pierre Peloso, Reshad Rahman, Markus Stenberg, Martin Stiemerling, Rene Struik, Martin Thomson, Dacheng Zhang, члены исследовательской группы Network Management, рабочей группы ANIMA и IESG.

Адреса авторов

Carsten Bormann
Universität Bremen TZI
Postfach 330440
D-28359 Bremen
Germany
Email: cabo@tzi.org
 
Brian Carpenter (редактор)
School of Computer Science
University of Auckland
PB 92019
Auckland 1142
New Zealand
Email: brian.e.carpenter@gmail.com
 
Bing Liu (редактор)
Huawei Technologies Co., Ltd
Q14, Huawei Campus
Hai-Dian District
No.156 Beiqing Road
Beijing
100095
China
Email: leo.liubing@huawei.com

Перевод на русский язык

Николай Малых

nmalykh@protokols.ru


1В переводе используется принятая в русском языке терминология для автоматических и автоматизированных узлов (систем, элементов). Автоматическая система работает без привлечения человека или внешней системы управления, автоматизированная просто выполняет задание (сценарий), заданный человеком или внешней системой управления. Термин «самоуправляемый» в переводе используется как синоним термина «автоматический». Прим. перев.

2Internet Engineering Task Force — комиссия по решению инженерных задач Internet.

3Internet Engineering Steering Group — комиссия по инженерным разработкам Internet.

Рубрика: RFC | Оставить комментарий

RFC 9010 Routing for RPL (Routing Protocol for Low-Power and Lossy Networks) Leaves

Internet Engineering Task Force (IETF)                   P. Thubert, Ed.
Request for Comments: 9010                                 Cisco Systems
Updates: 6550, 6775, 8505                                  M. Richardson
Category: Standards Track                                      Sandelman
ISSN: 2070-1721                                               April 2021

Routing for RPL (Routing Protocol for Low-Power and Lossy Networks) Leaves

Маршрутизация для листьев RPL

PDF

Аннотация

В этом документе определен механизм для хостов, реализующих независимый от маршрутизации интерфейс на основе обнаружения соседей 6LoWPAN, для определения доступности в сети, использующей маршрутизацию RFC 6550. Документ обновляет RFC 6550, RFC 6775 и RFC 8505.

Статус документа

Документ относится к категории Internet Standards Track.

Документ является результатом работы IETF1 и представляет согласованный взгляд сообщества IETF. Документ прошел открытое обсуждение и был одобрен для публикации IESG2. Дополнительную информацию о стандартах Internet можно найти в разделе 2 в RFC 7841.

Информацию о текущем статусе документа, ошибках и способах обратной связи можно найти по ссылке https://www.rfc-editor.org/info/rfc9010.

Авторские права

Авторские права (Copyright (c) 2021) принадлежат IETF Trust и лицам, указанным в качестве авторов документа. Все права защищены.

К документу применимы права и ограничения, указанные в BCP 78 и IETF Trust Legal Provisions и относящиеся к документам IETF (http://trustee.ietf.org/license-info), на момент публикации данного документа. Прочтите упомянутые документы внимательно. Фрагменты программного кода, включённые в этот документ, распространяются в соответствии с упрощённой лицензией BSD, как указано в параграфе 4.e документа IETF Trust Legal Provisions, без каких-либо гарантий (как указано в Simplified BSD License).

1. Введение

При разработке сетей LLN обычно рассматриваются вопросы экономии энергии, поскольку электропитание является наиболее ограниченные ресурсом. Другие ограничения ресурсов включают ограниченный объем памяти, рабочий цикл устройств LLN и потери при передаче, связанные с энергетическими ограничениями.

В IETF разработан документ «RPL: IPv6 Routing Protocol for Low-Power and Lossy Networks» [RFC6550] для обеспечения маршрутизации IPv6 [RFC8200] с учётом этих ограничений. Протокол RPL относится к протоколам маршрутизации на основе вектора удалённости, которые в отличие от протоколов на основе состояния канала (link-state), ограничивают объем топологической информации, которую нужно поддерживать на каждом узле, и не требует схождения для предотвращения микропетель.

Для хранения состояний сигнализации и маршрутизации в сетях с ограничениями RPL поддерживает растяжение путей (path stretch, см. [RFC6687]), при этом маршрутизация выполняется лишь по ориентированному на адресата направленному ациклическому графу (Destination-Oriented Directed Acyclic Graph или DODAG), оптимизированному для достижения корневого узла, а не по кратчайшему пути между двумя партнёрами, что бы это не означало в данной сети LLN. При этом вместо качества путей между партнёрами (peer-to-peer или P2P) выполняется обмен значительно меньшим объёмом управляющего трафика и состояний маршрутизации для работы протокола по кратчайшему пути «каждый с каждым». Кроме того, можно «неторопливо» исправлять по запросу оборванные пути на основе обнаружения несогласованности доставки в плоскости данных, что позволяет избавиться от расхода энергии на проактивное восстановление неиспользуемых путей.

Для многих (но не всех) узлов DODAG обеспечивает множество вариантов пересылки в направлении корня через так называемых родителей (parent). RPL организует маршруты заранее (проактивно), но приспособлен к «нечётким» соединениям (когда не предполагается стабильность физической топологии) и использует «неторопливую» поддержку маршрутов, исправляя их по факту (реактивно) наличия реального трафика. В результате RPL обеспечивает связность для большинства узлов LLN большую часть времени, но не обеспечивает сходимости в классическом понимании.

RPL можно развернуть вместе с обнаружением соседей IPv6 (Neighbor Discovery или ND) [RFC4861] [RFC4862] и 6LoWPAN ND [RFC6775] [RFC8505] для поддержки доступности внутри многоканальной подсети NBMA. В этом режиме адреса IPv6 анонсируются индивидуально как маршруты к хостам. Некоторые узлы могут служить маршрутизаторами и участвовать в пересылке, тогда как другие лишь передают и принимают пакеты, выступая в плоскости данных лишь в качестве хостов. В соответствии с терминологией [RFC6550] хост IPv6 [RFC8504], достижимый через сеть RPL, называется листом (leaf).

В разделе 2 [RFC9008] определены термины RPL leaf, RPL-Aware Leaf (RAL), RPL-Unaware Leaf (RUL). Лист RPL является хостом, подключённым к одному или нескольким маршрутизаторам RPL. Лист полагается на маршрутизаторы RPL для пересылки своего трафика через домен RPL, но сам не пересылает трафик других узлов. В отличие от RAL, лист RUL не участвует в RPL и полагается на свои маршрутизаторы RPL для вставки маршрутов к своим адресам IPv6 в домене RPL.

      ------+---------
            |          Internet
            |
         +-----+
         |     | <------------- Корень 6LBR / RPL DODAG
         +-----+                     ^
            |                        |
      o    o   o  o                  | RPL
  o o   o  o   o  o     o    o       |
 o  o o  o o    o   o  o   o  o      |  +
 o   o      o     o   o   o    o     |
o  o   o  o   o  o    o    o  o      | 6LoWPAN ND
   o  o  o  o        o   o           |
  o       o            o    o        v
o      o     o <------------- 6LR / Граничный маршрутизатор RPL
                                     ^
                                     | Только 6LoWPAN ND
                                     v
             u <------------- 6LN / не знающий RPL лист

Рисунок 1. Вставка маршрутов от имени RUL.


Устройство RUL может быть не в состоянии участвовать в работе по причине сильных ограничений по питанию или размеру кода, а также небезопасности вставки таким узлом маршрутов в RPL. Использование 6LoWPAN ND вместо RPL в качестве интерфейса между хостом и маршрутизатором ограничивает фронт возможных атак со стороны RUL на домен RPL. Если все RUL и понимающие RPL узлы (RPL-Aware Node или RAN) используют для обнаружения соседей 6LoWPAN ND, можно также защитить владение адресами для всех узлов, включая RUL.

В этом документе описана вставка маршрутизатором маршрутов к хостам в домен RPL от имени RUL. В разделе 5 описано, как RUL может воспользоваться 6LoWPAN ND для получения услуг маршрутизации. В этой модели RUL является также узлом 6LoWPAN (6LN), а понимающий RPL маршрутизатор — маршрутизатором 6LoWPAN (6LR). Используя механизм регистрации адресов 6LoWPAN ND, RUL сообщает, что маршрутизатор должен ввести маршрут к хосту для зарегистрированного адреса.

Механизм режима RPL Non-Storing применяется для расширения состояния маршрутизации связностью с RUL даже при работе DODAG в режиме Storing. Операция пересылки индивидуальных пакетов в 6LR обслуживает RUL, как описано в параграфе 4.1.1 [RFC9008].

Примерами RUL являются некоторые датчики с очень ограниченным питанием (например, датчики повреждения стёкол в окнах и выключатели света с кинетическим питанием). Другие применения этой спецификации могут включать интеллектуальные сети управления бытовыми приборами, такими как стиральные машины и домашние системы отопления. Бытовые электроприборы не могут участвовать в работе протокола RPL в интеллектуальной сети управления, но могут взаимодействовать с такой сетью для контроля и измерений.

Данная спецификация может разворачиваться постепенно в сети, реализующей [RFC9008], при этом обновлять требуется лишь корень и маршрутизаторы 6LR, соединённые с RUL. Маршрутизаторы RPL на пути будут видеть лишь индивидуальный трафик IPv6 между корнем и 6LR.

Организация оставшейся части документа описана ниже.

  • В разделах 3 и 4 приведено ненормативное описание основных аспектов RPL и 6LoWPAN ND, используемых в спецификации для подключения 6LN, являющихся RUL, через сеть RPL.

  • В разделе 5 даны требования к RUL для обслуживания этих листьев маршрутизатором RPL, соответствующим данной спецификации.

  • В разделе 6 представлены изменения по отношению к [RFC6550] — новое поведение, когда 6LR анонсирует адреса 6LN в сообщении RPL DAO на основе регистрации ND узлом 6LN, а корень RPL DODAG выполняет обмен EDAR/EDAC с граничным маршрутизатором 6LoWPAN (6LBR) от имени 6LR и изменения некоторых опций RPL и RPL Status для облегчения интеграции протоколов.

  • В разделе 7 представлены изменения по отношению к [RFC9009] — использование сообщения DCO расширено на режим работы Non-Storing для передачи сведений об асинхронных передачах из корня в 6LR.

  • В разделе 8 представлены изменения по отношению к [RFC6775] и [RFC8505] — диапазон значений статуса ARO/EARO сужен до 64, а оставшиеся биты переведены в резервные.

  • В разделах 9 и 10 представлена работа этой спецификации для индивидуальных и групповых потоков, а раздел 11 посвящён вопросам безопасности.

2. Терминология

2.1. Уровни требований

Ключевые слова необходимо (MUST), недопустимо (MUST NOT), требуется (REQUIRED), нужно (SHALL), не следует (SHALL NOT), следует (SHOULD), не нужно (SHOULD NOT), рекомендуется (RECOMMENDED), не рекомендуется (NOT RECOMMENDED), возможно (MAY), необязательно (OPTIONAL) в данном документе интерпретируются в соответствии с BCP 14 [RFC2119] [RFC8174] тогда и только тогда, когда они выделены шрифтом, как показано здесь.

2.2. Глоссарий

6BBR

6LoWPAN Backbone Router — магистральный маршрутизатор 6LoWPAN.

6CIO

6LoWPAN Capability Indication Option — опция индикации совместимости 6LoWPAN.

6LBR

6LoWPAN Border Router — граничный маршрутизатор 6LoWPAN.

6LN

6LoWPAN Node — узел 6LoWPAN (хост или маршрутизатор с ограниченным питанием).

6LoRH

6LoWPAN Routing Header — заголовок маршрутизации 6LoWPAN.

6LoWPAN

IPv6 over Low-Power Wireless Personal Area Network — IPv6 в персональной беспроводной сети со слабым питанием.

6LR

6LoWPAN Router — маршрутизатор 6LoWPAN.

AP-ND

Address-Protected Neighbor Discovery — обнаружение соседей с защитой адреса.

ARO

Address Registration Option — опция регистрации адреса.

DAC

Duplicate Address Confirmation — подтверждение дубликата адреса.

DAD

Duplicate Address Detection — обнаружение дубликатов адресов.

DAO

Destination Advertisement Object — объект анонсирования адресата (сообщение RPL).

DAR

Duplicate Address Request — запрос о дубликатах адреса.

DCO

Destination Cleanup Object — объект очистки адресата (сообщение RPL).

DIO

DODAG Information Object — информационный объект DODAG (сообщение RPL).

DODAG

Destination-Oriented Directed Acyclic Graph — ориентированный на адресата ациклический направленный граф.

EARO

Extended Address Registration Option — расширенная опция регистрации адреса.

EDAC

Extended Duplicate Address Confirmation — расширенное подтверждение дубликата адреса.

EDAR

Extended Duplicate Address Request — расширенный запрос о дубликатах адреса.

EUI

Extended Unique Identifier — расширенный уникальный идентификатор.

LLN

Low-Power and Lossy Network — сеть со слабым питанием и потерями.

MLD

Multicast Listener Discovery — обнаружение «слушателей» группового трафика.

MOP

RPL Mode of Operation — режим работы RPL.

NA

Neighbor Advertisement — анонсирование соседа.

NBMA

Non-Broadcast Multi-Access — множественный доступ без широковещания.

NCE

Neighbor Cache Entry — запись кэша соседа.

ND

Neighbor Discovery — обнаружение соседей.

NS

Neighbor Solicitation — запрос (ходатайство) о соседстве.

PIO

Prefix Information Option — опция сведений о префиксе.

RA

Router Advertisement — анонсирование маршрутизатора.

RAL

RPL-Aware Leaf — понимающий протокол RPL лист.

RAN

RPL-Aware Node — понимающий протокол RPL узел (маршрутизатор RPL или понимающий RPL лист).

RH3

Routing Header for IPv6 (type 3) — заголовок маршрутизации для IPv6 (тип 3).

ROVR

Registration Ownership Verifier — проверяющий владение регистрацией.

RPI

RPL Packet Information — информация пакета RPL.

RPL

Routing Protocol for Low-Power and Lossy Networks — протокол маршрутизации для сетей LLN.

RUL

RPL-Unaware Leaf — не понимающий протокол RPL лист.

SAVI

Source Address Validation Improvement — улучшение проверки адреса источника.

SLAAC

Stateless Address Autoconfiguration — автоматическая настройка адреса без учёта состояния.

SRH

Source Routing Header — заголовок заданной источником маршрутизации.

TID

Transaction ID — идентификатор транзакции (счётчик в EARO).

TIO

Transit Information Option — опция транзитной информации.

2.3. Связанные документы

Используемая в документе терминология соответствует «Terms Used in Routing for Low-Power and Lossy Networks» [RFC7102]. Глоссарий принятых в 6LoWPAN сокращений дан в параграфе 2.2. Другие термины, применяемые в LLN, определены в «Terminology for Constrained-Node Networks» [RFC7228]. В этой спецификации термины 6LN и 6LR служат для обозначения узлов, играющих соответствующую роль в 6LoWPAN ND, от которых не ожидается иной функциональности, такой как сжатие заголовков 6LoWPAN [RFC6282].

Термины RPL, RPI, RPL Instance (указывается RPLInstanceID), «вверх» (up) и «вниз» (down) определены в «RPL: IPv6 Routing Protocol for Low-Power and Lossy Networks» [RFC6550]. RPI является абстрактной информацией, определённой в RPL для размещения в пакетах данных (например, опция RPL Option [RFC6553] в заголовке IPv6 Hop-By-Hop). В более широком смысле RPI часто указывает саму опцию RPL. Сообщения DAO и DIO определены в [RFC6550], а DCO — в [RFC9009].

Термины RUL, RAN, RAL в документе применяются в соответствии с [RFC9008]. RAN указывает лист RAL или маршрутизатор RPL. В отличие от RUL, узел RAN управляет доступностью своих адресов и префиксов путём самостоятельной их вставки в RPL.

В документе также применяются указанные ниже термины из других документов.

Classical IPv6 ND — классическое обнаружение соседей IPv6

«Neighbor Discovery for IP version 6 (IPv6)» [RFC4861] and «IPv6 Stateless Address Autoconfiguration» [RFC4862].

6LoWPAN

«Problem Statement and Requirements for IPv6 over Low-Power Wireless Personal Area Network (6LoWPAN) Routing» [RFC6606] и «IPv6 over Low-Power Wireless Personal Area Networks (6LoWPANs): Overview, Assumptions, Problem Statement, and Goals» [RFC4919].

6LoWPAN ND — обнаружение соседей 6LoWPAN

«Neighbor Discovery Optimization for IPv6 over Low-Power Wireless Personal Area Networks (6LoWPANs)» [RFC6775], «Registration Extensions for IPv6 over Low-Power Wireless Personal Area Network (6LoWPAN) Neighbor Discovery» [RFC8505], «Address-Protected Neighbor Discovery for Low-Power and Lossy Networks» [RFC8928] и «IPv6 Backbone Router» [RFC8929].

3. Внешние маршруты RPL и «артефакты» плоскости данных

Протокол RPL изначально был предназначен для оконечных (stub) сетей, в который единственным граничным маршрутизатором является корень RPL DODAG (обычно совмещённый с 6LBR) и все узлы сети понимают RPL. Но спецификация [RFC6550] поддерживает расширения для внешних маршрутов (target — цель в терминологии RPL) с помощью флага E (External) в опции TIO (Transit Information Option). Внешние цели обеспечивают возможность взаимодействия с адресатами вне домена RPL и соединёнными с этим доменом через граничные маршрутизаторы RPL, не являющиеся корнями. В параграфе 4.1 [RFC9008] приведён набор правил (кратко изложены ниже), которые применяются для маршрутизации пакетов во внешние сети и из них. Лист RUL является особым случаем внешней цели, которая также является хостом, напрямую подключённым к домену RPL.

6LR, выступающий граничным маршрутизатором для внешних маршрутов, анонсирует их, используя сообщения DAO режима Non-Storing, которые передаются по индивидуальному адресу напрямую в корень, даже при работе DODAG в режиме Storing. Маршруты режима Non-Storing не видны в домене RPL и все пакеты маршрутизируются через корень. Корень RPL DODAG туннелирует пакеты данных напрямую маршрутизатору 6LR, анонсировавшему внешний маршрут, где эти пакеты декапсулируются и пересылаются.

Сигнализация RPL Non-Storing MOP и инкапсулированные пакеты IPv6-in-IPv6 представляются промежуточным устройствам как обычный трафик. Поддержка внешних маршрутов влияет лишь на корень и 6LR. Это может работать с унаследованными промежуточными маршрутизаторами и не добавляет состояний, которые эти маршрутизаторы должны поддерживать. RUL является примером адресата, доступного через внешний маршрут, который служит также маршрутом к хосту.

Пакеты данных RPL обычно содержат заголовок Hop-by-Hop с опцией RPL [RFC6553], включающей RPI (RPL Packet Information, см. параграф 11.2 в [RFC6550]). Пока лист RUL ещё не поместил RPL Option во внешнюю цепочку заголовков, пакеты от RUL и к нему инкапсулируются в туннель IPv6-in-IPv6 между корнем и 6LR, обслуживающим RUL (см. разделы 7 и 8 в [RFC9008]). Если пакет от RUL включает RPI, 6LR, служащий граничным маршрутизатором RPL, переписывает RPI для указания RPL Instance и установки флагов, но не обязан инкапсулировать пакет (см. параграф 9.2.2).

В режиме Non-Storing идущие вниз по DODAG пакеты содержат заголовок Source Routing (SRH). Инкапсуляцию IPv6-in-IPv6, RPI и SRH вместе называют артефактами RPL, их можно сжать с помощью метода, описанного в [RFC8138]. В Приложении A дан пример сжатого формата для пакетов, пересылаемых корнем узлу RUL в DODAG режима Storing.

Внутренний пакет, пересылаемый листу RUL, может включать артефакты RPL, например, RPI при наличии этой опции в исходном пакете и SRH в DODAG с режимом Non-Storing. В [RFC9008] предполагается, что RUL поддерживает базовые требования к узлам IPv6 в соответствии с [RFC8504], в частности, требования параграфов 4.2 и 4.4 в [RFC8200]. Поэтому предполагается, что RUL игнорирует артефакты RPL, которые могут оставаться, — SRH с Segments Left = 0 или RPL Option в заголовке Hop-by-Hop (может быть пропущен, если не удалось распознать, см. параграф 5.3).

От RUL не ожидается поддержка сжатия, заданного в [RFC8138], поэтому граничный маршрутизатор (здесь 6LR) распаковывает пакет перед его отправкой RUL по внешнему маршруту [RFC9008].

4. Обнаружение соседей 6LoWPAN

В этом разделе рассматриваются используемые спецификацией механизмы 6LoWPAN ND в качестве справки для читателей. Полное описание этих механизмов представлено в [RFC6775], [RFC8505] и [RFC8928].

4.1. Регистрация адреса в соответствии с RFC 6775

Классический протокол обнаружения соседей IPv6 (IPv6 Neighbor Discovery или IPv6 ND) [RFC4861] [RFC4862] был разработан для последовательных каналов и транзитных сред, таких как Ethernet. Это реактивный протокол, в значительной степени зависящий от групповых операций для обнаружения адресов (Address Discovery) и дубликатов адресов (Duplicate Address Detection или DAD).

В документе «Neighbor Discovery Optimization for IPv6 over Low-Power Wireless Personal Area Networks (6LoWPANs)» [RFC6775] механизмы IPv6 ND расширены для работы в ограниченных по питанию сетях LLN. Основной функцией [RFC6775] является упреждающее создание записей кэширования соседей (Neighbor Cache Entry или NCE) в 6LR и предотвращения дублирования адресов, для чего добавлен unicast-механизм регистрации адресов, сокращающий применение групповых сообщений по сравнению с классическим протоколом IPv6 ND.

В [RFC6775] также задана опция регистрации адресов (Address Registration Option или ARO), передаваемая в индивидуальных сообщениях NS3 и NA4 между узлом 6LoWPAN (6LN) и маршрутизатором 6LoWPAN (6LR). Определены также сообщения для запроса (Duplicate Address Request или DAR) и подтверждения (Duplicate Address Confirmation или DAC) дубликатов адреса между 6LR и 6LBR. В сети LLN маршрутизатор 6LBR является центральным хранилищем зарегистрированных адресов домена и источником достоверных данных о владении и уникальности.

4.2. Расширенная регистрация адреса в соответствии с RFC 8505

«Registration Extensions for IPv6 over Low-Power Wireless Personal Area Network (6LoWPAN) Neighbor Discovery» [RFC8505] обновляет RFC 6775 базовым механизмом регистрации адресов, который может служить для доступа к таким функциям, как маршрутизация и ND прокси. Для этого в [RFC8505] определена опция расширенной регистрации адреса (Extended Address Registration Option или EARO), как показано на рисунке 2.

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     Type      |     Length    |    Status     |    Opaque     |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  Rsvd | I |R|T|     TID       |     Registration Lifetime     |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
~          Registration Ownership Verifier (ROVR)               ~
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Рисунок 2. Формат опции EARO.


4.2.1. Флаг R

[RFC8505] определяет флаг R для опции EARO. Регистрирующий узел устанавливает флаг R для указания маршрутизатору 6LR обеспечения доступности для зарегистрированного адреса. При сброшенном флаге R регистрирующий узел обрабатывает доступность Registered Address иными путями. В сети RPL это означает, что узел RAN вносит маршрут самостоятельно или использует другой маршрутизатор RPL для служб доступности.

Этот документ задаёт использование флага R в контексте RPL. Узел RPL с функциональностью 6LN [RFC8505] требует служб доступности для адреса IPv6 тогда и только тогда, когда он устанавливает флаг в R в NS(EARO), служащем для регистрации адреса в 6LR, служащем граничным маршрутизатором RPL. При получении NS(EARO) маршрутизатор RPL создаёт сообщение DAO для Registered Address тогда и только тогда, когда установлен (1) флаг R.

В параграфе 9.2 описаны дополнительные операции, вызываемые наличием флага R в EARO сообщения NS или NA.

4.2.2. TID, флаг I и поле Opaque

При установленном (1) флаге T опция EARO включает значение счётчика, называемое идентификатором транзакции (Transaction ID или TID), которое требуется для заполнения поля Path Sequence в опции RPL Transit Information (TIO). По этой причине поддержка поддержка узлом RUL требований [RFC8505], а не только [RFC6775] является предварительным условием в данной спецификации (см. 5.1. Поддержка 6LoWPAN ND). Опция EARO включает также поле Opaque и связанное с ним поле I, определяющее содержимое и применение поля Opaque (см. параграф 9.2.1).

4.2.3. Проверка владельца маршрута

В параграфе 5.3 [RFC8505] введено поле проверки регистрации владения (Registration Ownership Verifier или ROVR) размером от 64 до 256 битов. ROVR заменяет 64-битовые расширенные уникальные идентификаторы (EUI-64) в опции ARO [RFC6775], которые служили для однозначного указания регистрации адресов канального уровня, но не обеспечивали защиты от подделки.

«Address-Protected Neighbor Discovery for Low-Power and Lossy Networks» [RFC8928] использует поле ROVR как криптографическое подтверждение владения для предотвращения регистрации другими адреса, который уже выделен. Применение поля ROVR позволяет маршрутизатору 6LR блокировать трафик, исходящий от чужого адреса.

Эта спецификация не решает вопрос расширения защиты [RFC8928] на RPL. С другой стороны, документ добавляет ROVR в сообщение DAO для создания в корне проксируемого EDAR (6.1. Обновлённая опция RPL Target), что позволяет узлам, знающим маршрут к хосту, знать значение ROVR, связанное с Target Address.

4.3. EDAR/EDAC в соответствии с RFC 8505

[RFC8505] заменяет сообщения DAR/DAC сообщениями EDAR/EDAC для включения поля ROVR. Обмен EDAR/EDAC происходит между 6LR и 6LBR и запускается сообщением NS(EARO) от 6LN для создания, обновления или удаления соответствующего состояния в 6LBR. Обмен защищён механизмом повтора, описанным в параграфе 8.2.6 [RFC6775], хотя в LLN, где по умолчанию принято значение RetransTimer (RETRANS_TIMER) [RFC4861] в 1 секунду, может потребоваться большее значение для учёта времени кругового обхода между 6LR и 6LBR.

В RPL [RFC6550] задана периодическая отправка DAO от 6LN по всем путям до корня, поддерживающего состояние маршрутизации в сети RPL, в течение всего срока действия, указанного источником DAO. Это означает, что для каждого адреса имеется два сообщения keep-alive, проходящие через всю сеть, — одно к корню, другое к 6LBR.

Эта спецификация не задаёт периодического обмена EDAR/EDAC через LLN. 6LR превращает периодические NS(EARO) от RUL в сообщение DAO для корня при каждом обновлении, но EDAR создаётся лишь при первой регистрации для DAD, требуемого до введения адреса в RPL. При получении сообщения DAO корень проксирует обмен EDAR для обновления состояния 6LBR от имени 6LR, как показано на рисунке 8 в параграфе 9.1.

4.3.1. Опция Capability Indication в соответствии с RFC 7400

В «6LoWPAN-GHC: Generic Header Compression for IPv6 over Low-Power Wireless Personal Area Networks (6LoWPANs)» [RFC7400] добавлена опция индикации возможностей (6LoWPAN Capability Indication Option или 6CIO), позволяющая узлу раскрывать свои возможности в сообщениях RA (Router Advertisement). В [RFC8505] определены биты 6CIO, включая перечисленные ниже.

L

Узел является маршрутизатором 6LR.

E

Узел является регистратором IPv6 ND, т. е. поддерживает регистрацию на основе EARO.

P

Узел является регистратором маршрутизации, т. е. регистратором IPv6 ND, обеспечивающим сведения о доступности для зарегистрированных адресов.

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     Type      |   Length = 1  |     Reserved      |D|L|B|P|E|G|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                           Reserved                            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Рисунок 3. Флаги 6CIO.


6LR, обеспечивающий услуги доступности RUL в сети RPL, как указано в этом документе, включает опцию 6CIO в свои сообщения RA и устанавливает (1) флаги L, P, E, как предписано [RFC8505] (см. 9.2. Детали работы).

5. Требования для листа, не знающего о RPL

Этот документ описывает расширение маршрутизации RPL для доступа к листьям RUL. В этом разделе описана минимальная реализация независимой от RPL функциональности, которую нужно реализовать в RUL для получения услуг маршрутизации своих адресов.

5.1. Поддержка 6LoWPAN ND

Для получения услуг маршрутизации от реализующего эту спецификацию маршрутизатора лист RUL должен поддерживать [RFC8505] и установить флаги R и T в опции EARO, как указано в параграфах 4.2.1 и 4.2.2. В параграфе 9.2.1 описано новое поведение для листа RUL, например, когда установленный в NS(EARO) флаг R не возвращается в NA(EARO), что говорит об отказе при вставке маршрута.

Предполагается, что RUL запрашивает услуги маршрутизации лишь в том случае, когда маршрутизатор является источником сообщений RA с опцией 6CIO, где установлены (1) флаги L, P и E, как описано в параграфе 4.3.1, если это не отменено в конфигурации. Предполагается также реализация листом RUL требований [RFC8928] для защиты владения его адресом.

Для листа RUL, который может быть подключён к нескольким 6LR, ожидается предпочтение маршрутизаторов, обеспечивающих услуги маршрутизации. Листу RUL нужно зарегистрироваться на всех 6LR, где он хочет получить услуги маршрутизации.

Параллельную регистрацию адреса на нескольких 6LR следует выполнять достаточно быстро с использованием одной и той же опции EARO для данного адреса. Интервал между регистрациями адреса будет аннулировать некоторые из маршрутов, пока регистрация адреса не отобразится на них.

В [RFC8505] заданы значения Status для ошибок в NA(EARO), которые могут приниматься синхронно по NS(EARO) или асинхронно. Лист RUL должен поддерживать оба варианта и воздерживаться от использования адреса, если поле Status показывает, что он был отвергнут (6.3. Обновлённое поле RPL Status).

5.2. Поддержка инкапсуляции IPv6

В параграфе 4.1.1 [RFC9008] заданы правила сигнализации о внешнем получателе (например, RUL) и туннелирования к подключающему его маршрутизатору (6LR). Для завершения туннеля IPv6-in-IPv6 лист RUL, как кост IPv6, способен декапсулировать туннельные пакеты и отбрасывать инкапсулированные пакеты, если они не адресованы ему, или передавать вышележащему уровню для дальнейшей обработки. Как указано в параграфе 4.1 [RFC9008], это не требуется [RFC8504] и туннель IPv6-in-IPv6 от корня завершается на родительском 6LR, поэтому от RUL не требуется поддержка декапсуляции IPv6-in-IPv6.

5.3. Поддержка заголовка Hop-by-Hop

Предполагается, что RUL обрабатывает Option Type в заголовке Hop-by-Hop в соответствии с параграфом 4.2 [RFC8200]. Опции RPI с Option Type = 0x23 [RFC9008] пропускаются, если не распознаны.

5.4. Поддержка заголовка Routing

Предполагается обработка листом RUL неизвестных типов Routing Header в соответствии с параграфом 4.4 [RFC8200]. Это предполагает, что заголовок SRH, имеющий тип 3 [RFC6554], игнорируется при Segments Left = 0. При ином значении Segments Left лист RUL отбрасывает пакет и передаёт по адресу отправителя пакета сообщение ICMP Parameter Problem с кодом 0, указывающее нераспознанный тип маршрутизации.

6. Расширение RFC 6550

Этот документ задаёт новое поведение, при котором 6LR передаёт сообщения DAO по индивидуальным (раздел 9) и групповым (раздел 10) адресам от имени листьев, не знающих о RPL. Адреса RUL раскрываются как внешние цели [RFC6550]. В соответствии с [RFC9008] применяется инкапсуляция IPv6-in-IPv6 между 6LR и корнем RPL DODAG для передачи артефактов RPL и их удаления при пересылке за пределы домена RPL, например, листьям RUL.

Документ также синхронизирует отслеживание жизнеспособности корня и 6LBR. Для обоих задаётся одинаковый срок действия и одно сообщение keep-alive — RPL DAO, проходящее через сеть RPL. Другой новинкой в поведении является проксирование корнем RPL DODAG сообщений EDAR маршрутизатору 6LBR от имени 6LR (раздел 8) для любого узла, реализующего функциональность 6LN, описанную в [RFC8505].

В параграфе 6.7.7 [RFC6550] определена опция RPL Target, которую можно применять в управляющих сообщениях RPL (таких как DAO) для передачи префикса адресата. Этот документ добавляет возможность передачи поля ROVR (4.2.3. Проверка владельца маршрута) и адреса IPv6 для анонсирующего префикс узла, когда Target содержит более короткий префикс. Их использование указывается отличным от 0 полем ROVR Size и новым флагом F (параграф 6.1).

Эта спецификация определяет флаг P в опции RPL DODAG Configuration (параграф 6.2). Кроме того, спецификация обеспечивает возможность передачи поля EARO Status, определённого для 6LoWPAN ND в сообщениях RPL DAO DCO и встраиваемого в поле RPL Status (параграф 6.3).

В разделе 12 [RFC6550] описана поддержка в RPL групповых потоков, когда RPL Instance работает в режиме MOP = 3 (режим Storing с поддержкой группового трафика). Эта спецификация расширяет операции корня RPL DODAG для прокси-трансляции операции MLDv2 [RFC3810] между RUL и 6LR (10. Операции протокола для групповых адресов).

6.1. Обновлённая опция RPL Target

Эта спецификация обновляет опцию RPL Target для доставки поля ROVR, заданного для сообщений 6LoWPAN ND, что позволяет корню RPL DODAG генерировать проксируемые сообщения EDAR для 6LBR.

Target Prefix в опции RPL Target размещается слева (старшие биты) и содержит анонсируемый префикс. Префикс размером менее 128 битов указывает маршрут. В поле Prefix Length указывается число битов анонсируемого префикса — 128 для маршрута к хосту, меньшее значение для маршрута к префиксу. Остальное сохранено без изменений.

Данная спецификация добавляет флаг F, при установке которого размер Target Prefix должен быть 128, а само поле должно содержать адрес IPv6 анонсирующего узла, взятый из анонсируемого префикса. В этом случае поле Target Prefix содержит две части информации — маршрут, который может вести к хосту (в зависимости от поля Prefix Length) и адрес IPv6, который может служить для достижения анонсирующего узла и проверки маршрута.

Если флаг F сброшен (0), поле Target Prefix может быть короче 128 битов и должно выравниваться по следующей границе байта после завершения префикса. Дополнительные биты справа заполняются значением 0, как указано в параграфе 6.7.7 [RFC6550].

В соответствии с этой спецификацией поле ROVR составляет оставшуюся часть опции RPL Target. Размер ROVR задаёт новое поле ROVR Size которое взаимно однозначно сопоставляется с полем Code Suffix в сообщении EDAR (таблица 4 в [RFC8505]). Поле ROVR Size берётся из поля Flags, обновлённого в реестре IANA RPL Target Option Flags.

Обновленный формат показан на рисунке 4 и совместим с опцией Target, определённой в [RFC6550]. Рекомендуется применять обновленный формат в новых реализациях для всех режимов MOP с целью подготовки к будущим механизмам проверки владения на основе ROVR, если ограничения устройства не препятствуют этому.

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|   Type = 0x05 | Option Length |F|X|Flg|ROVRsz | Prefix Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
|                Target Prefix (Variable Length)                |
.                                                               .
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
...            Registration Ownership Verifier (ROVR)         ...
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Рисунок 4. Обновленная опция Target.


F

Флаг указывающий, что поле Target Prefix содержит полный (128 битов) адрес IPv6 анонсирующего узла.

X

Флаг, устанавливаемый для запроса у корня выполнение проки-обмена EDAR/EDAC. Флаг устанавливается лишь в случае работы DODAG в режиме Non-Storing и установки узлом флага P в опции DODAG Configuration (параграф 6.2). Флаг может устанавливаться для хост-маршрутов к RUL и RAN, а также устанавливается для внутренних маршрутов к префиксам при установленном флаге F с использованием адреса узла в поле Target Prefix для формирования EDAR. В других случаях флаг не может устанавливаться (1).

Flg (Flags)

Два свободных бита флагов, которые отправитель должен сбрасывать (0), а получатель должен игнорировать.

ROVRsz (ROVR Size)

Размер поля ROVR в 64-битовых словах. В устаревшей опции Target поле должно иметь значение 0, как указано в [RFC6550]. Если значение поля превышает 4, размер ROVR становится неопределённым и узел не сможет проверить ROVR. Реализациям следует распространять опцию Target в восходящем направлении без изменений, для обеспечения возможности её проверки узлом-предком, поддерживающим обновлённое поле ROVR.

Registration Ownership Verifier (ROVR)

То же поле, что и в EARO [RFC8505].

6.2. Дополнительные флаги в опции RPL DODAG Configuration

Опция DODAG Configuration, определённая в параграфе 6.7.6 [RFC6550], расширена здесь для распространения данных конфигурации, влияющих на создание и поддержку DODAG, а также рабочих параметров RPL в DODAG через граф DODAG. В исходном определении 4 бита были зарезервированы для будущих флагов.

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|   Type = 0x04 |Opt Length = 14| |P| | |A|       ...           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                     +
                                  |4 бита |

Рисунок 5. Опция DODAG Configuration (частичное представление).


Эта спецификация определяет новый флаг P (Root Proxies EDAR/EDAC), размещённый в позиции 1 резервного поля флагов в опции DODAG Configuration (отсчёт с 0 для старшего бита), для которого установлено значение 0 в унаследованных реализациях, как указано в параграфах 20.14 и 6.7.6 [RFC6550]. Флаг P устанавливается (1) для индикации выполнения корнем операций посредника, что предполагает поддержку этой спецификации и обновлённой опции RPL Target (6.1. Обновлённая опция RPL Target).

Параграф 4.1.3 в [RFC9008] обновляет [RFC6550] для указания того, что определение флагов применимо лишь к значениям MOP от 0 до 6. Для MOP = 7 реализация должна предполагать выполнение корнем функций посредника.

Опция RPL DODAG Configuration обычно помещается в сообщения DIO (DODAG Information Object), которые распространяются вниз по графу DODAG для формирования и поддержки его структуры. Опция DODAG Configuration копируется без изменения от родителей к потомкам. В [RFC6550] сказано: «Узлам, не являющимся корнем DODAG, недопустимо менять эту информацию при распространении опции DODAG Configuration.» Поэтому унаследованные родители распространяют установленный корнем флаг P всем узлам в графе DODAG.

6.3. Обновлённое поле RPL Status

Поле RPL Status определено в параграфе 6.5.1 [RFC6550] для использования в сообщениях DAO-ACK. Заданные значения приведены в таблице 1.

Таблица 1. Определение RPL Status в RFC 6550.

Диапазон

Назначение

0

Безусловное восприятие

1-127

Непрямой отказ

128-255

Отказ

Поле 6LoWPAN ND Status определено для использования в EARO (см. параграф 4.1 в [RFC8505]). Эта спецификация добавляет возможность разрешить перенос значений 6LoWPAN ND Status в сообщения RPL DAO и DCO, встраивая их в поле RPL Status.

Для решения этой задачи диапазон значений ARO/EARO Status сужен до 0-63 с обновлением реестра IANA, созданного для [RFC6775]. Это обеспечивает поддержку значений RPL Status, как показано на рисунке 6. Реестры IANA описаны в параграфах 12.2, 12.5, 12.6. Эти обновления допустимы, поскольку для реестров задана политика Standards Action в соответствии с [RFC8126] и пока распределены значения, не превышающие 10.

 0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
|U|A|StatusValue|
+-+-+-+-+-+-+-+-+

Рисунок 6. Формат RPL Status.


Эта спецификация обновляет поле RPL Status, как показано ниже.

U

Флаг, установка (1) которого задаёт отказ (reject). При нулевом значении флага StatusValue = 0 указывает успешное восприятие, иные значения — неявный отказ (Not an outright rejection в RFC 6550).

A

Флаг, указывающий тип RPL StatusValue.

Status Value

6-битовое целое число без знака. При установленном (1) флаге A это поле содержит значение, определённое для 6LoWPAN ND EARO Status, при сброшенном (0) — StatusValue для RPL.

При создании сообщения DCO или DAO-ACK в ответ на IPv6 ND NA или EDAC корень RPL DODAG должен копировать код статуса 6LoWPAN ND без изменения в поле RPL Status Value и устанавливать (1) флаг A. Корень RPL DODAG должен устанавливать (1) флаг U для всех кодов отказа и неизвестного состояния. Коды из диапазона 1-10 [RFC8505] считаются индикацией отказа.

В свою очередь, при получении от корня RPL DODAG сообщения DCO или DAO-ACK с RPL Status, где установлен флаг A, маршрутизатор 6LR должен копировать значение RPL Status без изменения в поле Status опции EARO при генерации NA для RUL.

7. Расширение RFC 9009

В [RFC9009] определено сообщение DCO лишь для режима RPL Storing с областью действия на локальном канале (link-local). От всех узлов сети RPL ожидается поддержка этой спецификации, поскольку сообщение обрабатывается на каждом этапе пересылки по очищаемому пути.

Данная спецификация расширяет использование DCO на режим Non-Storing, при этом сообщения DCO передаются насквозь от корня напрямую узлу RAN, отправившему сообщение DAO для рассматриваемой цели. В этом случае от промежуточных узлов не требуется поддержка [RFC9009], они пересылают сообщение DCO как обычный пакет IPv6 между корнем и RAN.

В случае RUL обслуживающий лист маршрутизатор 6LR выступает в качестве узла RAN, получающего Non-Storing DCO. Эта спецификация применяет Non-Storing DCO между корнем и 6LR, служащим точкой присоединения RUL. Поддерживающие эту спецификацию 6LR и корень должны реализовать Non-Storing DCO.

8. Расширение RFC 6775 и RFC 8505

Этот документ обновляет [RFC6775] и [RFC8505], сужая диапазон значений ARO/EARO Status до 64. Два старших (слева) бита исходного поля ND Status сделаны резервными, они должны сбрасываться (0) отправителем и игнорироваться получателем.

Документ также обновляет поведение 6LR, служащего маршрутизатором RPL, и 6LN, служащего листом RUL в 6LoWPAN ND Address Registration, как указано ниже.

  • Если корень RPL DODAG анонсирует способность быть посредником в обмене EDAR/EDAC для 6LBR, маршрутизатор 6LR воздерживается от передачи сообщений EDAR keep-alive. Будучи отделенным от 6LBR, корень периодически создаёт сообщения EDAR для 6LBR по сообщению DAO, говорящему об активности адреса.

  • Применение флага R расширяется на сообщения NA(EARO) для подтверждения установки маршрута.

9. Протокольные операции для индивидуальных адресов

В приведённом ниже описании предполагается, что корень управляет флагом P в опции DODAG Configuration и выполняет операции посредника EDAR, описанные в параграфе 4.3. EDAR/EDAC в соответствии с RFC 8505.

Если флаг P сброшен (0), маршрутизатор 6LR должен периодически генерировать сообщения EDAR и обрабатывать возвращённый статус в соответствии с [RFC8505]. Если EDAC показывает успех, остальная часть потока выполняется, как представлено, но без проксирования обмена EDAR/EDAC.

В параграфе 9.1 приведён обзор внедрения маршрута в RPL, а в параграфе 9.2 — более подробное описание с точки зрения различных устройств, вовлечённых в поток.

9.1. Базовый поток

Эта спецификация отменяет необходимость обмена сообщениями keep-alive для EDAR и EDAC на всем пути от 6LN до 6LBR через mesh-сеть RPL. Вместо этого для обмена EDAR/EDAC с 6LBR корень RPL DODAG выступает посредником (прокси) по сообщениям DAO, обновляющим состояние маршрутизации RPL. Первое сообщение EDAR при новом Address Registration не может быть проксировано, хотя его создание для целей DAD, требует проверки до внесения адреса в RPL.

В сети RPL со включённой функцией за обновление состояния в 6LBR отвечает корень. В результате корень RPL DODAG будет сохранять на 6LBR лишь адреса, внедрённые в RPL. Поскольку листья RUL анонсируются с применением режима Non-Storing, поток DAO и EDAR/EDAC keep-alive может быть вложен в поток (пере)регистрации адресов. На рисунке 7 это показано для первой регистрации адреса с указанием обменов DAD и EDAR/EDAC keep-alive в одной последовательности.

6LN/RUL            6LR   <6LR*>   Корень             6LBR
   |<--Использ ND-->|<-Использ RPL>|<----Использ ND--->|
   |                |<----------Использ ND------------>|
   |                |              |                   |
   |   NS(EARO)     |              |                   |
   |--------------->|                                  |
   |                |            EDAR                  |
   |                |--------------------------------->|
   |                |                                  |
   |                |             EDAC                 |
   |                |<---------------------------------|
   |                |                                  |
   |                |   DAO(X=0)   |                   |
   |                |------------->|                   |
   |                |                                  |
   |                |    DAO-ACK   |                   |
   |                |<-------------|                   |
   |   NA(EARO)     |              |                   |
   |<---------------|              |                   |
   |                |              |                   |

Рисунок 7. Поток регистрации первого RUL.


Для этого потока требуется согласование сроков действия и порядковых номеров в 6LoWPAN ND и RPL. Для согласования значения Path Sequence и Path Lifetime в сообщении DAO берутся из полей Transaction ID и Address Registration lifetime в сообщении NS(EARO) от 6LN.

При первом сообщении Address Registration, показанном на рисунке 7 для режима RPL Non-Storing, обмен EDAR/EDAC выполняется в соответствии с [RFC8505]. При отказе 6LR возвращает сообщение NA с ненулевым статусом узлу 6LN, NCE не создаётся и адрес не передаётся в RPL. В иных случаях 6LR создаёт NCE и внедряет зарегистрированный адрес в маршрутизацию RPL, используя обмен DAO/DAO-ACK с корнем RPL DODAG.

6LN/RUL   <-ND->   6LR   <-RPL->  Root   <-ND->      6LBR
   |                |              |                   |
   |   NS(EARO)     |              |                   |
   |--------------->|              |                   |
   |                |   DAO(X=1)   |                   |
   |                |------------->|                   |
   |                |              |       EDAR        |
   |                |              |------------------>|
   |                |              |       EDAC        |
   |                |              |<------------------|
   |                |    DAO-ACK   |                   |
   |                |<-------------|                   |
   |   NA(EARO)     |              |                   |
   |<---------------|              |                   |

Рисунок 8. Поток регистрации следующего RUL.


6LN обновляет Address Registration для сохранения NCE в 6LR до завершения срока действия. После обновления регистрации 6LR заново внедряет соответствующий маршрут в RPL до завершения срока действия (рисунок 8).

Это заставляет корень RPL DODAG обновить состояние в 6LBR с помощью сообщения EDAC. При возникновении ошибки в проксируемом потоке EDAR код ошибки возвращается в DAO-ACK с использованием RPL Status с установленным (1) флагом A, встроенного в 6LoWPAN Status, как описано в параграфе 6.3.

6LR может получить запрошенное сообщение DAO-ACK после приёма асинхронного Non-Storing DCO, но ненулевой статус в DCO заменяет положительный статус из DAO-ACK независимо от порядка приёма. При получении первого из DAO-ACK или DCO маршрутизатор 6LR отвечает листу RUL сообщением NA(EARO).

Проблема может быть обнаружена позднее, например при переносе адреса в другой граф DODAG с 6LBR, подключённым к другому магистральному маршрутизатору 6BBR (6LoWPAN Backbone Router), как показано на рисунке 5 в параграфе 3.3 [RFC8929]. 6BBR может передать негативный статус ND, например, в асинхронном NA(EARO) для 6LBR.

В [RFC8929] предполагается, что 6LBR совмещён с корнем RPL DODAG, но если это не так, 6LBR должен переслать код состояния источнику EDAR (6LR или служащий посредником корень RPL DODAG). Код статуса ND отображается корнем RPL DODAG в поле RPL Status, а затем обратно в ND Status маршрутизатором 6LR для 6LN. Отметим, что унаследованный узел RAN, получивший сообщение Non-Storing DCO, которое он не поддерживает, будет игнорировать его в соответствии с разделом 6 в [RFC6550]. В результате он не будет знать о своей недоступности, пока не произойдёт следующий обмен RPL. Это состояние будет сбрасываться при следующем обмене Non-Storing DAO, если в DAO-ACK будет возвращена ошибка.

На рисунке 9 показан случай, где 6LBR и корень не совмещены и корень служит посредником для потока EDAR/EDAC.

6LN/RUL  <-ND->  6LR  <-RPL->  Root  <-ND->  6LBR  <-ND->  6BBR
   |              |             |              |             |
   |              |             |              |   NA(EARO)  |
   |              |             |              |<------------|
   |              |             |     EDAC     |             |
   |              |             |<-------------|             |
   |              |     DCO     |              |             |
   |              |<------------|              |             |
   |   NA(EARO)   |             |              |             |
   |<-------------|             |              |             |
   |              |             |              |             |

Рисунок 9. Асинхронное внедрение адреса.


Если корень не является посредником, EDAC с ненулевым статусом приходит в 6LR напрямую. В этом случае 6LR должен сбросить маршрут, используя DAO с Lifetime = 0 и должен распространить статус обратно в RUL через сообщение NA(EARO) со сброшенным флагом R.

RUL может прервать регистрацию в любой момент, воспользовавшись Registration Lifetime = 0. Эта спецификация требует от опции RPL Target доставки ROVR. За счёт этого потока, служащего для heartbeat, достаточно для информирования 6LBR об использовании корня в качестве посредника, как показано на рисунке 8.

Любая комбинация 6LR, корня и 6LBR может быть сжата в один узел.

9.2. Детали работы

В следующих параграфах описано поведение (1) 6LN в качестве RUL, (2) 6LR в качестве граничного маршрутизатора, обслуживающего 6LN, (3) корня RPL DODAG и (4) 6LBR в потоках управления, включающего маршрутизацию RPL в направлении RUL.

9.2.1. 6LN в качестве RUL

Эта спецификация основана на работе совместимого с 6LoWPAN ND узла 6LN/RUL, от которого ожидается указанное ниже поведение.

  1. 6LN выбирает 6LR обеспечивающий услуги доступности для RUL, указывая его опцией 6CIO в сообщениях RA с установленными (1) флагами L, P и E, как предписывает [RFC8505].

  2. 6LN получает глобальный адрес IPv6 через (1) автоматическую настройку без учёта состояния (SLAAC) [RFC4862] из опции PIO [RFC4861] в сообщении RA или (2) другим путём, например DHCPv6 [RFC8415].

  3. После получения адреса 6LN регистрирует его и периодически обновляет регистрацию заранее в течение срока действия предыдущей регистрации, как предписано [RFC6775], для обновления NCE до завершения срока действия, указанного в EARO. 6LN устанавливает (1) флаг T, как предписано в [RFC8505]. TID увеличивается каждый раз в соответствии с параграфом 5.2.1 в [RFC8505], что полностью совместимо с параграфом 7.2 в [RFC6550]).

  4. Как указано в параграфе 5.2 [RFC8505], 6LN может одновременно регистрировать несколько 6LR. В этом случае для всех полей в EARO устанавливаются одни значения для каждой параллельной регистрации адреса, за исключением поля Registration Lifetime и флага R, которые могут различаться. 6LN может отменить часть регистраций или перенести регистрацию с одних 6LR на другие. Для этого 6LN передаёт серию сообщений NS(EARO) с одинаковым TID, устанавливая Registration Lifetime = 0 для прежних 6LR и ненулевое значение для новых 6LR. В этом процессе узлу 6LN следует передавать NS(EARO) с ненулевым Registration Lifetime и убедиться, что хотя бы один раз был достигнут успех, прежде чем передавать NS(EARO) для прерывания другой регистрации. Это позволяет избежать оттока, связанного с временным аннулированием маршрута в сети RPL над общим родителем вовлечённых 6LR.

  5. В соответствии с параграфом 5.1 в [RFC8505] узел 6LN, действующий как RUL, устанавливает флаг R в EARO своих регистрация, для которых нужны услуги маршрутизации. Если флаг R не возвращается в NA, лист RUL должен считать, что организация маршрутов через данный 6LR привела к отказу и следует попытаться использовать другой 6LR. Листу RUL следует обеспечить успешное завершение регистрации до сброса флага R. В случае конфликта с предшествующим правилом по сроку действия, правило для срока имеет приоритет.

  6. 6LN может использовать любой из маршрутизаторов 6LR, где он зарегистрирован, в качестве принятого по умолчанию шлюза. Использование 6LR, на котором 6LN не зарегистрирован, может приводить к отбрасыванию пакетов в 6LR функцией проверки отправителя SAVI [RFC7039], поэтому не рекомендуется.

Даже без поддержки RPL можно настроить в RUL необрабатываемое (opaque) значение, предоставляемое протоколу маршрутизации. Если RUL знает RPL Instance, куда следует поместить пакет, листу следует установить в поле Opaque опции EARO значение RPLInstanceID. В оном случае лист должен оставить в поле Opaque значение 0.

Независимо от установки поля Opaque, узел 6LN должен установить I = 0 для указания «топологической информации для передачи протоколу маршрутизации» как указано в параграфе 5.1 [RFC8505].

От RUL не ожидается создание артефактов RPL в пакетах данных, но это возможно. Например, при наличии у RUL минимальных сведений о RPL Instance, лист может создать RPI. Листу RUL, помещающему RPI в пакет данных, следует указывать RPLInstanceID экземпляра RPL, которому следует переслать пакет. Маршрутизатор 6LR принимает решение (например, в соответствии с правилами) использовать данные RPLInstanceID, предоставленные RUL, или заменить их выбранным RPLInstanceID для пересылки внутри домена RPL. Для всех флагов и поля SenderRank устанавливается значение 0, как указано в параграфе 11.2 [RFC6550].

9.2.2. 6LR в качестве граничного маршрутизатора

Маршрутизатор 6LR, обеспечивающий доступность RUL в сети RPL, как указано в этом документе, должен включать 6CIO в свои сообщения RA и устанавливать (1) флаги L, P и E, как предписано [RFC8505]. В соответствии с [RFC8505] маршрутизатор 6LR создаёт EDAR при получении действительного сообщения NS(EARO) для регистрации нового адреса IPv6 узлом 6LN. При успешном начальном обмене EDAR/EDAC маршрутизатор 6LR устанавливает в NCE значение Registration Lifetime.

При установленном флаге R в NS(EARO) маршрутизатору 6LR следует внедрить в RPL маршрут к хосту, если это не запрещено по иным причинам, таким как максимальное число родителей RPL. 6LR должен использовать сигнализацию RPL Non-Storing и обновлённую опцию Target (параграф 6.1). Для предотвращения избыточного потока EDAR/EDAC к 6LBR маршрутизатору 6LR следует воздерживаться от установки флага X. 6LR должен запросить DAO-ACK путём установки флага K в сообщении DAO. Успешное внедрение маршрута к адресу RUL указывается сбросом флага U в поле RPL Status сообщения DAO-ACK.

Если при обновлении регистрации корень RPL DODAG устанавливает флаг P в опции DODAG Configuration, 6LR должен воздерживаться от передачи EDAR keep-alive и взамен должен устанавливать флаг X в опции Target сообщений DAO для запроса обмена EDAR/EDAC keep-alive с 6LBR (параграф 6). Если флаг P сброшен, 6LR должен сбросить флаг X для самостоятельной обработки потока EDAR/EDAC.

Поле Opaque в EARO позволяет указать RPL Instance для применения в анонсах DAO и пересылки пакетов, исходящих от Registered Address, при отсутствии в пакете RPI.

Как указано в [RFC8505], при I = 0 в поле Opaque предполагается значение RPLInstanceID, предложенное 6LN, в противном случае не будет предложенного экземпляра RPL. Если 6LR участвует в предложенном RPL Instance, он должен использовать этот экземпляр RPL для Registered Address. Если нет предложенного RPL Instance или 6LR не участвует в предложенном экземпляре RPL, предполагается, что пакеты от 6LN «можно будет однозначно связать хотя бы с одним RPL Instance» [RFC6550] посредством 6LR, например, по правилу сопоставления 6-tuple с RPL Instance.

Сообщение DAO, анонсирующее Registered Address, должно создаваться, как описано ниже.

  1. Registered Address указывается как Target Prefix в обновлённой опции Target сообщения DAO с установкой Prefix Length = 128 и сбросом флага F, поскольку анонсирующий узел не является RUL. Поле ROVR копируется из EARO (6.1. Обновлённая опция RPL Target).

  2. 6LR указывает один из глобальных или локальной уникальных unicast-адресов IPv6 как Parent Address в опции TIO, связанной с опцией Target.

  3. 6LR устанавливает флаг E в TIO для индикации распространения внешнего маршрута в сеть RPL.

  4. Path Lifetime в TIO рассчитывается по Registration Lifetime в EARO с преобразованием секунд в единицы Lifetime Unit сети RPL. Это задаёт ограничение для развёртывания требованием совместимости Lifetime Unit с выражением Registration Lifetime, например, Lifetime Unit = 0x4000 отображает старший бит Registration Lifetime на Path Lifetime. Значение Path Lifetime должно обеспечить срок действия пути, не превышающий регистрацию и охватывающий время кругового обхода на пути к корню.

    При Registration Lifetime = 0 значением Path Lifetime также будет 0 и сообщение DAO становится No-Path DAO, очищая нисходящие маршруты к RUL, а также заставляя корень быть посредником при передаче сообщения EDAR с Lifetime = 0 маршрутизатору 6LBR.

  5. В Path Sequence опции TIO устанавливается значение TID из EARO.

При получении DAO-ACK или тайм-ауте после заданного реализацией числа попыток 6LR должен передать RUL соответствующее сообщение NA(EARO). При получении асинхронного сообщения DCO он должен сразу же передать RUL асинхронное сообщение NA(EARO), сохраняя способность обработки сообщения DAO-ACK, если оно ожидается.

6LR должен установить флаг R в NA(EARO), передаваемом обратно 6LN тогда и только тогда, когда флаг U в RPL Status сброшен, указывая, что Registered Address успешно внедрён маршрутизатором 6LR в RPL и проксирование EDAR завершилось успехом.

Если установлен флаг A в RPL Status, встроенное значение Status возвращается листу RUL в EARO Status. Если установлен также флаг U, регистрация завершается отказом по связанным с 6LoWPAN-ND причинам и NCE удаляется.

Ошибка при внедрении маршрута ведёт к установке флага U. Если ошибка не связана с ND, флаг A сбрасывается. В этом случае регистрация будет успешной, но маршрут RPL не устанавливается. В результате NA(EARO) возвращается с кодом успеха и сброшенным флагом R, означающими, что узел 6LN получил привязку, но не получил маршрута.

Сброшенный флаг A в RPL Status статус DAO-ACK говорит, что операция 6LoWPAN ND успешна и узлу 6LN должно возвращаться EARO Status = 0 (Success). Значение EARO Status = 0 должно использоваться также в случаях, когда 6LR не пытается внедрить маршрут но может создать привязку после успешного обмена EDAR/EDAC или обновить её.

Установка флага U в RPL Status сообщения DAO-ACK говорит, что маршрут не был установлен и флаг R должен быть сброшен в NA(EARO). Флаг R должен также сбрасываться, если 6LR не пытается внедрить маршрут.

В сети со включённым механизмом AP-ND5 в случае DAO-ACK или DCO со EARO Status = 5 (Validation Requested) маршрутизатор 6LR должен спросить у 6LN о владении адресом, как указано в параграфе 6.1 [RFC8928], до завершения регистрации. Этот поток (рисунок 10) обеспечивает проверку адреса до внедрения в маршрутизацию RPL.

6LN                                       6LR        Root        6LBR
 |                                         |           |           |
 |<--------------- RA ---------------------|           |           |
 |                                         |           |           |
 |------ NS(EARO) (ROVR=Crypto-ID) ------->|           |           |
 |                                         |           |           |
 |<-NA(EARO) (Status=Validation Requested)-|           |           |
 |                                         |           |           |
 |---- NS(EARO) и подтвержд. владения ---->|           |           |
 |                                         |           |           |
 |                            <проверка подтверждения> |           |
 |                                                     |           |
 |<------- NA(EARO) (Status=10) -----<отказ>           |           |
 |                                                     |           |
 |                                       <иначе>       |           |
 |                                         |           |           |
 |                                         |--------- EDAR ------->|
 |                                         |                       |
 |                                         |<-------- EDAC --------|
 |                                         |                       |
 |                                         |           |           |
 |                                         |-DAO(X=0)->|           |
 |                                         |           |           |
 |                                         |<- DAO-ACK-|           |
 |                                         |           |           |
 |<---------- NA(EARO) (Status=0) ---------|           |           |
 |                                         |           |           |
                                     ...
 |                                         |           |           |
 |------ NS(EARO) (ROVR=Crypto-ID) ------->|           |           |
 |                                         |-DAO(X=1)->|           |
 |                                         |           |-- EDAR -->|
 |                                         |           |           |
 |                                         |           |<-- EDAC --|
 |                                         |<- DAO-ACK-|           |
 |<---------- NA(EARO) (Status=0) ---------|           |           |
 |                                         |           |           |
                                     ...

Рисунок 10. Защита адреса.


При подтверждённом владении адресом операции продолжаются обычным путём. В частности, создаётся сообщение DAO в ответ на NS(EARO) с подтверждением владения адресом. При отказе подтверждения 6LR отвергает регистрацию, как предписано AP-ND, и может выполнить действия по защите себя от атаки на отказ в обслуживании (Denial-Of-Service или DoS) со стороны обманного 6LN (см. раздел 11. Вопросы безопасности).

6LR может в любой момент передать индивидуальное асинхронное сообщение NA(EARO) со сброшенным флагом R для индикации прекращения услуг маршрутизации и/или с EARO Status = 2 (Neighbor Cache Full) для индикации удаления NCE. Маршрутизатор может также передать финальный анонс RA (индивидуальный или групповой) с полем Lifetime = 0 для индикации прекращения работы в качестве маршрутизатора, как указано в параграфе 6.2.5 [RFC4861]. Это может быть ответом на сообщение DCO или DAO-ACK, указывающее, что путь уже удалён. В иных случаях 6LR должен удалить хост-маршрут к 6LN, используя сообщение DAO с Path Lifetime = 0.

Действительное сообщение NS(EARO) со сброшенным флагом R и отличным от 0 полем Registration Lifetime указывает, что 6LN хочет поддерживать привязку, но больше не требует услуг маршрутизации от 6LR. После приёма такого сообщения, если в соответствии с предыдущим NS(EARO) с установленным флагом R, маршрутизатор 6LR внедрял хост-маршрут к Registered Address в RPL, используя сообщения DAO, 6LR должен аннулировать хост-маршрут в RPL, используя DAO с Path Lifetime = 0. С этого момента поддержка соответствующего маршрута становится задачей 6LN, которая решается (1) сохранением активности через другой 6LR или (2) поддержкой роли RAN с самостоятельным обеспечением доступности.

При пересылке от RUL в домен RPL пакета без RPI маршрутизатор 6LR должен инкапсулироваться пакет в корень и добавить RPI. Если в пакете есть RPI, 6LR должен переписать RPI, но инкапсуляция не требуется.

9.2.3. Корень RPL DODAG

Корень RPL DODAG должен устанавливать флаг P в опции RPL DODAG Configuration создаваемых сообщений DIO (раздел 6) для указания своей роли посредника в обмене EDAR/EDAC и поддержки обновлённой опции RPL Target.

При получении DAO для каждой обновлённой опции RPL Target (параграф 6.1) с установленным флагом X корень должен уведомить 6LBR, используя обмен EDAR/EDAC. Если корень RPL DODAG совмещён с 6LBR, можно применять внутренний API.

Сообщение EDAR должно создаваться в соответствии с приведённым ниже описанием.

  1. Целевой адрес IPv6 из опции RPL Target помещается в поле Registered Address сообщения EDAR.

  2. Значение Registration Lifetime преобразуется из Path Lifetime версии TIO в соответствии с Lifetime Unit в сети RPL и единицей 60 секунд а сообщениях 6LoWPAN ND.

  3. В поле TID устанавливается значение Path Sequence из TIO и указывается код ICMP 1 в сообщении EDAR.

  4. ROVR из опции RPL Target копируется в EDAR, а для ICMP Code Suffix устанавливается подходящее значение в соответствии с таблицей 4 в [RFC8505], в зависимости от размера поля ROVR.

При получении сообщения EDAC от 6LBR корень должен передать DAO-ACK маршрутизатору 6LR, если ожидается DAO. В иных случаях корень должен передать асинхронное сообщение DCO маршрутизатору 6LR, если статус в сообщении EDAC отличается от Success. В любом случае EDAC Status встраивается в RPL Status с установленным флагом A.

Обмен EDAR/EDAC через прокси должен быть защищён таймером, для которого продолжительность и число попыток (1) зависят от реализации (2) и их следует делать настраиваемыми, поскольку корень и 6LBR обычно являются узлами с более высокой производительностью и управляемостью, чем 6LR. При тайм-ауте корень должен вернуть ошибку маршрутизатору 6LR, как указано выше, используя подходящее из сообщений DAO-ACK и DCO с установленными в RPL Status флагами A и U, а также значением RPL Status «6LBR Registry Saturated» [RFC8505].

9.2.4. 6LBR

6LBR не знают о том, что корень RPL DODAG не является новым соединением 6LR с RUL, поэтому данная спецификация не относится к ним. При получении EDAR маршрутизатор 6LBR ведёт себя в соответствии с [RFC8505] и возвращает отправителю сообщение EDAC.

10. Операции протокола для групповых адресов

Поддержка групповых потоков в RPL подробно описана в разделе 12 [RFC6550]. Эта поддержка активируется установкой MOP = 3 (режим Storing с поддержкой групповой адресации) в сообщениях DIO, формирующих DODAG. Этот раздел относится лишь к RPL Instance с режимом MOP = 3. Поддержка группового трафика в RPL не зависит от источника и работает лишь как расширение режима Storing для индивидуальных пакетов. В этой модели RPL групповые пакеты копируются и передаются как индивидуальные кадры L2 для каждого заинтересованного потомка. Это остаётся верным при пересылке между 6LR и слушателем 6LN.

Документ «Multicast Listener Discovery Version 2 (MLDv2) for IPv6» [RFC3810] обеспечивает слушающему узлу интерфейс для регистрации в групповых потоках. В модели MLD маршрутизатор является запрашивающим (querier), а хост — слушателем, который регистрируется у запрашивающего для получения копии нужного потока.

Эквивалент первой регистрации адреса показан на рисунке 11. 6LN, как слушатель MLD, передаёт незапрошенное сообщение Report маршрутизатору 6LR и это позволяет ему сразу же начать приём потока, заставляя 6LR внедрить групповой маршрут в RPL.

6LN/RUL                6LR             Root                   6LBR
   |                    |               |                       |
   | Незапрошен. Report |               |                       |
   |------------------->|               |                       |
   |                    | DAO           |                       |
   |                    |-------------->|                       |
   |                    |    DAO-ACK    |                       |
   |                    |<--------------|                       |
   |                    |               | <Если еще не Done>    |
   |                    |               | Незапрошен.  Report   |
   |                    |               |---------------------->|
   |                    |               |                       |

Рисунок 11. Поток первой групповой регистрации.


Данная спецификация не меняет MLD, но будет работать более эффективно, если асинхронные сообщения для незапрошенных Report и Done передаются узлом 6LN как индивидуальные кадры L2 маршрутизатору 6LR, особенно в беспроводной сети. 6LR выступает как базовый MLD querier с создаёт DAO с групповым адресом в Target Prefix, как указано в разделе 12 [RFC6550]. Как и для индивидуальных хост-маршрутов Path Lifetime для Target отображается из Query Interval и имеет большее значение для учёта переменной задержки распространения к корню. Корень служит посредником в обмене MLD как слушатель, а 6LBR как запрашивающий, чтобы получать пакеты извне домена RPL.

При получении DAO с опцией Target для группового адреса корень RPL DODAG проверяет регистрацию адреса в качестве слушателя и при отсутствии создаёт незапрошенное сообщение Report для группового адреса, как указано в параграфе 6.1 [RFC3810]. Сообщение Report не зависит от источника, поэтому адрес отправителя в нем не указан.

Эквивалент обновления регистрации периодически выполняет запрашивающий маршрутизатор 6LR. По истечении Query Interval маршрутизатор 6LR передаёт Multicast Address Specific Query каждому из слушателей для каждого группового адреса. Слушатели отвечают сообщениями Report, на основе которых 6LR поддерживает объединённый список групповых адресов, где есть слушатели, и анонсирует его в DAO, как указано в разделе 12 [RFC6550]. 6LR может передать General Query с нулевым значением Multicast Address. В этом случае групповой пакет передаётся заинтересованным слушателям в индивидуальных кадрах L2.

При получении Report маршрутизатор 6LR создаёт DAO с опциями Target по числу записей Multicast Address в сообщении Report, копируя поле Multicast Address в Target Prefix опции RPL Target. Сообщение DAO для режима Storing передаётся выбранным родителям 6LR. Аналогичная процедура выполняется асинхронно от описанной между корнем и маршрутизатором (например, 6LBR), обслуживающим групповые потоки на канале, где размещён корень. Сообщения Query и Report также не зависят от источника. Корень один раз включает в список каждый групповой адрес, для которого имеется хотя бы одно активное состояние группового DAO, копирую групповой адрес из DAO в поле Multicast Address записей групповых адресов в Report, как показано на рисунке 12.

6LN/RUL                6LR            Корень               6LBR
   |                    |               |                    |
   |       Query        |               |                    |
   |<-------------------|               |                    |
   |       Report       |               |                    |
   |------------------->|               |                    |
   |                    | DAO           |                    |
   |                    |-------------->|                    |
   |                    |    DAO-ACK    |                    |
   |                    |<--------------|                    |
   |                    |               |       Query        |
   |                    |               |<-------------------|
   |                    |               |       Report       |
   |                    |               |------------------->|
   |                    |               |                    |

Рисунок 12. Поток следующей регистрации.


Любая комбинация 6LR, корня и 6LBR может размещаться на одном узле и в этом случае описанные выше поток обрабатывается внутри узла и могут использоваться вызовы внутреннего API вместо передачи сообщений.

11. Вопросы безопасности

Следует отметить, что в [RFC6550] каждый узел LLN понимает протокол RPL и может быть точкой атаки на сеть через RPL. Данная спецификация улучшает ситуацию за счёт выделения краевых узлов, которые могут взаимодействовать лишь с маршрутизаторами RPL, используя 6LoWPAN ND, что не позволяет организовать атаку из сети RPL.

Работа узлов LLN зависит от 6LBR и участников RPL. Нужна модель доверия, обеспечивающая исполнение этих ролей «правильными» устройствами, для предотвращения таких атак, как «чёрные дыры» (см. раздел 7 в [RFC7416]), DoS-атаки, где мошеннический маршрутизатор 6LR создаёт «мешанину» в сети RPL, анонсируя и удаляя множество фиктивных адресов, «бомбардировка», в которой злонамеренный маршрутизатор 6LBR разрушает состояния сети, используя код состояния 4 («Removed») [RFC8505]. Такая модель доверия может быть основана на защищённых подключениях L2 и защите канального уровня, что является базовым требованием к 6LoWPAN (см. требование 5.1 в Приложении B.5 [RFC8505]).

К данной спецификации в целом применимы разделы «Вопросы безопасности» [RFC6550], [RFC7416], [RFC6775], [RFC8505]. В частности, нужна защита на канальном уровне для предотвращения DoS-атак, в которых злонамеренный узел 6LN создаёт «мешанину» в сети RPL, постоянно регистрируя и отменяя адреса путём установки флага R в EARO.

В [RFC8928] к 6LoWPAN ND добавлен механизм AP-ND, защищающий владельца адреса от «кражи» адреса и атак с подставными устройствами в LLN. Поддерживающие расширение узлы рассчитывают криптографический идентификатор (Crypto-ID) и применяют его с одним или несколькими зарегистрированными адресами. Crypto-ID указывает владельца Registered Address и может служить для подтверждения владения зарегистрированными адресами. После регистрации адреса с Crypto-ID и подтверждения владения им регистрационные данные может менять лишь владелец, фактически реализуя SAVI. [RFC8928] дополнительно сужает фронт атак для граничных узлов и данная спецификация предлагает использовать это.

Модель доверия может также включать проверку ролей (например, контроль полномочий по роли) для того, чтобы функциональность 6LBR или корня RPL DODAG была доступна лишь уполномоченным устройствам.

Поле Opaque в EARO позволяет листу RUL указать RPLInstanceID для размещения трафика. RUL злоумышленника может включать в пакет опцию RPI, что открывает дверь для атак при резервировании RPL Instance для критического трафика, например, путём резервирования пропускной способности, когда трафик злоумышленника может нарушать работу. Такую атаку можно ослабит обычными механизмами контроля доступа и формовки трафика, где 6LR контролирует входящий трафик от 6LN. Более важно, что 6LR является узлом, внедряющим трафик в домен RPL, поэтому последним словом является выбор экземпляра RPL для трафика, входящего от RUL в соответствии с политикой. В частности, политика может переопределять формальный язык, который заставляет использовать поле Opaque или переписывать опцию RPI, предоставленную RUL, когда администратор сочтёт это нужным.

На момент создания этого документа в RPL не было модели проверки владения маршрутом, позволяющей проверить источник адреса, внедрённого в DAO. Эта спецификация делает первый шаг в данном направлении, позволяя корню запрашивать RUL через обслуживающий лист маршрутизатор 6LR.

В параграфе 6.1 указано, что при неизвестном размере поля ROVR опция RPL Target должна передаваться в том виде, как она получена в режиме RPL Storing. Это позволяет использовать сообщения DAO в качестве скрытого канала. Сообщения DAO достаточно редки и чрезмерное использованием канала может быть обнаружено. Реализации следует уведомлять систему управления сетью при получении опции RPL Target с неизвестным размером поля ROVR, чтобы администратор знал о таких ситуациях.

[RFC9009] позволяет любому фиктивному узлу общего предка аннулировать маршрут от имени целевого узла. В таком случае RPL Status в DCO имеет сброшенный флаг A, а NA(EARO) возвращается узлу 6LN со сброшенным флагом R. Это заставляет 6LN попытаться использовать другой маршрутизатор 6LR. При наличии 6LR, не пользующегося обманным общим предком, 6LN в конечном итоге добъётся доступности через сеть RPL вопреки обманному узлу.

12. Взаимодействие с IANA

12.1. Реестр флагов опции Address Registration

Раздел 9.1 в [RFC8505] создал реестр 8-битовых значений поля Address Registration Option Flags. Агентство IANA переименовало первых столбец этого реестра (ARO Status) в Bit Number.

12.2. Изменение числа значений ARO Status

Раздел 12 в [RFC6775] создал реестр Address Registration Option Status Values со значениями от 0 до 255. Данная спецификация сужает диапазон до 0-63 (параграф 6.3) и агентство IANA изменило реестр, задав верхнюю границу 63 и добавило ссылку на данный документ. Процедура регистрации не изменилась.

12.3. Новый флаг опции RPL DODAG Configuration

Агентство IANA выделило указанный в таблице 2 флаг в реестре DODAG Configuration Option Flags for MOP 0..6 [RFC9008].

Таблица 2. Флаг опции DODAG Configuration.

Номер бита

Описание

Документ

1

Root Proxies EDAR/EDAC (P)

RFC 9010

В реестр RPL Mode of Operation добавлена ссылка на данный документ для MOP 7.

12.4. Реестр флагов опции RPL Target

Этот документ обновляет реестр RPL Target Option Flags, заданный параграфом 20.15 в [RFC6550]. Сейчас этот реестр включает лишь 4 бита (параграф 6.1) и содержит ссылку на данный документ. Процедура регистрации не изменилась.

В параграфе 6.1 определены две новых записи (таблица 3).

Таблица 3. Флаги опции RPL Target.

Номер бита

Описание

Документ

0

Advertiser address in Full (F)

RFC 9010

1

Proxy EDAR Requested (X)

RFC 9010

12.5. Субреестр значений RPL Non-Rejection Status

Агентство IANA создало в реестре Routing Protocol for Low Power and Lossy Networks (RPL) новый субреестр значений RPL Non-Rejection Status для использования в сообщениях RPL DAO-ACK, DCO и DCO-ACK со сброшенным флагом A и установленным флагом U.

  • Положительные значения являются 6-битовыми целыми числами без знака (0..63).

  • Регистрация выполняется по процедуре IETF Review [RFC8126].

  • Начальное значение указано в таблице 4.

Таблица 4. Значения восприятия для RPL Status.

Значение

Описание

Документ

0

Успех, безусловное восприятие

RFC 6550 и RFC 9010

1 — 63

Не выделены

12.6. Субреестр значений RPL Rejection Status

Агентство IANA создало в реестре Routing Protocol for Low Power and Lossy Networks (RPL) новый субреестр значений RPL Rejection Status для использования в сообщениях RPL DAO-ACK, DCO и DCO-ACK со сброшенным флагом A и установленным флагом U.

  • Положительные значения являются 6-битовыми целыми числами без знака (0..63).

  • Регистрация выполняется по процедуре IETF Review [RFC8126].

  • Начальные значения указаны в таблице 5.

Таблица 5. Значения отказов для RPL Status.

Значение

Описание

Документ

0

Безусловный отказ

RFC 9010

1

Нет маршрутной записи

RFC 9009

2 — 63

Не выделены

13. Литература

13.1. Нормативные документы

[RFC2119] Bradner, S., «Key words for use in RFCs to Indicate Requirement Levels», BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>.

[RFC3810] Vida, R., Ed. and L. Costa, Ed., «Multicast Listener Discovery Version 2 (MLDv2) for IPv6», RFC 3810, DOI 10.17487/RFC3810, June 2004, <https://www.rfc-editor.org/info/rfc3810>.

[RFC4861] Narten, T., Nordmark, E., Simpson, W., and H. Soliman, «Neighbor Discovery for IP version 6 (IPv6)», RFC 4861, DOI 10.17487/RFC4861, September 2007, <https://www.rfc-editor.org/info/rfc4861>.

[RFC6550] Winter, T., Ed., Thubert, P., Ed., Brandt, A., Hui, J., Kelsey, R., Levis, P., Pister, K., Struik, R., Vasseur, JP., and R. Alexander, «RPL: IPv6 Routing Protocol for Low-Power and Lossy Networks», RFC 6550, DOI 10.17487/RFC6550, March 2012, <https://www.rfc-editor.org/info/rfc6550>.

[RFC6775] Shelby, Z., Ed., Chakrabarti, S., Nordmark, E., and C. Bormann, «Neighbor Discovery Optimization for IPv6 over Low-Power Wireless Personal Area Networks (6LoWPANs)», RFC 6775, DOI 10.17487/RFC6775, November 2012, <https://www.rfc-editor.org/info/rfc6775>.

[RFC7102] Vasseur, JP., «Terms Used in Routing for Low-Power and Lossy Networks», RFC 7102, DOI 10.17487/RFC7102, January 2014, <https://www.rfc-editor.org/info/rfc7102>.

[RFC7400] Bormann, C., «6LoWPAN-GHC: Generic Header Compression for IPv6 over Low-Power Wireless Personal Area Networks (6LoWPANs)», RFC 7400, DOI 10.17487/RFC7400, November 2014, <https://www.rfc-editor.org/info/rfc7400>.

[RFC8126] Cotton, M., Leiba, B., and T. Narten, «Guidelines for Writing an IANA Considerations Section in RFCs», BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017, <https://www.rfc-editor.org/info/rfc8126>.

[RFC8174] Leiba, B., «Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words», BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[RFC8200] Deering, S. and R. Hinden, «Internet Protocol, Version 6 (IPv6) Specification», STD 86, RFC 8200, DOI 10.17487/RFC8200, July 2017, <https://www.rfc-editor.org/info/rfc8200>.

[RFC8504] Chown, T., Loughney, J., and T. Winters, «IPv6 Node Requirements», BCP 220, RFC 8504, DOI 10.17487/RFC8504, January 2019, <https://www.rfc-editor.org/info/rfc8504>.

[RFC8505] Thubert, P., Ed., Nordmark, E., Chakrabarti, S., and C. Perkins, «Registration Extensions for IPv6 over Low-Power Wireless Personal Area Network (6LoWPAN) Neighbor Discovery», RFC 8505, DOI 10.17487/RFC8505, November 2018, <https://www.rfc-editor.org/info/rfc8505>.

[RFC8928] Thubert, P., Ed., Sarikaya, B., Sethi, M., and R. Struik, «Address-Protected Neighbor Discovery for Low-Power and Lossy Networks», RFC 8928, DOI 10.17487/RFC8928, November 2020, <https://www.rfc-editor.org/info/rfc8928>.

[RFC9008] Robles, M.I., Richardson, M., and P. Thubert, «Using RPI Option Type, Routing Header for Source Routes, and IPv6-in-IPv6 Encapsulation in the RPL Data Plane», RFC 9008, DOI 10.17487/RFC9008, April 2021, <https://www.rfc-editor.org/info/rfc9008>.

[RFC9009] Jadhav, R.A., Ed., Thubert, P., Sahoo, R.N., and Z. Cao, «Efficient Route Invalidation», RFC 9009, DOI 10.17487/RFC9009, April 2021, <https://www.rfc-editor.org/info/rfc9009>.

13.2. Дополнительная литература

[RFC4862] Thomson, S., Narten, T., and T. Jinmei, «IPv6 Stateless Address Autoconfiguration», RFC 4862, DOI 10.17487/RFC4862, September 2007, <https://www.rfc-editor.org/info/rfc4862>.

[RFC4919] Kushalnagar, N., Montenegro, G., and C. Schumacher, «IPv6 over Low-Power Wireless Personal Area Networks (6LoWPANs): Overview, Assumptions, Problem Statement, and Goals», RFC 4919, DOI 10.17487/RFC4919, August 2007, <https://www.rfc-editor.org/info/rfc4919>.

[RFC6282] Hui, J., Ed. and P. Thubert, «Compression Format for IPv6 Datagrams over IEEE 802.15.4-Based Networks», RFC 6282, DOI 10.17487/RFC6282, September 2011, <https://www.rfc-editor.org/info/rfc6282>.

[RFC6553] Hui, J. and JP. Vasseur, «The Routing Protocol for Low-Power and Lossy Networks (RPL) Option for Carrying RPL Information in Data-Plane Datagrams», RFC 6553, DOI 10.17487/RFC6553, March 2012, <https://www.rfc-editor.org/info/rfc6553>.

[RFC6554] Hui, J., Vasseur, JP., Culler, D., and V. Manral, «An IPv6 Routing Header for Source Routes with the Routing Protocol for Low-Power and Lossy Networks (RPL)», RFC 6554, DOI 10.17487/RFC6554, March 2012, <https://www.rfc-editor.org/info/rfc6554>.

[RFC6606] Kim, E., Kaspar, D., Gomez, C., and C. Bormann, «Problem Statement and Requirements for IPv6 over Low-Power Wireless Personal Area Network (6LoWPAN) Routing», RFC 6606, DOI 10.17487/RFC6606, May 2012, <https://www.rfc-editor.org/info/rfc6606>.

[RFC6687] Tripathi, J., Ed., de Oliveira, J., Ed., and JP. Vasseur, Ed., «Performance Evaluation of the Routing Protocol for Low-Power and Lossy Networks (RPL)», RFC 6687, DOI 10.17487/RFC6687, October 2012, <https://www.rfc-editor.org/info/rfc6687>.

[RFC7039] Wu, J., Bi, J., Bagnulo, M., Baker, F., and C. Vogt, Ed., «Source Address Validation Improvement (SAVI) Framework», RFC 7039, DOI 10.17487/RFC7039, October 2013, <https://www.rfc-editor.org/info/rfc7039>.

[RFC7228] Bormann, C., Ersue, M., and A. Keranen, «Terminology for Constrained-Node Networks», RFC 7228, DOI 10.17487/RFC7228, May 2014, <https://www.rfc-editor.org/info/rfc7228>.

[RFC7416] Tsao, T., Alexander, R., Dohler, M., Daza, V., Lozano, A., and M. Richardson, Ed., «A Security Threat Analysis for the Routing Protocol for Low-Power and Lossy Networks (RPLs)», RFC 7416, DOI 10.17487/RFC7416, January 2015, <https://www.rfc-editor.org/info/rfc7416>.

[RFC8025] Thubert, P., Ed. and R. Cragie, «IPv6 over Low-Power Wireless Personal Area Network (6LoWPAN) Paging Dispatch», RFC 8025, DOI 10.17487/RFC8025, November 2016, <https://www.rfc-editor.org/info/rfc8025>.

[RFC8138] Thubert, P., Ed., Bormann, C., Toutain, L., and R. Cragie, «IPv6 over Low-Power Wireless Personal Area Network (6LoWPAN) Routing Header», RFC 8138, DOI 10.17487/RFC8138, April 2017, <https://www.rfc-editor.org/info/rfc8138>.

[RFC8415] Mrugalski, T., Siodelski, M., Volz, B., Yourtchenko, A., Richardson, M., Jiang, S., Lemon, T., and T. Winters, «Dynamic Host Configuration Protocol for IPv6 (DHCPv6)», RFC 8415, DOI 10.17487/RFC8415, November 2018, <https://www.rfc-editor.org/info/rfc8415>.

[RFC8929] Thubert, P., Ed., Perkins, C.E., and E. Levy-Abegnoli, «IPv6 Backbone Router», RFC 8929, DOI 10.17487/RFC8929, November 2020, <https://www.rfc-editor.org/info/rfc8929>.

Приложение A. Пример сжатия

На рисунке 13 показан режим Storing для случая приема пакета из Internet, его инкапсуляции корнем для внедрения в RPI и доставки маршрутизатору 6LR, являющемуся родителем конечного получателя, для которого неизвестно о поддержке [RFC8138].

+-+ ... -+-+ ... +-+- ... -+-+ ... -+-+-+ ... +-+-+ ... -+ ... +-...
|11110001|SRH-6LoRH| RPI-  |IP-in-IP| NH=1      |11110CPP| UDP | UDP
|Page 1  |Type1 S=0| 6LoRH | 6LoRH  |LOWPAN_IPHC| UDP    | hdr |Payld
+-+ ... -+-+ ... +-+- ... -+-+ ... -+-+-+ ... +-+-+ ... -+ ... +-...
         <-4 байта->                <-        RFC 6282        ->
                                    <-     Нет артефактов RPL ...

Рисунок 13. Инкапсуляция для родительского 6LR в режиме Storing.


Отличие от примера на рисунке 19 в [RFC8138] состоит в добавлении SRH-6LoRH перед RPI-6LoRH для транспортировки сжатого адреса 6LR в качестве адреса получателя во внешнем заголовке IPv6. На рисунке 19 в [RFC8138] IP-адрес получателя во внешнем заголовке опущен и неявно является адресом получателя из внутреннего заголовка. Тип 1 выбран произвольно, а нулевой размер обозначает единственный адрес в SRH.

На рисунке 13 источником инкапсуляции IPv6-in-IPv6 является корень, поэтому он исключен из IPv6-in-IPv6 6LoRH. Адресатом является родительский маршрутизатор 6LR для получателя инкапсулированного пакета, поэтому игнорировать его нельзя. Если DODAG работает в режиме Storing, это будет единственной записью в SRH-6LoRH, а поле SRH-6LoRH Size содержит 0. SRH-6LoRH является первым 6LoRH в цепочке. В этом примере адрес 6LR можно сжать до 2 байтов, поэтому применяется тип 1. В результате общий размер SRH-6LoRH составляет 4 байта.

В режиме In Non-Storing инкапсуляция из корня будет аналогична представленной на рисунке 13 возможно с большим числом интервалов пересылки в SRH-6LoRH множеством SRH-6LoRH, если для разных адресов в заголовке маршрутизации применяются разные форматы сжатия. Отметим, что на последнем этапе пересылки к родительскому 6LR заголовок RH3 потребляется и удаляется из сжатой формы, поэтому форматы пакетов в режимах Non-Storing и Storing не различаются.

За SRH-6LoRH следует RPI-6LoRH, затем IPv6-in-IPv6 6LoRH. При удалении IPv6-in-IPv6 6LoRH удаляются также все предшествующие заголовки 6LoRH. Paging Dispatch [RFC8025] также может удаляться, сли предыдущая страница Page не сменилась на страницу, отличную от 0 и 1, поскольку LOWPAN_IPHC кодируется одинаково на принятой по умолчанию Page 0 и Page 1. Результирующий пакет для адресата является инкапсулированным с компрессией [RFC6282].

Благодарности

Авторы благодарны Ines Robles, Georgios Papadopoulos и особенно Rahul Jadhav и Alvaro Retana за их рецензии и вклад в документ. Большое спасибо также Éric Vyncke, Erik Kline, Murray Kucherawy, Peter van der Stok, Carl Wallace, Barry Leiba, Julien Meuric и особенно Benjamin Kaduk и Elwyn Davies за их рецензии и полезные комментации на сессиях IETF Last Call и IESG review.

Адреса авторов

Pascal Thubert (редактор)

Cisco Systems, Inc.

Building D

45 Allee des Ormes — BP1200

06254 MOUGINS — Sophia Antipolis

France

Phone: +33 497 23 26 34

Email: pthubert@cisco.com

Michael C. Richardson

Sandelman Software Works

Email: mcr+ietf@sandelman.ca

URI: https://www.sandelman.ca/


Перевод на русский язык

Николай Малых

nmalykh@protokols.ru

1Internet Engineering Task Force.

2Internet Engineering Steering Group.

3Neighbor Solicitation — запрос соседства.

4Neighbor Advertisement — анонсирование соседа.

5Address-Protected Neighbor Discovery — обнаружение соседей с защитой адреса.

Рубрика: RFC | Оставить комментарий