SSU2

Proposal 159
Закрыто
Author eyedeekay, orignal, zlatinb, zzz
Created 2021-09-12
Last Updated 2025-03-05
Target Version 0.9.56

Статус

План развертывания:

FeatureTesting (not default)Enabled by default
Local test code2022-02
Joint test code2022-03
Joint test in-net0.9.54 2022-05
Freeze basic protocol0.9.54 2022-05
Basic Session0.9.55 2022-080.9.56 2022-11
Address Validation (Retry)0.9.55 2022-080.9.56 2022-11
Fragmented RI in handshake0.9.55 2022-080.9.56 2022-11
New Token0.9.55 2022-080.9.57 2022-11
Freeze extended protocol0.9.55 2022-08
Relay0.9.55 2022-080.9.56 2022-11
Peer Test0.9.55 2022-080.9.56 2022-11
Enable for random 2%0.9.55 2022-08
Path Validation0.9.55+ dev0.9.56 2022-11
Connection Migration0.9.55+ dev0.9.56 2022-11
Immediate ACK flag0.9.55+ dev0.9.56 2022-11
Key Rotation0.9.57 2023-020.9.58 2023-05
Disable SSU 1 (i2pd)0.9.56 2022-11
Disable SSU 1 (Java I2P)0.9.58 2023-050.9.61 2023-12
Базовая сессия включает фазу рукопожатия и фазу данных. Расширенный протокол включает relay и peer test.

Обзор

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

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

Как и другие транспорты I2P, SSU2 предназначен для передачи I2NP сообщений между точками (роутер-к-роутеру). Это не универсальный канал передачи данных. Как и SSU, он также предоставляет два дополнительных сервиса: Relaying для преодоления NAT и Peer Testing для определения доступности входящих соединений. Он также предоставляет третий сервис, которого нет в SSU, для миграции соединений когда узел меняет IP или порт.

Мотивация

SSU является единственным оставшимся протокольным слоем, который требует ElGamal, что очень медленно. Управление потоком для SSU сложное и работает плохо. Части SSU уязвимы для атак подмены адресов. Рукопожатие не использует Noise.

Цели проектирования

  • Снизить использование CPU, исключив ElGamal. Использовать X25519 для DH.

  • Поддерживать функции Peer Test и Relay, а также повысить их безопасность.

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

  • Уменьшить задержку установки соединения. Медианное время установки соединения в настоящее время составляет около 135 мс для NTCP2 и 187 мс для SSU, хотя NTCP2 требует дополнительный цикл обмена; замена ElGamal в SSU2 должна это сократить, но другие изменения также могут помочь.

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

  • Предотвращать атаки усиления трафика и неправильной маршрутизации с поддельных адресов-источников через “валидацию адресов”.

  • Упростить идентификацию пакетов, чтобы уменьшить зависимость от резервных механизмов и эвристик, которые делают код излишне сложным.

  • Формализовать и улучшить миграцию соединений при изменении IP-адреса или порта пира. Не выполнять миграцию соединений до завершения валидации адреса во избежание атак. Некоторые реализации SSU 1 используют ресурсозатратные эвристики для обработки изменений портов из-за NAT rebinding. Ни одна из известных реализаций SSU 1 не может обрабатывать изменения IP-адресов вообще.

  • Поддержка SSU 1 и 2 на одном порту, автоопределение, и публикация как единый “transport” (т.е. RouterAddress) в NetDB.

  • Публиковать поддержку только версии 1, только версии 2, или 1+2 в NetDB в отдельном поле, и по умолчанию использовать только версию 1 (не привязывать поддержку версий к конкретной версии роутера)

  • Убедиться, что все реализации (Java/i2pd/Go) могут добавить поддержку версии 2 (или не добавлять) по своему собственному графику

  • Добавлять случайное заполнение ко всем сообщениям, включая сообщения рукопожатия и данных. Все заполнение должно покрываться MAC, в отличие от заполнения в конце пакета в SSU 1. Предоставить механизм опций для обеих сторон для запроса минимального и максимального заполнения и/или распределения заполнения. Особенности распределения заполнения зависят от реализации и могут быть или не быть указаны в самом протоколе.

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

  • Исправить потерю битов в DH из-за формата Java Ticket1112, и ускорить DH переключением на X25519.

  • Переключиться на настоящую функцию вывода ключей (KDF) вместо использования результата DH как есть

  • Добавить “устойчивость к зондированию” (как это называется в Tor); это включает устойчивость к replay-атакам.

  • Поддерживать двустороннюю аутентификацию обмена ключами (2W-AKE). 1W-AKE недостаточно для нашего приложения.

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

  • Добавить options/version в handshake для будущей расширяемости.

  • Не должен существенно увеличивать нагрузку на CPU, требуемую для установки соединения; по возможности, должен значительно её снижать.

  • Убрать требование дополнения до кратного 16 байтам наложенное AES шифрованием в SSU 1.

  • Использовать стандартный ChaCha/Poly1305 для шифрования и MAC, заменив шифрование AES и нестандартный HMAC-MD5-128 MAC, используемый в SSU 1.

  • Используйте отдельные ключи шифрования для отправки и получения вместо общих ключей для обоих направлений, используемых в SSU 1.

  • Использовать 3-сообщенное рукопожатие в одну поездку, как в NTCP2. Устранить задержку ожидания сообщений данных, которая делает SSU фактически рукопожатием в две поездки.

  • Кардинально улучшить эффективность ACK и NACK, которая ужасна в SSU 1. Снизить требуемую пропускную способность для ACK и NACK, и увеличить размер пакета, доступный для данных. Эффективно кодировать NACK для пакетной передачи пропущенных сообщений, что часто происходит через WiFi.

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

  • Минимизируйте служебные данные протокола до padding, особенно для ACK. Хотя padding будет добавлен, служебные данные до padding всё равно остаются служебными данными. Узлы с низкой пропускной способностью должны иметь возможность использовать SSU2.

  • Поддерживать временные метки для обнаружения повторов и отклонений.

  • Избегать любых проблем 2038 года в временных метках, должно работать как минимум до 2106 года.

  • Увеличить минимальный MTU с 620 до 1280 для повышения эффективности, простоты реализации и увеличения максимального размера I2NP сообщений. Фрагментация и реассемблирование довольно затратны. Предоставляя место для tunnel сообщений размером 1028 байт, большинство I2NP сообщений не потребует фрагментации.

  • Увеличить максимальный MTU с 1488 (1484 для IPv6) до 1500 для повышения эффективности. Убрать требование, чтобы MTU был кратен 16.

  • Увеличить максимальный размер I2NP сообщения с приблизительно 32K в SSU 1 до приблизительно 64 КБ как в NTCP2.

  • Удалить подпись полей IP и порта из handshake, чтобы router’ы, которые не знают свой внешний IP и порт, могли подключаться.

  • Сохранить механизм обнаружения IP/порта из SSU 1 в рукопожатии, чтобы роутеры могли узнать свой внешний IP и порт.

  • Включить представителей разработчиков router на Java, C++ и Go в процесс проектирования.

Non-Goals

  • Защита от DPI, устойчивая к любым попыткам обнаружения… это будут подключаемые транспорты, Предложение 109.

  • TLS-основанный (или похожий на HTTPS) транспорт… это будет Proposal 104.

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

  • Отрицаемость участия в сессии (там есть подписи).

Не-цели, которые могут быть частично пересмотрены или обсуждены:

  • Степень защиты от глубокой проверки пакетов (Deep Packet Inspection, DPI)

  • Постквантовая (PQ) безопасность

  • Отрицаемость

Security Goals

Мы рассматриваем три стороны:

  • Алиса, которая хочет установить новую сессию.
  • Боб, с которым Алиса хочет установить сессию.
  • Мэллори, “человек посередине” между Алисой и Бобом.

Не более двух участников могут участвовать в активных атаках.

Алиса и Боб оба обладают статической парой ключей, которая содержится в их RouterIdentity.

Предлагаемый протокол пытается позволить Алисе и Бобу договориться о совместном секретном ключе (K) при следующих требованиях:

  1. Безопасность закрытого ключа: ни Боб, ни Мэллори не узнают ничего о статическом закрытом ключе Алисы. Симметрично, Алиса не узнает ничего о статическом закрытом ключе Боба.

  2. Ключ сессии K известен только Алисе и Бобу.

  3. Совершенная прямая секретность: согласованный сессионный ключ остается секретным в будущем, даже когда статические приватные ключи Алисы и/или Боба раскрываются после того, как ключ был согласован.

  4. Двусторонняя аутентификация: Алиса уверена, что она установила сессию с Бобом, и наоборот.

  5. Защита от онлайн DPI: Обеспечить, чтобы не было тривиально обнаружить, что Алиса и Боб участвуют в протоколе, используя только простые методы глубокой проверки пакетов (DPI). См. ниже.

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

Данное предложение пытается обеспечить все пять требований на основе протокола Station-To-Station (STS). Обратите внимание, что этот протокол также является основой для протокола SSU.

Additional DPI Discussion

Мы предполагаем два компонента DPI:

Online DPI

Онлайн DPI инспектирует все потоки в режиме реального времени. Соединения могут быть заблокированы или иным образом нарушены. Данные соединений или метаданные могут быть идентифицированы и сохранены для офлайн анализа. Онлайн DPI не имеет доступа к сетевой базе данных I2P. Онлайн DPI обладает лишь ограниченными вычислительными возможностями в реальном времени, включая вычисление длины, инспекцию полей и простые вычисления, такие как XOR. Онлайн DPI действительно обладает возможностями быстрых криптографических функций в реальном времени, таких как ChaCha20, AEAD и хеширование, но их применение к большинству или всем потокам было бы слишком дорогостоящим. Любое применение этих криптографических операций распространялось бы только на потоки по комбинациям IP/Port, предварительно идентифицированным офлайн анализом. Онлайн DPI не обладает возможностями высокозатратных криптографических функций, таких как DH или elligator2. Онлайн DPI не предназначен специально для обнаружения I2P, хотя может иметь ограниченные правила классификации для этой цели.

Цель состоит в том, чтобы предотвратить идентификацию протокола с помощью онлайн DPI.

Понятие онлайн или “прямого” DPI здесь включает в себя следующие возможности противника:

  1. Возможность проверять все данные, отправляемые или получаемые целью.

  2. Способность выполнять операции над наблюдаемыми данными, такие как применение блочных шифров или хеш-функций.

  3. Возможность сохранения и сравнения с ранее отправленными сообщениями.

  4. Возможность модифицировать, задерживать или фрагментировать пакеты.

Однако предполагается, что онлайн DPI имеет следующие ограничения:

  1. Невозможность сопоставления IP-адресов с хешами router. Хотя это тривиально при наличии доступа к базе данных сети в реальном времени, это потребовало бы системы DPI, специально разработанной для таргетинга I2P.

  2. Невозможность использования информации о времени для обнаружения протокола.

  3. Вообще говоря, онлайн-набор инструментов DPI не содержит каких-либо встроенных инструментов, которые специально разработаны для обнаружения I2P. Это включает создание “honeypot”, которые, например, включали бы неслучайное заполнение в своих сообщениях. Обратите внимание, что это не исключает системы машинного обучения или высококонфигурируемые инструменты DPI, пока они соответствуют другим требованиям.

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

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

Offline DPI

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

Офлайновая DPI не имеет возможности блокировать существующие соединения. Офлайновая DPI имеет возможность отправлять в режиме близком к реальному времени (в течение минут после настройки) на хост/порт сторон путем внедрения пакетов. Офлайновая DPI имеет возможность в режиме близком к реальному времени (в течение минут после настройки) воспроизводить предыдущие сообщения (модифицированные или нет) для “зондирования” или других целей.

Это не является целью предотвратить идентификацию протокола с помощью автономного DPI. Все декодирование обфусцированных данных в первых двух сообщениях, которое реализовано I2P router’ами, также может быть реализовано автономным DPI.

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

Address Validation

Далее скопировано из QUIC RFC 9000. Для каждого раздела проведите анализ и редактирование.

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

Основная защита от атак усиления заключается в проверке того, что узел способен получать пакеты по транспортному адресу, который он заявляет. Поэтому после получения пакетов с адреса, который еще не подтвержден, конечная точка ДОЛЖНА ограничить объем данных, отправляемых на неподтвержденный адрес, тремя размерами объема данных, полученных с этого адреса. Это ограничение на размер ответов известно как лимит защиты от усиления.

Валидация адресов выполняется как во время установления соединения (см. раздел 8.1), так и во время миграции соединения (см. раздел 8.2).

Address Validation during Connection Establishment

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

Кроме того, конечная точка МОЖЕТ считать адрес пира проверенным, если пир использует connection ID, выбранный конечной точкой, и connection ID содержит не менее 64 битов энтропии.

Для клиента значение поля Destination Connection ID в его первом Initial пакете позволяет ему проверить адрес сервера как часть успешной обработки любого пакета. Initial пакеты от сервера защищены ключами, которые получены из этого значения (см. Section 5.2 в QUIC-TLS). Альтернативно, это значение возвращается сервером в пакетах Version Negotiation (Section 6) или включается в Integrity Tag в пакетах Retry (Section 5.8 в QUIC-TLS).

До валидации адреса клиента серверы НЕ ДОЛЖНЫ отправлять более чем в три раза больше байт, чем количество байт, которое они получили. Это ограничивает масштаб любой атаки усиления, которая может быть осуществлена с использованием поддельных адресов источника. В целях предотвращения усиления до валидации адреса серверы ДОЛЖНЫ учитывать все байты полезной нагрузки, полученные в датаграммах, которые однозначно относятся к одному соединению. Это включает датаграммы, содержащие пакеты, которые успешно обработаны, и датаграммы, содержащие пакеты, которые все отброшены.

Клиенты ДОЛЖНЫ обеспечить, чтобы UDP дейтаграммы, содержащие Initial пакеты, имели UDP полезную нагрузку не менее 1200 байт, добавляя PADDING фреймы по мере необходимости. Клиент, который отправляет дополненные дейтаграммы, позволяет серверу отправлять больше данных до завершения проверки адреса.

Потеря пакета Initial или Handshake от сервера может вызвать взаимоблокировку, если клиент не отправляет дополнительные пакеты Initial или Handshake. Взаимоблокировка может возникнуть, когда сервер достигает своего лимита защиты от усиления атак, а клиент получил подтверждения для всех отправленных им данных. В этом случае, когда у клиента нет причин отправлять дополнительные пакеты, сервер не сможет отправить больше данных, поскольку он не проверил адрес клиента. Для предотвращения этой взаимоблокировки клиенты ДОЛЖНЫ отправить пакет по истечении Probe Timeout (PTO); см. раздел 6.2 QUIC-RECOVERY. В частности, клиент ДОЛЖЕН отправить пакет Initial в UDP датаграмме, содержащей не менее 1200 байт, если у него нет ключей Handshake, и в противном случае отправить пакет Handshake.

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

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

Token Construction

Токен, отправленный в кадре NEW_TOKEN или пакете Retry, ДОЛЖЕН быть сконструирован таким образом, чтобы сервер мог определить, как он был предоставлен клиенту. Эти токены передаются в одном и том же поле, но требуют разной обработки со стороны серверов.

Address Validation Using Retry Packets

После получения пакета Initial от клиента, сервер может запросить валидацию адреса, отправив пакет Retry (Раздел 17.2.5), содержащий токен. Этот токен ДОЛЖЕН повторяться клиентом во всех пакетах Initial, которые он отправляет для данного соединения после получения пакета Retry.

В ответ на обработку Initial пакета, содержащего токен, который был предоставлен в Retry пакете, сервер не может отправить другой Retry пакет; он может только отклонить соединение или разрешить его продолжение.

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

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

Если сервер получает клиентский Initial, который содержит недействительный Retry токен, но в остальном является корректным, он знает, что клиент не примет другой Retry токен. Сервер может отбросить такой пакет и позволить клиенту достичь таймаута для обнаружения сбоя рукопожатия, но это может наложить значительную задержку на клиента. Вместо этого сервер ДОЛЖЕН немедленно закрыть (Раздел 10.2) соединение с ошибкой INVALID_TOKEN. Обратите внимание, что сервер не установил никакого состояния для соединения на этом этапе и поэтому не входит в период закрытия.

Поток, показывающий использование пакета Retry, представлен на рисунке 9.

Client                                                  Server

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, "..."]

                Figure 9: Example Handshake with Retry

Address Validation for Future Connections

Сервер МОЖЕТ предоставить клиентам токен валидации адреса во время одного соединения, который можно использовать при последующем соединении. Валидация адреса особенно важна при 0-RTT, поскольку сервер потенциально отправляет значительный объем данных клиенту в ответ на 0-RTT данные.

Сервер использует фрейм NEW_TOKEN (Раздел 19.7) для предоставления клиенту токена валидации адреса, который может быть использован для валидации будущих соединений. В будущем соединении клиент включает этот токен в пакеты Initial для обеспечения валидации адреса. Клиент ДОЛЖЕН включать токен во все отправляемые им пакеты 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), и последние могут быть проверены более строго. Если валидация успешна, сервер СЛЕДУЕТ затем разрешить продолжение handshake.

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

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

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

Address Validation Token Integrity

Токен валидации адреса ДОЛЖЕН быть сложным для угадывания. Включение случайного значения с энтропией не менее 128 бит в токен было бы достаточным, но это зависит от того, что сервер запоминает значение, которое он отправляет клиентам.

Схема на основе токенов позволяет серверу передавать клиенту любое состояние, связанное с проверкой. Для работы этой схемы токен ДОЛЖЕН быть защищен от изменения или фальсификации клиентами средствами обеспечения целостности. Без защиты целостности злонамеренные клиенты могли бы генерировать или угадывать значения токенов, которые были бы приняты сервером. Только сервер требует доступа к ключу защиты целостности для токенов.

Нет необходимости в едином четко определенном формате для токена, поскольку сервер, который генерирует токен, также его потребляет. Токены, отправляемые в пакетах Retry, ДОЛЖНЫ включать информацию, которая позволяет серверу проверить, что IP-адрес источника и порт в клиентских пакетах остаются постоянными.

Токены, отправляемые в кадрах NEW_TOKEN, ДОЛЖНЫ включать информацию, позволяющую серверу проверить, что IP-адрес клиента не изменился с момента выдачи токена. Серверы могут использовать токены из кадров NEW_TOKEN при принятии решения не отправлять пакет Retry, даже если адрес клиента изменился. Если IP-адрес клиента изменился, сервер ДОЛЖЕН соблюдать ограничение по защите от усиления; см. раздел 8. Обратите внимание, что при наличии NAT это требование может быть недостаточным для защиты других хостов, использующих общий NAT, от атак усиления.

Злоумышленники могут повторно использовать токены для применения серверов в качестве усилителей в DDoS-атаках. Для защиты от таких атак серверы ДОЛЖНЫ обеспечивать предотвращение или ограничение повторного использования токенов. Серверы ДОЛЖНЫ обеспечивать, чтобы токены, отправленные в пакетах Retry, принимались только в течение короткого времени, поскольку они немедленно возвращаются клиентами. Токены, предоставляемые во фреймах NEW_TOKEN (Раздел 19.7), должны быть действительны дольше, но НЕ ДОЛЖНЫ приниматься несколько раз. Серверам рекомендуется разрешать использование токенов только один раз, если это возможно; токены МОГУТ включать дополнительную информацию о клиентах для дальнейшего сужения применимости или повторного использования.

Онлайн DPI

Валидация пути используется обеими сторонами во время миграции соединения (см. Раздел 9) для проверки достижимости после изменения адреса. При валидации пути конечные точки тестируют достижимость между конкретным локальным адресом и конкретным адресом узла, где адрес представляет собой кортеж из IP-адреса и порта.

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

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

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

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

Конечная точка МОЖЕТ включать другие фреймы вместе с фреймами PATH_CHALLENGE и PATH_RESPONSE, используемыми для проверки пути. В частности, конечная точка может включать фреймы PADDING с фреймом PATH_CHALLENGE для обнаружения максимального размера передаваемого блока пути (PMTUD); см. раздел 14.2.1. Конечная точка также может включать свой собственный фрейм PATH_CHALLENGE при отправке фрейма PATH_RESPONSE.

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

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

Автономная DPI

Для инициации валидации пути конечная точка отправляет кадр 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.

Path Validation Responses

При получении фрейма PATH_CHALLENGE конечная точка ДОЛЖНА ответить, отправив данные, содержащиеся во фрейме PATH_CHALLENGE, во фрейме PATH_RESPONSE. Конечная точка НЕ ДОЛЖНА задерживать передачу пакета, содержащего фрейм PATH_RESPONSE, если только это не ограничено управлением перегрузкой.

Фрейм PATH_RESPONSE ДОЛЖЕН быть отправлен по сетевому пути, где был получен фрейм PATH_CHALLENGE. Это обеспечивает, что валидация пути peer’ом успешна только в том случае, если путь функционален в обоих направлениях. Это требование НЕ ДОЛЖНО применяться конечной точкой, которая инициирует валидацию пути, так как это позволило бы атаку на миграцию; см. Раздел 9.3.3.

Конечная точка ДОЛЖНА расширять датаграммы, содержащие кадр PATH_RESPONSE, до минимального допустимого максимального размера датаграммы в 1200 байт. Это подтверждает, что путь способен передавать датаграммы такого размера в обоих направлениях. Однако конечная точка НЕ ДОЛЖНА расширять датаграмму, содержащую PATH_RESPONSE, если полученные данные превышают лимит защиты от усиления. Ожидается, что это произойдет только в том случае, если полученный PATH_CHALLENGE не был отправлен в расширенной датаграмме.

Конечная точка НЕ ДОЛЖНА отправлять более одного кадра PATH_RESPONSE в ответ на один кадр PATH_CHALLENGE; см. Раздел 13.3. Ожидается, что узел будет отправлять дополнительные кадры PATH_CHALLENGE по мере необходимости для вызова дополнительных кадров PATH_RESPONSE.

Проверка адреса при установлении соединения

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

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

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

Конструкция токенов

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

Конечные точки ДОЛЖНЫ прекращать валидацию пути на основе таймера. При установке этого таймера реализациям следует учитывать, что новый путь может иметь более длительное время приёма-передачи, чем исходный. РЕКОМЕНДУЕТСЯ значение, равное трём значениям большего из текущего PTO или PTO для нового пути (используя kInitialRtt, как определено в QUIC-RECOVERY).

Этот таймаут позволяет истечь нескольким PTO перед признанием проверки пути неудачной, так что потеря одного кадра PATH_CHALLENGE или PATH_RESPONSE не приводит к сбою проверки пути.

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

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

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

Connection Migration

Далее скопировано из QUIC RFC 9000. Для каждого раздела просмотрите и отредактируйте.

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

Дизайн QUIC опирается на то, что конечные точки сохраняют стабильный адрес в течение всего процесса установления соединения. Конечная точка НЕ ДОЛЖНА инициировать миграцию соединения до подтверждения установления соединения, как определено в разделе 4.1.2 QUIC-TLS.

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

Не все изменения адреса узла являются намеренными или активными миграциями. Узел может столкнуться с повторной привязкой NAT: изменением адреса из-за промежуточного устройства, обычно NAT, выделяющего новый исходящий порт или даже новый исходящий IP-адрес для потока. Конечная точка ДОЛЖНА выполнить проверку пути (Раздел 8.2), если она обнаруживает любое изменение адреса узла, если только она ранее не проверила этот адрес.

Когда конечная точка не имеет проверенного пути для отправки пакетов, она МОЖЕТ отбросить состояние соединения. Конечная точка, поддерживающая миграцию соединения, МОЖЕТ ожидать доступности нового пути перед отбрасыванием состояния соединения.

Данный документ ограничивает миграцию соединений на новые адреса клиентов, за исключением случаев, описанных в разделе 9.6. Клиенты несут ответственность за инициацию всех миграций. Серверы не отправляют не-пробные пакеты (см. раздел 9.1) на адрес клиента до тех пор, пока не увидят не-пробный пакет с этого адреса. Если клиент получает пакеты с неизвестного адреса сервера, клиент ДОЛЖЕН отбросить эти пакеты.

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

Конечная точка МОЖЕТ проверить доступность узла с нового локального адреса, используя валидацию пути (Раздел 8.2), до миграции соединения на новый локальный адрес. Неудача валидации пути просто означает, что новый путь не пригоден для использования с данным соединением. Неспособность валидировать путь не приводит к завершению соединения, если только не отсутствуют другие валидные альтернативные пути.

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

Валидация адресов для будущих соединений

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

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

Для установления достижимости по новому пути, конечная точка инициирует проверку пути (Раздел 8.2) на новом пути. Конечная точка МОЖЕТ отложить проверку пути до тех пор, пока партнер не отправит следующий не-зондирующий кадр на свой новый адрес.

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

Новый путь может не иметь такой же возможности ECN. Поэтому конечная точка проверяет возможность ECN, как описано в разделе 13.4.

Целостность токена валидации адреса

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

Если получатель разрешает миграцию, он ДОЛЖЕН отправлять последующие пакеты на новый адрес узла и ДОЛЖЕН инициировать валидацию пути (Раздел 8.2) для проверки владения узлом этим адресом, если валидация еще не выполняется. Если у получателя нет неиспользованных идентификаторов соединения от узла, он не сможет отправить что-либо по новому пути до тех пор, пока узел не предоставит такой идентификатор; см. Раздел 9.5.

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

Конечная точка МОЖЕТ отправлять данные на неподтвержденный адрес узла, но ДОЛЖНА защищаться от потенциальных атак, как описано в разделах 9.3.1 и 9.3.2. Конечная точка МОЖЕТ пропустить проверку адреса узла, если этот адрес был замечен недавно. В частности, если конечная точка возвращается к ранее подтвержденному пути после обнаружения какой-либо формы ложной миграции, пропуск проверки адреса и восстановление состояния обнаружения потерь и управления перегрузкой может снизить влияние атаки на производительность.

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

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

После верификации нового адреса клиента, сервер ДОЛЖЕН отправить клиенту новые токены валидации адреса (Раздел 8).

Валидация пути

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

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

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

Инициация валидации пути

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

Чтобы защитить соединение от сбоя из-за такой ложной миграции, конечная точка ДОЛЖНА вернуться к использованию последнего проверенного адреса партнера, когда проверка нового адреса партнера завершается неудачей. Кроме того, получение пакетов с более высокими номерами пакетов с легитимного адреса партнера запустит другую миграцию соединения. Это приведет к тому, что проверка адреса ложной миграции будет прекращена, тем самым ограничивая миграции, инициированные злоумышленником, вводящим один пакет.

Если endpoint не имеет состояния о последнем проверенном адресе узла, он ДОЛЖЕН закрыть соединение молча, отбросив все состояние соединения. Это приводит к тому, что новые пакеты на соединении обрабатываются обобщенно. Например, endpoint МОЖЕТ отправить Stateless Reset в ответ на любые дальнейшие входящие пакеты.

Ответы на валидацию пути

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

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

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

В ответ на очевидную миграцию, конечные точки ДОЛЖНЫ проверить ранее активный путь, используя кадр PATH_CHALLENGE. Это вызывает отправку новых пакетов по этому пути. Если путь больше не является жизнеспособным, попытка проверки истечет по времени и завершится неудачей; если путь жизнеспособен, но больше не желателен, проверка будет успешной, но приведет только к отправке зондирующих пакетов по пути.

Конечная точка, которая получает PATH_CHALLENGE на активном пути, ДОЛЖНА отправить непробный пакет в ответ. Если непробный пакет прибывает раньше любой копии, созданной злоумышленником, это приводит к миграции соединения обратно на исходный путь. Любая последующая миграция на другой путь перезапускает весь этот процесс.

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

Конечная точка также может использовать эвристику для улучшения обнаружения атак такого типа. Например, NAT rebinding маловероятен, если пакеты недавно были получены по старому пути; аналогично, rebinding редко происходит на IPv6 путях. Конечные точки также могут искать дублированные пакеты. И наоборот, изменение connection ID с большей вероятностью указывает на намеренную миграцию, а не на атаку.

Успешная валидация пути

Пропускная способность, доступная на новом пути, может не совпадать со старым путем. Пакеты, отправленные по старому пути, НЕ ДОЛЖНЫ влиять на управление перегрузкой или оценку RTT для нового пути.

При подтверждении права собственности узла на его новый адрес, конечная точка ДОЛЖНА немедленно сбросить контроллер перегрузок и оценщик времени круговой задержки для нового пути к начальным значениям (см. Приложения A.3 и B.3 в QUIC-RECOVERY), если только единственное изменение в адресе узла не касается номера порта. Поскольку изменения только порта обычно являются результатом повторного связывания NAT или другой активности промежуточных устройств, конечная точка МОЖЕТ вместо этого сохранить свое состояние управления перегрузками и оценку времени круговой задержки в таких случаях вместо возврата к начальным значениям. В случаях, когда состояние управления перегрузками, сохраненное со старого пути, используется на новом пути с существенно отличающимися характеристиками, отправитель может передавать слишком агрессивно до тех пор, пока контроллер перегрузок и оценщик RTT не адаптируются. В целом, реализациям рекомендуется проявлять осторожность при использовании предыдущих значений на новом пути.

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

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

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

Неудачная проверка пути

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

В любое время конечные точки МОГУТ изменить Destination Connection ID, который они передают, на значение, которое не использовалось на другом пути.

Конечная точка НЕ ДОЛЖНА повторно использовать идентификатор соединения при отправке с более чем одного локального адреса – например, при инициации миграции соединения, как описано в разделе 9.2, или при зондировании нового сетевого пути, как описано в разделе 9.1.

Аналогично, конечная точка НЕ ДОЛЖНА повторно использовать connection ID при отправке на более чем один адрес назначения. Из-за изменений в сети, находящихся вне контроля её партнёра, конечная точка может получить пакеты с нового адреса источника с тем же значением поля Destination Connection ID, в этом случае она МОЖЕТ продолжить использовать текущий connection ID с новым удалённым адресом, продолжая при этом отправку с того же локального адреса.

Эти требования касательно повторного использования connection ID применяются только к отправке пакетов, поскольку возможны непреднамеренные изменения пути без изменения connection ID. Например, после периода сетевой неактивности NAT rebinding может привести к тому, что пакеты будут отправляться по новому пути, когда клиент возобновит отправку. Конечная точка отвечает на такое событие, как описано в разделе 9.3.

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

Конечная точка НЕ ДОЛЖНА инициировать миграцию с узлом, который запросил идентификатор соединения нулевой длины, поскольку трафик по новому пути может быть тривиально связан с трафиком по старому. Если сервер способен ассоциировать пакеты с идентификатором соединения нулевой длины с правильным соединением, это означает, что сервер использует другую информацию для демультиплексирования пакетов. Например, сервер может предоставлять уникальный адрес каждому клиенту – например, используя альтернативные службы HTTP ALTSVC. Информация, которая может позволить корректную маршрутизацию пакетов через множественные сетевые пути, также позволит связать активность на этих путях сущностями, отличными от узла.

Клиент может захотеть снизить возможность связывания путем переключения на новый connection ID, исходный UDP-порт или IP-адрес (см. RFC8981) при отправке трафика после периода неактивности. Изменение адреса, с которого отправляются пакеты, в то же время может привести к тому, что сервер обнаружит миграцию соединения. Это обеспечивает использование механизмов поддержки миграции даже для клиентов, которые не сталкиваются с NAT rebinding или реальными миграциями. Изменение адреса может привести к сбросу состояния контроля перегрузки узла (см. раздел 9.4), поэтому адреса СЛЕДУЕТ изменять нечасто.

Конечная точка, которая исчерпала доступные идентификаторы соединения, не может исследовать новые пути или инициировать миграцию, а также не может отвечать на зондирование или попытки миграции со стороны своего партнера. Чтобы обеспечить возможность миграции и невозможность корреляции пакетов, отправленных по разным путям, конечные точки ДОЛЖНЫ предоставлять новые идентификаторы соединения до миграции партнеров; см. раздел 5.1.1. Если партнер мог исчерпать доступные идентификаторы соединения, мигрирующая конечная точка могла бы включать фрейм NEW_CONNECTION_ID во все пакеты, отправляемые по новому сетевому пути.

Server’s Preferred Address

QUIC позволяет серверам принимать соединения на одном IP-адресе и пытаться перенести эти соединения на более предпочтительный адрес вскоре после handshake. Это особенно полезно, когда клиенты изначально подключаются к адресу, который используется несколькими серверами совместно, но предпочли бы использовать unicast-адрес для обеспечения стабильности соединения. Данный раздел описывает протокол миграции соединения на предпочтительный адрес сервера.

Миграция соединения на новый адрес сервера в процессе соединения не поддерживается версией QUIC, указанной в данном документе. Если клиент получает пакеты с нового адреса сервера, когда клиент не инициировал миграцию на этот адрес, клиент ДОЛЖЕН отбросить эти пакеты.

Исследование нового пути

Сервер передает предпочтительный адрес, включив параметр транспорта preferred_address в TLS handshake.

Серверы МОГУТ сообщать предпочтительный адрес для каждого семейства адресов (IPv4 и IPv6), чтобы позволить клиентам выбрать наиболее подходящий для их сетевого подключения.

После подтверждения рукопожатия клиент ДОЛЖЕН выбрать один из двух адресов, предоставленных сервером, и инициировать валидацию пути (см. Раздел 8.2). Клиент конструирует пакеты, используя любой ранее не использованный активный connection ID, взятый либо из транспортного параметра preferred_address, либо из фрейма NEW_CONNECTION_ID.

Как только валидация пути завершается успешно, клиент ДОЛЖЕН начать отправлять все будущие пакеты на новый адрес сервера, используя новый connection ID, и прекратить использование старого адреса сервера. Если валидация пути не удается, клиент ДОЛЖЕН продолжать отправлять все будущие пакеты на исходный IP-адрес сервера.

Инициация миграции соединения

Клиент, который мигрирует на предпочтительный адрес, ДОЛЖЕН проверить адрес, который он выбирает, перед миграцией; см. Раздел 21.5.3.

Сервер может получить пакет, адресованный на его предпочитаемый IP-адрес, в любое время после того, как он принимает соединение. Если этот пакет содержит кадр PATH_CHALLENGE, сервер отправляет пакет, содержащий кадр PATH_RESPONSE, согласно разделу 8.2. Сервер ДОЛЖЕН отправлять не-зондирующие пакеты со своего исходного адреса до тех пор, пока он не получит не-зондирующий пакет от клиента на свой предпочитаемый адрес и пока сервер не проверит новый путь.

Сервер ДОЛЖЕН выполнить зондирование по пути к клиенту со своего предпочтительного адреса. Это помогает защититься от ложной миграции, инициированной атакующим.

После того как сервер завершил проверку пути и получил непробный пакет с новым наибольшим номером пакета на своем предпочтительном адресе, сервер начинает отправлять непробные пакеты клиенту исключительно со своего предпочтительного IP-адреса. Сервер ДОЛЖЕН отбрасывать более новые пакеты для данного соединения, которые получены на старом IP-адресе. Сервер МОЖЕТ продолжать обрабатывать задержанные пакеты, которые получены на старом IP-адресе.

Адреса, которые сервер предоставляет в транспортном параметре preferred_address, действительны только для соединения, в котором они предоставляются. Клиент НЕ ДОЛЖЕН использовать их для других соединений, включая соединения, которые возобновляются из текущего соединения.

Ответ на миграцию соединения

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

Если проверка пути предпочтительного адреса сервера прошла успешно, клиент ДОЛЖЕН прекратить проверку исходного адреса и перейти к использованию предпочтительного адреса сервера. Если проверка пути предпочтительного адреса сервера не удалась, но проверка исходного адреса сервера прошла успешно, клиент МОЖЕТ перейти на свой новый адрес и продолжить отправку на исходный адрес сервера.

Если пакеты, полученные по предпочтительному адресу сервера, имеют исходный адрес, отличающийся от наблюдаемого со стороны клиента во время handshake, сервер ДОЛЖЕН защищаться от потенциальных атак, как описано в разделах 9.3.1 и 9.3.2. Помимо преднамеренной одновременной миграции, это также может произойти из-за того, что сеть доступа клиента использовала другую привязку NAT для предпочтительного адреса сервера.

Серверы ДОЛЖНЫ инициировать валидацию пути к новому адресу клиента при получении пробного пакета с другого адреса; см. Раздел 8.

Клиент, который переходит на новый адрес, ДОЛЖЕН использовать предпочтительный адрес из того же семейства адресов для сервера.

ID соединения, предоставленный в транспортном параметре preferred_address, не является специфичным для предоставленных адресов. Этот ID соединения предоставляется для обеспечения того, чтобы у клиента был доступный ID соединения для миграции, но клиент МОЖЕТ использовать этот ID соединения на любом пути.

Подмена адресов узлов

QUIC рекомендует, чтобы конечные точки, которые отправляют данные с использованием IPv6, ДОЛЖНЫ применять метку потока IPv6 в соответствии с RFC 6437, если только локальный API не позволяет устанавливать метки потоков IPv6.

К сожалению, Java API не позволяет устанавливать метки потока IPv6.

Не-цели

Следующее скопировано из QUIC RFC 9000. Для каждого раздела проведите обзор и редактирование.

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

Подделка адресов на пути передачи данных

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

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

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

Злоумышленники дополнительно классифицируются как атакующие на пути следования пакетов (on-path attackers) или атакующие вне пути следования пакетов (off-path attackers). Атакующий на пути может читать, изменять или удалять любой наблюдаемый им пакет таким образом, что пакет больше не достигает места назначения, в то время как атакующий вне пути наблюдает пакеты, но не может предотвратить доставку исходного пакета к предполагаемому получателю. Оба типа злоумышленников также могут передавать произвольные пакеты. Это определение отличается от определения в разделе 3.5 SEC-CONS тем, что атакующий вне пути способен наблюдать пакеты.

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

Перенаправление пакетов вне маршрута

Handshake QUIC включает в себя handshake TLS 1.3 и наследует криптографические свойства, описанные в Приложении E.1 TLS13. Многие свойства безопасности QUIC зависят от того, что handshake TLS обеспечивает эти свойства. Любая атака на handshake TLS может повлиять на QUIC.

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

Атака на целостность TLS-handshake может позволить злоумышленнику повлиять на выбор протокола приложения или версии QUIC.

В дополнение к свойствам, предоставляемым TLS, рукопожатие QUIC обеспечивает некоторую защиту от DoS-атак на рукопожатие.

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

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

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

Примечание: Ограничение против усиления применяется только когда конечная точка отвечает на пакеты, полученные с непроверенного адреса. Ограничение против усиления не применяется к клиентам при установлении нового соединения или при инициировании миграции соединения.

Влияние миграции соединений на приватность

Вычисление первого полета сервера для полного handshake потенциально является дорогостоящим, требуя как вычисления подписи, так и обмена ключами. Чтобы предотвратить вычислительные DoS-атаки, пакет Retry предоставляет дешевый механизм обмена токенами, который позволяет серверам проверить IP-адрес клиента перед выполнением любых дорогостоящих вычислений ценой одного кругового обмена. После успешного handshake серверы могут выдать новые токены клиенту, что позволит установить новые соединения без этих затрат.

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

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

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

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

Весь handshake криптографически защищен: Initial пакеты шифруются с помощью ключей для конкретной версии, а Handshake и последующие пакеты шифруются ключами, полученными из обмена ключами TLS. Кроме того, согласование параметров включается в TLS transcript и таким образом обеспечивает те же гарантии целостности, что и обычное TLS согласование. Атакующий может наблюдать транспортные параметры клиента (если он знает salt для конкретной версии), но не может наблюдать транспортные параметры сервера и не может влиять на согласование параметров.

Идентификаторы соединений не шифруются, но защищены по целостности во всех пакетах.

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

Миграция на предпочтительный адрес

Защита пакетов (Раздел 12.1) применяет аутентифицированное шифрование ко всем пакетам, за исключением пакетов Version Negotiation, хотя пакеты Initial и Retry имеют ограниченную защиту из-за использования материала для формирования ключей, зависящего от версии; см. QUIC-TLS для более подробной информации. В данном разделе рассматриваются пассивные и активные атаки на защищенные пакеты.

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

Злоумышленник, который внедряет пакеты без возможности наблюдать действительные пакеты для соединения, вряд ли будет успешным, поскольку защита пакетов обеспечивает, что действительные пакеты создаются только конечными точками, которые обладают ключевым материалом, установленным во время handshake; см. разделы 7 и 21.1.1. Аналогично, любой активный злоумышленник, который наблюдает пакеты и пытается вставить новые данные или изменить существующие данные в этих пакетах, не должен быть способен создать пакеты, считающиеся действительными принимающей конечной точкой, за исключением Initial пакетов.

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

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

Взаимодействие миграции клиента и предпочтительного адреса

Миграция соединения (Раздел 9) предоставляет конечным точкам возможность переключаться между IP-адресами и портами по нескольким путям, используя один путь за раз для передачи и получения фреймов, не являющихся пробными. Валидация пути (Раздел 8.2) устанавливает, что узел готов и способен получать пакеты, отправленные по определенному пути. Это помогает снизить влияние подмены адресов, ограничивая количество пакетов, отправляемых на поддельный адрес.

Данный раздел описывает предполагаемые свойства безопасности миграции соединений при различных типах DoS-атак.

Использование IPv6 Flow Label и миграция

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

Атакующий на пути передачи данных может:

  • Проверка пакетов

  • Изменение заголовков IP и UDP пакетов

  • Внедрение новых пакетов

  • Задержка пакетов

  • Переупорядочивание пакетов

  • Сбрасывать пакеты

  • Разделение и объединение датаграмм по границам пакетов

Атакующий на пути не может:

  • Изменить аутентифицированную часть пакета и заставить получателя принять этот пакет

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

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

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

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

  3. Атакующий на пути не может помешать клиенту мигрировать на путь, на котором атакующий не находится.

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

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

Off-Path Active Attacks

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

Атакующий вне маршрута может:

  • Проверка пакетов

  • Внедрение новых пакетов

  • Переупорядочить внедренные пакеты

Атакующий вне пути не может:

  • Изменение пакетов, отправляемых конечными точками

  • Задержка пакетов

  • Отбрасывать пакеты

  • Переупорядочить исходные пакеты

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

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

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

QUIC нацелен на ограничение возможностей атакующего вне маршрута следующим образом:

  1. Атакующий вне маршрута может участвовать в гонке пакетов и пытаться стать “ограниченным” атакующим на маршруте.

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

  3. Атакующий вне маршрута не может вызвать закрытие соединения после завершения handshake.

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

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

  6. Атакующий вне пути может стать ограниченным атакующим на пути, воздействуя на общее состояние NAT таким образом, чтобы он отправлял пакеты на сервер с того же IP-адреса и порта, которые изначально использовал клиент.

Обзор свойств безопасности

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

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

Ограниченный атакующий на пути может:

  • Проверка пакетов

  • Внедрение новых пакетов

  • Изменение незашифрованных заголовков пакетов

  • Переупорядочить пакеты

Ограниченный атакующий на пути не может:

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

  • Отбрасывать пакеты

  • Изменить аутентифицированную и зашифрованную часть пакета и заставить получателя принять этот пакет

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

QUIC нацелен на ограничение возможностей ограниченного внепутевого злоумышленника следующим образом:

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

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

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

Обратите внимание, что эти гарантии являются теми же гарантиями, которые предоставляются для любого NAT, по тем же причинам.

Рукопожатие

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

После установления соединения QUIC endpoints могут принимать некоторые неаутентифицированные ICMP-пакеты (см. раздел 14.2.1), но использование этих пакетов крайне ограничено. Единственным другим типом пакетов, который endpoint может принимать, является stateless reset (раздел 10.3), который полагается на то, что токен остается секретным до момента его использования.

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

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

Поля Source и Destination Connection ID являются основным средством защиты от атак вне пути во время рукопожатия; см. раздел 8.1. Они должны соответствовать тем, что установлены узлом. За исключением Initial и Stateless Resets, конечная точка принимает только пакеты, которые включают поле Destination Connection ID, соответствующее значению, ранее выбранному конечной точкой. Это единственная защита, предоставляемая для пакетов Version Negotiation.

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

Эти меры защиты не предназначены для эффективной работы против злоумышленника, который способен получать QUIC-пакеты до установления соединения. Такой злоумышленник потенциально может отправлять пакеты, которые будут приняты QUIC endpoints. Данная версия QUIC пытается обнаружить подобного рода атаку, но ожидается, что endpoints не смогут установить соединение, а не восстановятся. По большей части, криптографический протокол handshake QUIC-TLS отвечает за обнаружение несанкционированного вмешательства во время handshake.

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

Противодействие усилению

Злоумышленник может получить токен валидации адреса (Раздел 8) от сервера, а затем освободить IP-адрес, который использовался для получения этого токена. Позднее злоумышленник может инициировать 0-RTT соединение с сервером, подменив этот же адрес, который теперь может принадлежать другой (жертве) конечной точке. Таким образом, злоумышленник потенциально может заставить сервер отправить объем данных размером с начальное окно перегрузки в направлении жертвы.

Серверы ДОЛЖНЫ предоставлять меры защиты от этой атаки путем ограничения использования и времени жизни токенов валидации адресов; см. Раздел 8.1.3.

DoS на стороне сервера

Конечная точка, которая подтверждает пакеты, которые она не получила, может заставить контроллер перегрузок разрешить отправку со скоростями, превышающими те, которые поддерживает сеть. Конечная точка МОЖЕТ пропускать номера пакетов при отправке пакетов для обнаружения такого поведения. Конечная точка может затем немедленно закрыть соединение с ошибкой соединения типа PROTOCOL_VIOLATION; см. Раздел 10.2.

Завершение handshake на пути передачи

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

Для эффективной подделки запросов злоумышленнику необходимо иметь возможность влиять на то, какие пакеты отправляет peer и куда эти пакеты направляются. Если злоумышленник может нацелить уязвимую службу с контролируемой полезной нагрузкой, эта служба может выполнить действия, которые приписываются peer’у злоумышленника, но решения о которых принимает злоумышленник.

Например, эксплойты межсайтовой подделки запроса CSRF в Интернете заставляют клиента отправлять запросы, которые включают авторизационные cookies COOKIE, позволяя одному сайту получить доступ к информации и действиям, которые предназначены для ограничения другим сайтом.

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

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

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

Поскольку атака миграции, описанная в разделе 21.5.4, довольно мощная и не имеет адекватных контрмер, реализации QUIC-серверов должны предполагать, что злоумышленники могут заставить их генерировать произвольные UDP-пакеты для произвольных назначений. QUIC-серверы НЕ ДОЛЖНЫ развертываться в сетях, которые не используют входящую фильтрацию BCP38 и также имеют недостаточно защищенные UDP-конечные точки.

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

Согласование параметров

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 фреймы. Хотя это в некоторой степени зависит от деталей протокола приложения, определенный контроль возможен во многих контекстах использования протокола. Поскольку у атакующего есть доступ к ключам защиты пакетов, он, вероятно, способен предсказать, как узел-партнер будет шифровать будущие пакеты. Успешный контроль над содержимым датаграммы тогда требует только того, чтобы атакующий был способен с некоторой степенью надежности предсказать номер пакета и размещение фреймов в пакетах.

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

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

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

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

Однако поле 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 для подделки запросов.

Миграция соединений

Серверы могут указать предпочтительный адрес, на который клиенты затем мигрируют после подтверждения handshake; см. раздел 9.6. Поле Destination Connection ID пакетов, которые клиент отправляет на предпочтительный адрес, может быть использовано для подделки запросов.

Клиент НЕ ДОЛЖЕН отправлять не-зондирующие фреймы на предпочтительный адрес до валидации этого адреса; см. Раздел 8. Это значительно сокращает возможности сервера по контролю зашифрованной части датаграмм.

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

Активные атаки на пути передачи данных

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

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

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

Данный документ не предлагает конкретных контрмер, которые могут быть реализованы конечными точками, помимо общих мер, описанных в разделе 21.5.6. Однако контрмеры против подмены адресов на сетевом уровне — в частности, входящая фильтрация BCP38 — особенно эффективны против атак, использующих подмену и исходящих из внешней сети.

Атаки с использованием активного воздействия вне маршрута

Клиенты, которые могут представить подделанный адрес источника в пакете, могут заставить сервер отправить пакет Version Negotiation (раздел 17.2.1) на этот адрес.

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

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

Ограниченные активные атаки по маршруту

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

Сервисы, предоставляемые через loopback-интерфейсы, часто не имеют надлежащей аутентификации. Конечные точки МОГУТ предотвращать попытки подключения или миграцию на loopback-адрес. Конечные точки НЕ ДОЛЖНЫ разрешать подключения или миграцию на loopback-адрес, если тот же сервис был ранее доступен на другом интерфейсе или если адрес был предоставлен сервисом с не-loopback адреса. Конечные точки, которые зависят от этих возможностей, могут предложить опцию для отключения этих защитных мер.

Аналогично, конечные точки могли бы рассматривать изменение адреса на link-local адрес RFC4291 или адрес в диапазоне частного использования RFC1918 с глобального, unique-local RFC4193 или не частного адреса как потенциальную попытку подделки запроса. Конечные точки могли бы полностью отказаться от использования таких адресов, но это несет значительный риск вмешательства в законное использование. Конечные точки НЕ ДОЛЖНЫ отказываться от использования адреса, если у них нет конкретных знаний о сети, указывающих на то, что отправка датаграмм на непроверенные адреса в данном диапазоне небезопасна.

Конечные точки МОГУТ выбрать снижение риска подделки запросов, не включая значения из фреймов NEW_TOKEN в пакеты Initial или отправляя только пробные фреймы в пакетах до завершения проверки адреса. Обратите внимание, что это не предотвращает использование атакующим поля Destination Connection ID для атаки.

Конечные точки не должны иметь специфической информации о расположении серверов, которые могли бы стать уязвимыми целями атаки подделки запросов. Однако со временем может стать возможным выявление определенных UDP-портов, которые являются распространенными целями атак, или конкретных шаблонов в датаграммах, используемых для атак. Конечные точки МОГУТ выбрать избегание отправки датаграмм на эти порты или не отправлять датаграммы, соответствующие этим шаблонам, до проверки адреса назначения. Конечные точки МОГУТ отзывать идентификаторы соединений, содержащие шаблоны, известные как проблемные, без их использования.

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

Отказ в обслуживании при рукопожатии

Атаки, широко известные как Slowloris SLOWLORIS, пытаются поддерживать множество соединений с целевой конечной точкой открытыми и удерживать их открытыми как можно дольше. Эти атаки могут быть выполнены против QUIC-конечной точки путем генерирования минимального количества активности, необходимой для избежания закрытия из-за бездействия. Это может включать отправку небольших объемов данных, постепенное открытие окон управления потоком для контроля скорости отправителя или изготовление ACK-фреймов, которые имитируют высокий уровень потерь.

Развертывания QUIC ДОЛЖНЫ обеспечивать средства защиты от атак Slowloris, такие как увеличение максимального количества клиентов, которое сервер будет обслуживать, ограничение количества соединений, которые может устанавливать один IP-адрес, наложение ограничений на минимальную скорость передачи данных для соединения, и ограничение времени, в течение которого конечная точка может оставаться подключенной.

Атака усиления

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

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

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

QUIC развертывания ДОЛЖНЫ обеспечивать меры защиты от атак фрагментации потоков. Меры защиты могут состоять из избегания чрезмерного выделения памяти, ограничения размера структур данных отслеживания, задержки повторной сборки STREAM фреймов, реализации эвристик на основе возраста и продолжительности дыр в повторной сборке, или некоторой комбинации этих методов.

Атака оптимистичного ACK

Злонамеренная конечная точка может открыть большое количество потоков, исчерпывая состояние на конечной точке. Злонамеренная конечная точка может повторить этот процесс для большого количества соединений, подобно атакам SYN flooding в TCP.

Обычно клиенты будут открывать потоки последовательно, как объясняется в Разделе 2.1. Однако, когда несколько потоков инициируются через короткие интервалы, потери или переупорядочивание могут привести к тому, что кадры STREAM, которые открывают потоки, будут получены не по порядку. При получении ID потока с большим номером получатель обязан открыть все промежуточные потоки того же типа; см. Раздел 3.2. Таким образом, при новом соединении открытие потока 4000000 открывает 1 миллион и 1 инициированный клиентом двунаправленный поток.

Количество активных потоков ограничено транспортными параметрами initial_max_streams_bidi и initial_max_streams_uni, которые обновляются любыми полученными фреймами MAX_STREAMS, как объясняется в разделе 4.6. При разумном выборе эти ограничения смягчают эффект атаки обязательства потоков. Однако установка слишком низкого ограничения может повлиять на производительность, когда приложения ожидают открытия большого количества потоков.

Атаки с подделкой запросов

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

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

Если затраты на обработку непропорционально велики по сравнению с потреблением полосы пропускания или влиянием на состояние, то это может позволить злонамеренному узлу исчерпать вычислительную мощность.

Хотя все сообщения имеют законные варианты использования, реализации ДОЛЖНЫ отслеживать стоимость обработки относительно прогресса и рассматривать чрезмерное количество любых непродуктивных пакетов как признак атаки. Конечные точки МОГУТ отвечать на это условие ошибкой соединения или сбросом пакетов.

Параметры управления для конечных точек

Атакующий на пути следования пакетов может манипулировать значением полей ECN в IP-заголовке, чтобы повлиять на скорость отправителя. RFC3168 более подробно обсуждает манипуляции и их эффекты.

Ограниченный атакующий на пути может дублировать и отправлять пакеты с модифицированными полями ECN, чтобы повлиять на скорость отправителя. Если дублированные пакеты отбрасываются получателем, атакующему потребуется опередить дублированный пакет по отношению к оригинальному, чтобы добиться успеха в этой атаке. Поэтому конечные точки QUIC игнорируют поле ECN в IP-пакете, если по крайней мере один пакет QUIC в этом IP-пакете не был успешно обработан; см. раздел 13.4.

Подделка запросов с помощью начальных пакетов клиента

Stateless сбросы создают возможную атаку типа «отказ в обслуживании», аналогичную инъекции TCP reset. Эта атака возможна, если злоумышленник способен заставить сгенерировать stateless reset token для соединения с выбранным connection ID. Злоумышленник, который может заставить сгенерировать этот токен, может сбросить активное соединение с тем же connection ID.

Если пакет может быть направлен к различным экземплярам, которые используют один статический ключ – например, путем изменения IP-адреса или порта – то злоумышленник может заставить сервер отправить сброс без сохранения состояния. Для защиты от подобного типа отказа в обслуживании, конечные точки, которые используют общий статический ключ для сбросов без сохранения состояния (см. Раздел 10.3.2), ДОЛЖНЫ быть организованы таким образом, чтобы пакеты с данным идентификатором соединения всегда поступали к экземпляру, который имеет состояние соединения, если только это соединение больше не активно.

В более общем случае серверы НЕ ДОЛЖНЫ генерировать stateless reset, если соединение с соответствующим connection ID может быть активным на любой конечной точке, использующей тот же статический ключ.

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

Подделка запросов с предпочтительными адресами

Данный документ определяет пакеты согласования версии QUIC (Раздел 6), которые могут использоваться для согласования версии QUIC между двумя конечными точками. Однако данный документ не определяет, как будет выполняться это согласование между данной версией и последующими будущими версиями. В частности, пакеты согласования версии не содержат никакого механизма для предотвращения атак понижения версии. Будущие версии QUIC, использующие пакеты согласования версии, ДОЛЖНЫ определять механизм, который устойчив против атак понижения версии.

Подделка запроса со спуфингом миграции

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

Подделка запроса с согласованием версии

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

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

Relay Security

Ниже приведен анализ Relay Request, Relay Response, Relay Intro и Hole Punch в SSU1.

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

SSU 1: Алиса сначала подключается к introducer Бобу, который передает запрос Чарли (который находится за файрволом). После hole punch сессия устанавливается между Алисой и Чарли как при прямом установлении соединения.

Alice                         Bob                  Charlie
1. RelayRequest ---------------------->
2.      <-------------- RelayResponse    RelayIntro ----------->
3.      <-------------------------------------------- HolePunch
4. SessionRequest -------------------------------------------->
5.      <-------------------------------------------- SessionCreated
6. SessionConfirmed ------------------------------------------>

Аутентификация: Relay Request и Relay Response не защищены безопасной аутентификацией, поскольку Alice и Bob обычно не имеют существующей сессии; эти сообщения используют опубликованные intro ключи. Внутрисессионные Relay Request/Response разрешены и предпочтительны, если сессия существует.

Relay Intro от Bob к Charlie требуется в существующей сессии, поэтому предполагается безопасным.

Bob может подделать Relay Intros или изменить IP/порт из Relay Request. Отсутствуют механизмы для криптографической привязки запросов к интро или иного предотвращения или обнаружения злонамеренных Bob.

Хеш router’а Боба в настоящее время не опубликован в Router Info Чарли, поэтому это необходимо добавить, если мы хотим, чтобы сообщения Алиса-Боб были аутентифицированы. Дополнительно, другие параметры SSU2 должны были бы быть опубликованы в Router Info Чарли, или Алисе пришлось бы искать Router Info Боба в netDb, что добавило бы дополнительную задержку. Аутентификация добавила бы обмен данными туда-обратно между Алисой и Бобом.

Передавая хеш router’а Алисы Чарли, Чарли мог бы легче определить, желает ли он получить соединение от Алисы, проверив локальный список запрещенных. Не существует механизма для Чарли отклонить релей, отправив отказ через Боба Алисе. Не существует механизма для Чарли принять релей, отправив подтверждение через Боба Алисе. Алиса должна ждать HolePunch или просто отправить SessionRequest вслепую. HolePunch может прийти с другого порта, чем ожидала Алиса, из-за NAT, что может затруднить распознавание того, от какого router’а пришел HolePunch.

Алиса могла бы отправить свою полную Router Info в Relay Request к Бобу и переслать Чарли в Relay Intro.

Relay Request не содержит временную метку, поэтому у него нет защиты от повторных атак. Исходный IP может быть подделан, чтобы заставить Чарли отправить Hole Punch на любой IP/порт. Relay Request не подписан, и даже если бы был подписан и содержал временную метку, у Чарли нет полной Router Identity для возможности проверить подпись.

Протокол определяет поле вызова переменной длины 0-255 байт. Вызов в Relay Request передается Чарли в Relay Intro. Однако протокол не указывает, как создавать, использовать или проверять вызов, и это не реализовано. Если бы HolePunch содержал вызов, Алиса смогла бы легко соотнести HolePunch с Чарли.

Четырехбайтовый nonce может потребоваться заменить или дополнить 8-байтовым connection ID.

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

Дополнительное обсуждение DPI

Далее приводится анализ Peer Test в SSU1.

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

SSU 1:

Alice                     Bob                  Charlie
1. PeerTest ------------------->
2.                          PeerTest-------------------->
3.                             <-------------------PeerTest
4.      <-------------------PeerTest

5.      <------------------------------------------PeerTest
6. PeerTest------------------------------------------>
7.      <------------------------------------------PeerTest

Поскольку спецификацию SSU1 сложно понять, мы документируем содержимое сообщений ниже.

MessagePathAlice IP incl?Intro Key
1A->B sessionnoAlice
2B->C sessionyesAlice
3C->B sessionyesCharlie
4B->A sessionyesCharlie
5C->AyesCharlie
6A->CnoAlice
7C->AyesCharlie
Аутентификация: Алиса всегда выберет Боба с существующей сессией. Боб будет отклонять PeerTests от узлов без установленной сессии. Сообщение 1 отправляется внутри сессии. Следовательно, сообщение 1 является безопасным и аутентифицированным.

Боб выбирает Чарли, с которым у него есть существующая сессия. Сообщения 2 и 3 отправляются внутри сессии. Поэтому сообщения 2 и 3 являются безопасными и аутентифицированными.

Сообщение 4 должно отправляться внутри сессии; однако, спецификация SSU 1 ранее указывала, что оно отправляется с опубликованным intro key Алисы, что означает не внутри сессии. До версии 0.9.52 Java I2P действительно отправлял с intro key. Начиная с версии 0.9.52, спецификация гласит, что должен использоваться ключ сессии, и Java I2P отправляет сообщение внутри сессии начиная с версии 0.9.52.

Алиса не должна иметь существующую сессию с Чарли для продолжения теста; Алиса прерывает тест, если Боб выбирает Чарли, у которого есть сессия с Алисой. Поэтому сообщения 5-7 не являются безопасными и аутентифицированными.

Все сообщения Peer Test содержат 4-байтовый nonce, который выбирается Alice. Этот nonce не используется криптографически.

Возможные атаки на сообщения 5-7: требует исследования.

Хеш router’а Алисы неизвестен Чарли. Хеш router’а Чарли неизвестен Алисе. Они должны быть добавлены в протокол, если мы хотим, чтобы сообщения между Алисой и Чарли были аутентифицированы. Дополнительно, другие параметры SSU2 должны были бы предоставляться в сообщениях Peer Test, или Чарли пришлось бы искать Router Info Алисы в сетевой базе данных, что добавило бы дополнительную задержку. Аутентификация добавила бы один round-trip между Чарли и Алисой.

Пересылая хеш router’а Алисы Чарли, Чарли мог бы легче определить, желает ли он участвовать в Peer Test с Алисой, проверив локальный список блокировок.

Четырехбайтовый nonce может потребовать замены или дополнения 8-байтовым идентификатором соединения.

Relay and Peer Test Design Goals

Relay и Peer Test имеют схожие конструкции. В обоих случаях Алиса запрашивает Боба переслать служебный запрос Чарли, и затем Чарли выполняет этот запрос.

Текущие проблемы SSU1 Peer Test:

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

Текущие проблемы SSU1 Relay:

Большинство проблем Peer Test, перечисленных выше, также относятся к Peer Test.

У нас есть следующие цели по улучшению безопасности Relay и Peer Test:

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

  • Защита от подмены адресов или угроз типа man-in-the-middle, которые могут подделывать, изменять, фальсифицировать или повторно отправлять запросы от Alice к Bob. Bob должен убедиться, что Alice является настоящим I2P router и что представленные запрос и тестовый адрес действительны.

  • Защита от вредоносных Bob, которые могут подделывать, изменять, фальсифицировать или повторно отправлять запросы, переадресованные Charlie. Charlie должен убедиться, что и Alice, и Bob являются настоящими I2P router’ами и что представленные запрос и тестовый адрес являются действительными.

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

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

  • Алиса должна иметь возможность проверить, что ответ, переданный через Боба, действительно поступил от Чарли.

  • Алиса и Чарли должны иметь возможность проверить, что их последующие прямые сообщения (не переданные через Боба) исходят от ожидаемого источника и являются настоящими I2P роутерами.

Следующие механизмы могут помочь в достижении этих целей:

  • Временные метки

  • Подписи с использованием ключа подписи router

  • Использование данных вызова, включенных в запрос

  • Шифрование с использованием ключа шифрования router

  • Отправка хешей роутеров, Router Identities или Router Infos, а не только IP-адресов и портов.

  • Валидация информации router путем запроса к базе данных сети

  • Проверка информации маршрутизатора, IP-адресов и портов по спискам блокировки

  • Ограничение скорости

  • Требование установки сессии

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

Кросс-версионная ретрансляция и тестирование узлов также должны поддерживаться, если это возможно. Это облегчит постепенный переход с SSU 1 на SSU 2. Возможные комбинации версий:

Alice/BobBob/CharlieAlice/CharlieSupported
111SSU 1
112no, use 1/1/1
121Relay: yes? Peer Test: no
122no, use 1/2/1
211Relay: yes? Peer Test: no
212Relay: yes? Peer Test: no
221no, use 2/2/2
222yes

Цели безопасности

Summary

Мы опираемся на несколько существующих протоколов, как внутри I2P, так и внешних стандартов, для вдохновения, руководства и повторного использования кода:

  • Модели угроз: Из NTCP2 NTCP2, со значительными дополнительными угрозами, относящимися к UDP-транспорту, как проанализировано в QUIC RFC 9000 RFC 9001.

  • Криптографические решения: Из NTCP2.

  • Handshake: Noise XK из NTCP2 и NOISE. Значительные упрощения по сравнению с NTCP2 возможны благодаря инкапсуляции (встроенные границы сообщений), обеспечиваемой UDP.

  • Обфускация эфемерного ключа рукопожатия: Адаптировано из NTCP2, но с использованием ChaCha20 из ECIES вместо AES.

  • Заголовки пакетов: Адаптированы из WireGuard WireGuard и QUIC RFC 9000 RFC 9001.

  • Обфускация заголовков пакетов: Адаптирована из NTCP2, но использует ChaCha20 из ECIES вместо AES.

  • Защита заголовков пакетов: Адаптировано из QUIC RFC 9001 и Nonces

  • Заголовки, используемые как AEAD ассоциированные данные, как в ECIES.

  • Нумерация пакетов: Адаптировано из WireGuard WireGuard и QUIC RFC 9000 RFC 9001.

  • Сообщения: Адаптировано из SSU

  • Фрагментация I2NP: Адаптировано из SSU

  • Relay и Peer Testing: Адаптировано из SSU

  • Подписи данных Relay и Peer Test: Из спецификации общих структур Common

  • Формат блока: Из NTCP2 и ECIES.

  • Заполнение и опции: Из NTCP2 и ECIES.

  • Acks, nacks: Адаптировано из QUIC RFC 9000.

  • Управление потоком: TBD

В I2P не используются новые криптографические примитивы, которые не применялись в I2P ранее.

Валидация адресов

Как и другие транспорты I2P — NTCP, NTCP2 и SSU 1, — данный транспорт не является универсальным средством для доставки упорядоченного потока байтов. Он предназначен для транспортировки сообщений I2NP. Абстракция «потока» не предоставляется.

Кроме того, как и для SSU, он содержит дополнительные возможности для обхода NAT с помощью пиров и тестирования доступности (входящих соединений).

Что касается SSU 1, он НЕ обеспечивает упорядоченную доставку I2NP сообщений. Также он не гарантирует доставку I2NP сообщений. Для повышения эффективности, или из-за неупорядоченной доставки UDP датаграмм или их потери, I2NP сообщения могут быть доставлены на дальний конец в неправильном порядке или могут вообще не быть доставлены. I2NP сообщение может быть повторно передано несколько раз при необходимости, но доставка может в конечном итоге завершиться неудачей без разрыва всего соединения. Кроме того, новые I2NP сообщения могут продолжать отправляться даже во время повторной передачи (восстановления после потерь) других I2NP сообщений.

Этот протокол НЕ предотвращает полностью дублированную доставку I2NP сообщений. Router должен обеспечивать истечение срока действия I2NP и использовать фильтр Блума или другой механизм, основанный на ID I2NP сообщения. См. раздел “Дублирование I2NP сообщений” ниже.

Noise Protocol Framework

Данное предложение определяет требования на основе Noise Protocol Framework NOISE (редакция 33, 2017-10-04). Noise имеет схожие свойства с протоколом Station-To-Station (STS), который является основой для протокола SSU. В терминологии Noise Алиса является инициатором, а Боб - ответчиком.

SSU2 основан на протоколе Noise Noise_XK_25519_ChaChaPoly_SHA256. (Фактический идентификатор для функции первоначального извлечения ключа - “Noise_XKchaobfse+hs1+hs2+hs3_25519_ChaChaPoly_SHA256”, указывающий на расширения I2P - см. раздел KDF 1 ниже)

ПРИМЕЧАНИЕ: Этот идентификатор отличается от используемого для NTCP2, поскольку все три сообщения рукопожатия используют заголовок в качестве ассоциированных данных.

Этот протокол Noise использует следующие примитивы:

  • Handshake Pattern: XK Алиса передает свой ключ Бобу (X) Алиса уже знает статический ключ Боба (K)

  • DH Function: X25519 X25519 DH с длиной ключа 32 байта, как указано в RFC 7748.

  • Cipher Function: ChaChaPoly AEAD_CHACHA20_POLY1305 как указано в RFC 7539 разделе 2.8. 12-байтовый nonce, где первые 4 байта установлены в ноль.

  • Hash Function: SHA256 Стандартный 32-байтный хеш, уже широко используемый в I2P.

Additions to the Framework

Данное предложение определяет следующие улучшения для Noise_XK_25519_ChaChaPoly_SHA256. Они в целом следуют рекомендациям в разделе 13 NOISE.

  1. Сообщения handshake (Session Request, Created, Confirmed) включают заголовок размером 16 или 32 байта.

  2. Заголовки для сообщений handshake (Session Request, Created, Confirmed) используются как входные данные для mixHash() перед шифрованием/расшифрованием для привязки заголовков к сообщению.

  3. Заголовки зашифрованы и защищены.

  4. Открытые эфемерные ключи маскируются шифрованием ChaCha20 с использованием известного ключа и IV. Это быстрее, чем elligator2.

  5. Формат полезной нагрузки определен для сообщений 1, 2 и фазы данных. Конечно, это не определено в Noise.

Фаза данных использует шифрование, похожее на фазу данных Noise, но не совместимое с ней.

Processing overhead estimate

Будет определено позднее

Definitions

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

ZEROLEN

zero-length byte array

H(p, d)

SHA-256 hash function that takes a personalization string p and data d, and
produces an output of length 32 bytes.
As defined in [NOISE](https://noiseprotocol.org/noise.html).
|| below means append.

Use SHA-256 as follows::

    H(p, d) := SHA-256(p || d)

MixHash(d)

SHA-256 hash function that takes a previous hash h and new data d,
and produces an output of length 32 bytes.
|| below means append.

Use SHA-256 as follows::

    MixHash(d) := h = SHA-256(h || d)

STREAM

The ChaCha20/Poly1305 AEAD as specified in [RFC 7539](https://tools.ietf.org/html/rfc7539).
S_KEY_LEN = 32 and S_IV_LEN = 12.

ENCRYPT(k, n, plaintext, ad)
    Encrypts plaintext using the cipher key k, and nonce n which MUST be unique for
    the key k.
    Associated data ad is optional.
    Returns a ciphertext that is the size of the plaintext + 16 bytes for the HMAC.

    The entire ciphertext must be indistinguishable from random if the key is secret.

DECRYPT(k, n, ciphertext, ad)
    Decrypts ciphertext using the cipher key k, and nonce n.
    Associated data ad is optional.
    Returns the plaintext.

DH

X25519 public key agreement system. Private keys of 32 bytes, public keys of 32
bytes, produces outputs of 32 bytes. It has the following
functions:

GENERATE_PRIVATE()
    Generates a new private key.

DERIVE_PUBLIC(privkey)
    Returns the public key corresponding to the given private key.

DH(privkey, pubkey)
    Generates a shared secret from the given private and public keys.

HKDF(salt, ikm, info, n)

A cryptographic key derivation function which takes some input key material ikm (which
should have good entropy but is not required to be a uniformly random string), a salt
of length 32 bytes, and a context-specific 'info' value, and produces an output
of n bytes suitable for use as key material.

Use HKDF as specified in [RFC 5869](https://tools.ietf.org/html/rfc5869), using the HMAC hash function SHA-256
as specified in [RFC 2104](https://tools.ietf.org/html/rfc2104). This means that SALT_LEN is 32 bytes max.

MixKey(d)

Use HKDF() with a previous chainKey and new data d, and
sets the new chainKey and k.
As defined in [NOISE](https://noiseprotocol.org/noise.html).

Use HKDF as follows::

    MixKey(d) := output = HKDF(chainKey, d, "", 64)
                 chainKey = output[0:31]
                 k = output[32:63]

Messages

Каждая UDP дейтаграмма содержит ровно одно сообщение. Длина дейтаграммы (после IP и UDP заголовков) равна длине сообщения. Padding, если присутствует, содержится в блоке padding внутри сообщения. В этом документе мы используем термины “дейтаграмма” и “пакет” в основном как взаимозаменяемые. Каждая дейтаграмма (или пакет) содержит одно сообщение (в отличие от QUIC, где дейтаграмма может содержать несколько QUIC пакетов). “Заголовок пакета” - это часть после IP/UDP заголовка.

Исключение: Сообщение Session Confirmed уникально тем, что оно может быть фрагментировано на несколько пакетов. Смотрите раздел Session Confirmed Fragmentation ниже для получения дополнительной информации.

Все сообщения SSU2 имеют длину не менее 40 байт. Любое сообщение длиной 1-39 байт является недействительным. Все сообщения SSU2 имеют длину менее или равную 1472 (IPv4) или 1452 (IPv6) байт. Формат сообщения основан на сообщениях Noise с модификациями для кадрирования и неразличимости. Реализации, использующие стандартные библиотеки Noise, должны предварительно обрабатывать полученные сообщения до стандартного формата сообщений Noise. Все зашифрованные поля представляют собой шифртексты AEAD.

Определены следующие сообщения:

TypeMessageHeader LengthHeader Encr. Length
0SessionRequest3264
1SessionCreated3264
2SessionConfirmed1616
6Data1616
7PeerTest3232
9Retry3232
10Token Request3232
11HolePunch3232

Session Establishment

Стандартная последовательность установления соединения, когда у Алисы есть действительный токен, ранее полученный от Боба, выглядит следующим образом:

Alice                           Bob

SessionRequest ------------------->
<------------------- SessionCreated
SessionConfirmed ----------------->

Когда у Alice нет действительного токена, последовательность установления соединения выглядит следующим образом:

Alice                           Bob

TokenRequest --------------------->
<---------------------------  Retry
SessionRequest ------------------->
<------------------- SessionCreated
SessionConfirmed ----------------->

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

Alice                           Bob

SessionRequest ------------------->
<---------------------------  Retry
SessionRequest ------------------->
<------------------- SessionCreated
SessionConfirmed ----------------->

Боб может отклонить запрос Session или Token, ответив сообщением Retry, содержащим блок Termination с кодом причины. На основе кода причины Алиса не должна предпринимать другую попытку запроса в течение определенного периода времени:

Alice                           Bob

SessionRequest ------------------->
<---------------------------  Retry containing a Termination block

or

TokenRequest --------------------->
<---------------------------  Retry containing a Termination block

Используя терминологию Noise, последовательность установления соединения и передачи данных выглядит следующим образом: (Свойства безопасности полезной нагрузки)

XK(s, rs):           Authentication   Confidentiality
    <- s
    ...
    -> e, es                  0                2
    <- e, ee                  2                1
    -> s, se                  2                5
    <-                        2                5

После установления сессии Алиса и Боб могут обмениваться сообщениями Data.

Packet Header

Все пакеты начинаются с обфусцированного (зашифрованного) заголовка. Существует два типа заголовков: длинный и короткий. Обратите внимание, что первые 13 байт (Destination Connection ID, номер пакета и тип) одинаковы для всех заголовков.

Контрмеры против общих атак подделки запросов

Длинный заголовок составляет 32 байта. Он используется до создания сессии для Token Request, SessionRequest, SessionCreated и Retry. Он также используется для сообщений Peer Test и Hole Punch вне сессии.

До шифрования заголовка:


+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type| ver| id |flag|
  +----+----+----+----+----+----+----+----+
  |        Source Connection ID           |
  +----+----+----+----+----+----+----+----+
  |                 Token                 |
  +----+----+----+----+----+----+----+----+

  Destination Connection ID :: 8 bytes, unsigned big endian integer

  Packet Number :: 4 bytes, unsigned big endian integer

  type :: The message type = 0, 1, 7, 9, 10, or 11

  ver :: The protocol version, equal to 2

  id :: 1 byte, the network ID (currently 2, except for test networks)

  flag :: 1 byte, unused, set to 0 for future compatibility

  Source Connection ID :: 8 bytes, unsigned big endian integer

  Token :: 8 bytes, unsigned big endian integer

Атаки Slowloris

Короткий заголовок составляет 16 байт. Он используется для сообщений Session Created и Data. Неаутентифицированные сообщения, такие как Session Request, Retry и Peer Test, всегда будут использовать длинный заголовок.

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

Для Session Confirmed, до шифрования заголовка:


+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type|frag|  flags  |
  +----+----+----+----+----+----+----+----+

  Destination Connection ID :: 8 bytes, unsigned big endian integer

  Packet Number :: 4 bytes, all zeros

  type :: The message type = 2

  frag :: 1 byte fragment info:
         bit order: 76543210 (bit 7 is MSB)
         bits 7-4: fragment number 0-14, big endian
         bits 3-0: total fragments 1-15, big endian

  flags :: 2 bytes, unused, set to 0 for future compatibility

Смотрите раздел Session Confirmed Fragmentation ниже для получения дополнительной информации о поле frag.

Для Data сообщений, перед шифрованием заголовка:


+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type|flag|moreflags|
  +----+----+----+----+----+----+----+----+

  Destination Connection ID :: 8 bytes, unsigned big endian integer

  Packet Number :: 4 bytes, unsigned big endian integer

  type :: The message type = 6

  flag :: 1 byte flags:
         bit order: 76543210 (bit 7 is MSB)
         bits 7-1: unused, set to 0 for future compatibility
         bits 0: when set to 1, immediate ack requested

  moreflags :: 2 bytes, unused, set to 0 for future compatibility

Атаки фрагментации и повторной сборки потоков

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

В отличие от QUIC, мы не изменяем идентификаторы соединения во время или после рукопожатия, даже после сообщения Retry. Идентификаторы остаются постоянными с первого сообщения (Token Request или Session Request) до последнего сообщения (Data with Termination). Кроме того, идентификаторы соединения не изменяются во время или после проверки пути или миграции соединения.

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

Атака с обязательством потока

Если в рукопожатии не отправляется блок First Packet Number, пакеты нумеруются в рамках одной сессии для каждого направления, начиная с 0, до максимума (2**32 -1). Сессия должна быть завершена и создана новая сессия задолго до отправки максимального количества пакетов.

Если блок First Packet Number отправляется в рукопожатии, пакеты нумеруются в рамках одной сессии для данного направления, начиная с этого номера пакета. Номер пакета может обернуться во время сессии. Когда отправлено максимум 2**32 пакетов, что приводит к обёртыванию номера пакета обратно к первому номеру пакета, эта сессия больше не является действительной. Сессия должна быть завершена и создана новая сессия задолго до отправки максимального количества пакетов.

TODO ротация ключей, уменьшить максимальный номер пакета?

Пакеты handshake, которые определены как потерянные, передаются повторно целиком, с идентичным заголовком, включая номер пакета. Сообщения handshake Session Request, Session Created и Session Confirmed ДОЛЖНЫ передаваться повторно с тем же номером пакета и идентичным зашифрованным содержимым, чтобы для шифрования ответа использовался тот же цепочечный хеш. Сообщение Retry никогда не передается.

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

Повторная передача неизмененного целого пакета как есть, с тем же номером пакета, не разрешена по нескольким причинам. Для получения справочной информации см. QUIC RFC 9000 раздел 12.3.

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

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

Исключение: Пакет фазы данных, содержащий блок завершения, может быть, но не обязан быть, повторно передан целиком, как есть. См. раздел “Завершение сессии” ниже.

Следующие пакеты содержат случайный номер пакета, который игнорируется:

  • Session Request
  • Session Created
  • Token Request
  • Retry
  • Peer Test
  • Hole Punch

Для Алисы нумерация исходящих пакетов начинается с 0 с Session Confirmed. Для Боба нумерация исходящих пакетов начинается с 0 с первого пакета Data, который должен быть ACK для Session Confirmed. Номера пакетов в примере стандартного рукопожатия будут:

Alice                           Bob

SessionRequest (r)    ------------>
<-------------   SessionCreated (r)
SessionConfirmed (0)  ------------>
<-------------             Data (0) (Ack-only)
Data (1)              ------------> (May be sent before Ack is received)
<-------------             Data (1)
Data (2)              ------------>
Data (3)              ------------>
Data (4)              ------------>
<-------------             Data (2)

r = random packet number (ignored)
Token Request, Retry, and Peer Test
also have random packet numbers.

Любая повторная передача handshake сообщений (SessionRequest, SessionCreated или SessionConfirmed) должна быть отправлена без изменений, с тем же номером пакета. Не используйте разные эфемерные ключи и не изменяйте полезную нагрузку при повторной передаче этих сообщений.

Отказ в обслуживании пира

Заголовок (до обфускации и защиты) всегда включается в ассоциированные данные для функции AEAD, чтобы криптографически связать заголовок с данными.

Атаки с явным уведомлением о перегрузке

Шифрование заголовков имеет несколько целей. См. раздел “Дополнительное обсуждение DPI” выше для контекста и предпосылок.

  • Предотвратить идентификацию протокола онлайн DPI
  • Предотвратить паттерны в серии сообщений в одном и том же соединении, за исключением повторных передач рукопожатия
  • Предотвратить паттерны в сообщениях одного типа в разных соединениях
  • Предотвратить дешифрование заголовков рукопожатия без знания introduction key, найденного в netDb
  • Предотвратить идентификацию эфемерных ключей X25519 без знания introduction key, найденного в netDb
  • Предотвратить дешифрование номера пакета и типа фазы данных любым онлайн или офлайн атакующим
  • Предотвратить инъекцию валидных пакетов рукопожатия наблюдателем на пути или вне пути без знания introduction key, найденного в netDb
  • Предотвратить инъекцию валидных пакетов данных наблюдателем на пути или вне пути
  • Обеспечить быструю и эффективную классификацию входящих пакетов
  • Обеспечить сопротивление “прощупыванию”, чтобы не было ответа на плохой Session Request, или если есть Retry ответ, ответ не идентифицируется как I2P без знания introduction key, найденного в netDb
  • Destination Connection ID не является критичными данными, и допустимо, если их может расшифровать наблюдатель со знанием introduction key, найденного в netDb
  • Номер пакета пакета фазы данных является AEAD nonce и критичными данными. Он не должен быть расшифровываемым наблюдателем даже со знанием introduction key, найденного в netDb. См. Nonces.

Заголовки шифруются с помощью известных ключей, опубликованных в базе данных сети или вычисленных позже. На этапе handshake это служит только для сопротивления DPI, поскольку ключ является публичным, а ключ и nonce повторно используются, поэтому это фактически просто обфускация. Обратите внимание, что шифрование заголовков также используется для обфускации эфемерных ключей X (в Session Request) и Y (в Session Created).

Смотрите раздел “Обработка входящих пакетов” ниже для получения дополнительных указаний.

Байты 0-15 всех заголовков шифруются с использованием схемы защиты заголовков путем операции XOR с данными, вычисленными из известных ключей, используя ChaCha20, аналогично QUIC RFC 9001 и Nonces. Это обеспечивает то, что зашифрованный короткий заголовок и первая часть длинного заголовка будут выглядеть случайными.

Для Session Request и Session Created байты 16-31 длинного заголовка и 32-байтовый Noise эфемерный ключ шифруются с использованием ChaCha20. Незашифрованные данные являются случайными, поэтому зашифрованные данные будут выглядеть как случайные.

Для Retry байты 16-31 длинного заголовка шифруются с использованием ChaCha20. Нешифрованные данные являются случайными, поэтому зашифрованные данные будут выглядеть случайными.

В отличие от схемы защиты заголовков QUIC RFC 9001, ВСЕ части всех заголовков, включая идентификаторы соединения назначения и источника, зашифрованы. QUIC RFC 9001 и Nonces в первую очередь сосредоточены на шифровании “критической” части заголовка, т.е. номера пакета (nonce ChaCha20). Хотя шифрование идентификатора сессии делает классификацию входящих пакетов немного более сложной, это затрудняет некоторые атаки. QUIC определяет разные идентификаторы соединения для разных фаз, а также для проверки пути и миграции соединения. Здесь мы используем одни и те же идентификаторы соединения на протяжении всего процесса, поскольку они зашифрованы.

Существует семь фаз ключей защиты заголовков:

  • Запрос сессии и запрос токена
  • Сессия создана
  • Повторная попытка
  • Сессия подтверждена
  • Фаза данных
  • Тест узла
  • Пробивка NAT
MessageKey k_header_1Key k_header_2
Token RequestBob Intro KeyBob Intro Key
Session RequestBob Intro KeyBob Intro Key
Session CreatedBob Intro KeySee Session Request K
Session ConfirmedBob Intro KeySee Session Created K
RetryBob Intro KeyBob Intro Key
DataAlice/Bob Intro KeySee data phase KDF
Peer Test 5,7Alice Intro KeyAlice Intro Key
Peer Test 6Charlie Intro KeyCharlie Intro Key
Hole PunchAlice Intro KeyAlice Intro Key
Шифрование заголовка предназначено для быстрой классификации входящих пакетов без сложной эвристики или резервных механизмов. Это достигается за счёт использования одного и того же ключа k_header_1 для почти всех входящих сообщений. Даже когда исходный IP или порт соединения изменяется из-за фактического изменения IP или поведения NAT, пакет может быть быстро сопоставлен с сессией при помощи единственного поиска connection ID.

Обратите внимание, что Session Created и Retry — это ЕДИНСТВЕННЫЕ сообщения, которые требуют резервной обработки для k_header_1 для расшифровки Connection ID, поскольку они используют intro key отправителя (Bob). ВСЕ остальные сообщения используют intro key получателя для k_header_1. Резервная обработка должна только искать ожидающие исходящие соединения по IP/порту источника.

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

  • Не является сообщением SSU2
  • Поврежденное сообщение SSU2
  • Ответ подделан или изменен злоумышленником
  • Bob имеет симметричный NAT
  • Bob изменил IP или порт во время обработки сообщения
  • Bob отправил ответ через другой интерфейс

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

См. раздел “Обработка входящих пакетов” ниже для получения дополнительных рекомендаций.

Смотрите отдельные разделы KDF ниже для получения ключей шифрования заголовков для этой фазы.

Stateless Reset Oracle

// incoming encrypted packet
  packet = incoming encrypted packet
  len = packet.length

  // take the next-to-last 12 bytes of the packet
  iv = packet[len-24:len-13]
  k_header_1 = header encryption key 1
  data = {0, 0, 0, 0, 0, 0, 0, 0}
  mask = ChaCha20.encrypt(k_header_1, iv, data)

  // encrypt the first part of the header by XORing with the mask
  packet[0:7] ^= mask[0:7]

  // take the last 12 bytes of the packet
  iv = packet[len-12:len-1]
  k_header_2 = header encryption key 2
  data = {0, 0, 0, 0, 0, 0, 0, 0}
  mask = ChaCha20.encrypt(k_header_2, iv, data)

  // encrypt the second part of the header by XORing with the mask
  packet[8:15] ^= mask[0:7]


  // For Session Request and Session Created only:
  iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

  // encrypt the third part of the header and the ephemeral key
  packet[16:63] = ChaCha20.encrypt(k_header_2, iv, packet[16:63])


  // For Retry, Token Request, Peer Test, and Hole Punch only:
  iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

  // encrypt the third part of the header
  packet[16:31] = ChaCha20.encrypt(k_header_2, iv, packet[16:31])

Данная KDF использует последние 24 байта пакета в качестве IV для двух операций ChaCha20. Поскольку все пакеты заканчиваются 16-байтовым MAC, это требует, чтобы все полезные нагрузки пакетов имели минимальный размер 8 байт. Данное требование дополнительно документировано в разделах сообщений ниже.

Понижение версии

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

Расшифровка следующих 8 байт заголовка затем раскроет тип сообщения и позволит определить, является ли он коротким или длинным заголовком. Если это длинный заголовок, получатель должен проверить поля версии и netid. Если версия != 2, или netid != ожидаемое значение (обычно 2, за исключением тестовых сетей), получатель должен отбросить сообщение.

Packet Integrity

Все сообщения содержат либо три, либо четыре части:

  • Заголовок сообщения
  • Только для Session Request и Session Created, эфемерный ключ
  • Полезная нагрузка, зашифрованная ChaCha20
  • MAC Poly1305

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

  • Для handshake сообщений Session Request, Session Created и Session Confirmed, заголовок сообщения обрабатывается mixHash() перед фазой обработки Noise
  • Эфемерный ключ, если присутствует, покрывается стандартным Noise misHash()
  • Для сообщений вне handshake Noise, заголовок используется как Associated Data для шифрования ChaCha20/Poly1305.

Обработчики входящих пакетов всегда должны расшифровывать полезную нагрузку ChaCha20 и проверять MAC перед обработкой сообщения, за одним исключением: Для смягчения DoS-атак от пакетов с подменённым адресом, содержащих кажущиеся сообщения Session Request с недействительным токеном, обработчик НЕ ДОЛЖЕН пытаться расшифровать и проверить полное сообщение (что требует дорогостоящей операции DH в дополнение к расшифровке ChaCha20/Poly1305). Обработчик может ответить сообщением Retry, используя значения, найденные в заголовке сообщения Session Request.

Authenticated Encryption

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

Зашифрованные/аутентифицированные данные будут представлены как

+----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |   Encrypted and authenticated data    |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

Целенаправленные атаки через маршрутизацию

Зашифрованный и аутентифицированный формат данных.

Входные данные для функций шифрования/дешифрования:


k :: 32 byte cipher key, as generated from KDF

  nonce :: Counter-based nonce, 12 bytes.
           Starts at 0 and incremented for each message.
           First four bytes are always zero.
           Last eight bytes are the counter, little-endian encoded.
           Maximum value is 2**64 - 2.
           Connection must be dropped and restarted after
           it reaches that value.
           The value 2**64 - 1 must never be sent.

  ad :: In handshake phase:
        Associated data, 32 bytes.
        The SHA256 hash of all preceding data.
        In data phase:
        The packet header, 16 bytes.

  data :: Plaintext data, 0 or more bytes

Результат функции шифрования, входные данные для функции расшифрования:


+----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |       ChaCha20 encrypted data         |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+
  |  Poly1305 Message Authentication Code |
  +              (MAC)                    +
  |             16 bytes                  |
  +----+----+----+----+----+----+----+----+

  encrypted data :: Same size as plaintext data, 0 - 65519 bytes

  MAC :: Poly1305 message authentication code, 16 bytes

Для ChaCha20 то, что описано здесь, соответствует RFC 7539, который также используется аналогичным образом в TLS RFC 7905.

Анализ трафика

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

  • Ключ для шифра (256 бит) согласовывается с помощью SHA256 KDF. Детали KDF для каждого сообщения приведены в отдельных разделах ниже.

AEAD Error Handling

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

  • Bob должен поддерживать чёрный список IP-адресов с повторяющимися сбоями.

KDF for Session Request

Функция вывода ключа (KDF) генерирует ключ шифрования k для фазы handshake из результата DH, используя HMAC-SHA256(key, data) как определено в RFC 2104. Это функции InitializeSymmetric(), MixHash() и MixKey(), точно как определено в спецификации Noise.

KDF for Initial ChainKey


// Define protocol_name.
  Set protocol_name = "Noise_XKchaobfse+hs1+hs2+hs3_25519_ChaChaPoly_SHA256"
   (52 bytes, US-ASCII encoded, no NULL termination).

  // Define Hash h = 32 bytes
  h = SHA256(protocol_name);

  Define ck = 32 byte chaining key. Copy the h data to ck.
  Set ck = h

  // MixHash(null prologue)
  h = SHA256(h);

  // up until here, can all be precalculated by Alice for all outgoing connections

  // Bob's X25519 static keys
  // bpk is published in routerinfo
  bsk = GENERATE_PRIVATE()
  bpk = DERIVE_PUBLIC(bsk)

  // Bob static key
  // MixHash(bpk)
  // || below means append
  h = SHA256(h || bpk);

  // Bob introduction key
  // bik is published in routerinfo
  bik = RANDOM(32)

  // up until here, can all be precalculated by Bob for all incoming connections

KDF for Session Request


// MixHash(header)
  h = SHA256(h || header)

  This is the "e" message pattern:

  // Alice's X25519 ephemeral keys
  aesk = GENERATE_PRIVATE()
  aepk = DERIVE_PUBLIC(aesk)

  // Alice ephemeral key X
  // MixHash(aepk)
  h = SHA256(h || aepk);

  // h is used as the associated data for the AEAD in Session Request
  // Retain the Hash h for the Session Created KDF


  End of "e" message pattern.

  This is the "es" message pattern:

  // DH(e, rs) == DH(s, re)
  sharedSecret = DH(aesk, bpk) = DH(bsk, aepk)

  // MixKey(DH())
  //[chainKey, k] = MixKey(sharedSecret)
  // ChaChaPoly parameters to encrypt/decrypt
  keydata = HKDF(chainKey, sharedSecret, "", 64)
  chainKey = keydata[0:31]

  // AEAD parameters
  k = keydata[32:63]
  n = 0
  ad = h
  ciphertext = ENCRYPT(k, n, payload, ad)

  // retain the chainKey for Session Created KDF


  End of "es" message pattern.

  // Header encryption keys for this message
  // bik = Bob's intro key
  k_header_1 = bik
  k_header_2 = bik

  // Header encryption keys for next message (Session Created)
  k_header_1 = bik
  k_header_2 = HKDF(chainKey, ZEROLEN, "SessCreateHeader", 32)

  // Header encryption keys for next message (Retry)
  k_header_1 = bik
  k_header_2 = bik

SessionRequest (Type 0)

Alice отправляет Bob’у, либо как первое сообщение в handshake, либо в ответ на сообщение Retry. Bob отвечает сообщением Session Created. Размер: 80 + размер payload. Минимальный размер: 88

Если у Алисы нет действительного токена, Алиса должна отправить сообщение Token Request вместо Session Request, чтобы избежать накладных расходов на асимметричное шифрование при генерации Session Request.

Длинный заголовок. Содержимое Noise: эфемерный ключ Алисы X Полезная нагрузка Noise: DateTime и другие блоки Максимальный размер полезной нагрузки: MTU - 108 (IPv4) или MTU - 128 (IPv6). Для MTU 1280: Максимальная полезная нагрузка составляет 1172 (IPv4) или 1152 (IPv6). Для MTU 1500: Максимальная полезная нагрузка составляет 1392 (IPv4) или 1372 (IPv6).

Свойства безопасности полезной нагрузки:

XK(s, rs):           Authentication   Confidentiality
    -> e, es                  0                2

    Authentication: None (0).
    This payload may have been sent by any party, including an active attacker.

    Confidentiality: 2.
    Encryption to a known recipient, forward secrecy for sender compromise
    only, vulnerable to replay.  This payload is encrypted based only on DHs
    involving the recipient's static key pair.  If the recipient's static
    private key is compromised, even at a later date, this payload can be
    decrypted.  This message can also be replayed, since there's no ephemeral
    contribution from the recipient.

    "e": Alice generates a new ephemeral key pair and stores it in the e
         variable, writes the ephemeral public key as cleartext into the
         message buffer, and hashes the public key along with the old h to
         derive a new h.

    "es": A DH is performed between the Alice's ephemeral key pair and the
          Bob's static key pair.  The result is hashed along with the old ck to
          derive a new ck and k, and n is set to zero.

Значение X зашифровано для обеспечения неразличимости и уникальности полезной нагрузки, что является необходимыми мерами противодействия DPI. Мы используем шифрование ChaCha20 для достижения этого, а не более сложные и медленные альтернативы, такие как elligator2. Асимметричное шифрование открытым ключом router Боба было бы слишком медленным. Шифрование ChaCha20 использует intro key Боба, опубликованный в базе данных сети.

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

Необработанное содержимое:

+----+----+----+----+----+----+----+----+
  |  Long Header bytes 0-15, ChaCha20     |
  +  encrypted with Bob intro key         +
  |    See Header Encryption KDF          |
  +----+----+----+----+----+----+----+----+
  |  Long Header bytes 16-31, ChaCha20    |
  +  encrypted with Bob intro key n=0     +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +       X, ChaCha20 encrypted           +
  |       with Bob intro key n=0          |
  +              (32 bytes)               +
  |                                       |
  +                                       +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |   ChaCha20 encrypted data             |
  +          (length varies)              +
  |  k defined in KDF for Session Request |
  +  n = 0                                +
  |  see KDF for associated data          |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

  X :: 32 bytes, ChaCha20 encrypted X25519 ephemeral key, little endian
          key: Bob's intro key
          n: 1
          data: 48 bytes (bytes 16-31 of the header, followed by encrypted X)

Незашифрованные данные (тег аутентификации Poly1305 не показан):

+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type| ver| id |flag|
  +----+----+----+----+----+----+----+----+
  |        Source Connection ID           |
  +----+----+----+----+----+----+----+----+
  |                 Token                 |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |                   X                   |
  +              (32 bytes)               +
  |                                       |
  +                                       +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |     Noise payload (block data)        |
  +          (length varies)              +
  |     see below for allowed blocks      |
  +----+----+----+----+----+----+----+----+


  Destination Connection ID :: Randomly generated by Alice

  id :: 1 byte, the network ID (currently 2, except for test networks)

  ver :: 2

  type :: 0

  flag :: 1 byte, unused, set to 0 for future compatibility

  Packet Number :: Random 4 byte number generated by Alice, ignored

  Source Connection ID :: Randomly generated by Alice,
                          must not be equal to Destination Connection ID

  Token :: 0 if not previously received from Bob

  X :: 32 bytes, X25519 ephemeral key, little endian

Payload

  • Блок DateTime
  • Блок Options (опциональный)
  • Блок Relay Tag Request (опциональный)
  • Блок Padding (опциональный)

Минимальный размер полезной нагрузки составляет 8 байт. Поскольку блок DateTime содержит только 7 байт, должен присутствовать как минимум один другой блок.

Notes

  • Уникальное значение X в начальном блоке ChaCha20 гарантирует, что шифротекст будет различным для каждой сессии.

  • Для обеспечения устойчивости к зондированию, Bob не должен отправлять сообщение Retry в ответ на сообщение Session Request, если только поля типа сообщения, версии протокола и сетевого ID в сообщении Session Request не являются действительными.

  • Bob должен отклонять соединения, где значение временной метки слишком сильно отклоняется от текущего времени. Назовём максимальную дельту времени “D”. Bob должен поддерживать локальный кэш ранее использованных значений handshake и отклонять дубликаты для предотвращения replay-атак. Значения в кэше должны иметь время жизни не менее 2*D. Значения кэша зависят от реализации, однако может использоваться 32-байтовое значение X (или его зашифрованный эквивалент). Отклонить, отправив сообщение Retry, содержащее нулевой token и блок завершения.

  • Эфемерные ключи Диффи-Хеллмана никогда не должны использоваться повторно во избежание криптографических атак, и повторное использование будет отклонено как replay-атака.

  • Опции “KE” и “auth” должны быть совместимы, т.е. общий секрет K должен иметь соответствующий размер. Если будет добавлено больше опций “auth”, это может неявно изменить значение флага “KE” для использования другого KDF или другого размера усечения.

  • Bob должен проверить, что эфемерный ключ Alice является действительной точкой на кривой здесь.

  • Заполнение должно быть ограничено разумным количеством. Bob может отклонять соединения с избыточным заполнением. Bob укажет свои параметры заполнения в Session Created. Рекомендации по мин/макс значениям TBD. Случайный размер от 0 до 31 байта минимум? (Распределение подлежит определению, см. Приложение A.) TODO ЕСЛИ НЕ принудительный минимальный размер пакета для PMTU.

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

  • Bob МОЖЕТ отправить сообщение Retry, содержащее нулевой токен и блок Termination с кодом причины расхождения часов, если временная метка в блоке DateTime слишком сильно расходится.

  • Предотвращение DoS-атак: DH является относительно ресурсоемкой операцией. Как и в случае с предыдущим протоколом NTCP, роутеры должны принимать все необходимые меры для предотвращения истощения CPU или соединений. Установите ограничения на максимальное количество активных соединений и максимальное количество установок соединений в процессе. Применяйте таймауты чтения (как на одно чтение, так и общее для “slowloris”). Ограничивайте повторные или одновременные соединения с одного источника. Ведите чёрные списки источников, которые регулярно терпят неудачу. Не отвечайте на сбой AEAD. Альтернативно, отвечайте сообщением Retry перед операцией DH и проверкой AEAD.

  • Поле “ver”: Общий протокол Noise, расширения и протокол SSU2, включая спецификации полезной нагрузки, указывающий на SSU2. Это поле может использоваться для обозначения поддержки будущих изменений.

  • Поле network ID используется для быстрой идентификации межсетевых соединений. Если это поле не совпадает с network ID узла Bob, Bob должен разорвать соединение и блокировать будущие подключения.

  • Bob должен отбросить сообщение, если Source Connection ID равен Destination Connection ID.

KDF for Session Created and Session Confirmed part 1


// take h saved from Session Request KDF
  // MixHash(ciphertext)
  h = SHA256(h || encrypted Noise payload from Session Request)

  // MixHash(header)
  h = SHA256(h || header)

  This is the "e" message pattern:

  // Bob's X25519 ephemeral keys
  besk = GENERATE_PRIVATE()
  bepk = DERIVE_PUBLIC(besk)

  // h is from KDF for Session Request
  // Bob ephemeral key Y
  // MixHash(bepk)
  h = SHA256(h || bepk);

  // h is used as the associated data for the AEAD in Session Created
  // Retain the Hash h for the Session Confirmed KDF

  End of "e" message pattern.

  This is the "ee" message pattern:

  // MixKey(DH())
  //[chainKey, k] = MixKey(sharedSecret)
  sharedSecret = DH(aesk, bepk) = DH(besk, aepk)
  keydata = HKDF(chainKey, sharedSecret, "", 64)
  chainKey = keydata[0:31]

  // AEAD parameters
  k = keydata[32:63]
  n = 0
  ad = h
  ciphertext = ENCRYPT(k, n, payload, ad)

  // retain the chaining key ck for Session Confirmed KDF

  End of "ee" message pattern.

  // Header encryption keys for this message
  // bik = Bob's intro key
  k_header_1 = bik
  k_header_2: See Session Request KDF above

  // Header protection keys for next message (Session Confirmed)
  k_header_1 = bik
  k_header_2 = HKDF(chainKey, ZEROLEN, "SessionConfirmed", 32)

Миграция соединений

Боб отправляет Алисе в ответ на сообщение Session Request. Алиса отвечает сообщением Session Confirmed. Размер: 80 + размер полезной нагрузки. Минимальный размер: 88

Содержимое Noise: эфемерный ключ Боба Y Полезная нагрузка Noise: DateTime, Address и другие блоки Максимальный размер полезной нагрузки: MTU - 108 (IPv4) или MTU - 128 (IPv6). Для MTU 1280: Максимальная полезная нагрузка составляет 1172 (IPv4) или 1152 (IPv6). Для MTU 1500: Максимальная полезная нагрузка составляет 1392 (IPv4) или 1372 (IPv6).

Свойства безопасности полезной нагрузки:

XK(s, rs):           Authentication   Confidentiality
    <- e, ee                  2                1

    Authentication: 2.
    Sender authentication resistant to key-compromise impersonation (KCI).
    The sender authentication is based on an ephemeral-static DH ("es" or "se")
    between the sender's static key pair and the recipient's ephemeral key pair.
    Assuming the corresponding private keys are secure, this authentication cannot be forged.

    Confidentiality: 1.
    Encryption to an ephemeral recipient.
    This payload has forward secrecy, since encryption involves an ephemeral-ephemeral DH ("ee").
    However, the sender has not authenticated the recipient,
    so this payload might be sent to any party, including an active attacker.


    "e": Bob generates a new ephemeral key pair and stores it in the e variable,
    writes the ephemeral public key as cleartext into the message buffer,
    and hashes the public key along with the old h to derive a new h.

    "ee": A DH is performed between the Bob's ephemeral key pair and the Alice's ephemeral key pair.
    The result is hashed along with the old ck to derive a new ck and k, and n is set to zero.

Значение Y зашифровано для обеспечения неразличимости и уникальности полезной нагрузки, что является необходимыми мерами противодействия DPI. Мы используем шифрование ChaCha20 для достижения этого, а не более сложные и медленные альтернативы, такие как elligator2. Асимметричное шифрование с использованием публичного ключа router’а Alice было бы слишком медленным. Шифрование ChaCha20 использует intro key Боба, опубликованный в базе данных сети.

Шифрование ChaCha20 предназначено только для противодействия DPI. Любая сторона, знающая intro key Боба, который опубликован в базе данных сети, и захватившая первые 32 байта Session Request, может расшифровать значение Y в этом сообщении.

Исходное содержимое:

+----+----+----+----+----+----+----+----+
  |  Long Header bytes 0-15, ChaCha20     |
  +  encrypted with Bob intro key and     +
  | derived key, see Header Encryption KDF|
  +----+----+----+----+----+----+----+----+
  |  Long Header bytes 16-31, ChaCha20    |
  +  encrypted with derived key n=0       +
  |  See Header Encryption KDF            |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +       Y, ChaCha20 encrypted           +
  |       with derived key n=0            |
  +              (32 bytes)               +
  |       See Header Encryption KDF       |
  +                                       +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |   ChaCha20 data                       |
  +   Encrypted and authenticated data    +
  |  length varies                        |
  +  k defined in KDF for Session Created +
  |  n = 0; see KDF for associated data   |
  +                                       +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

  Y :: 32 bytes, ChaCha20 encrypted X25519 ephemeral key, little endian
          key: Bob's intro key
          n: 1
          data: 48 bytes (bytes 16-31 of the header, followed by encrypted Y)

Незашифрованные данные (Poly1305 auth tag не показан):

+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type| ver| id |flag|
  +----+----+----+----+----+----+----+----+
  |        Source Connection ID           |
  +----+----+----+----+----+----+----+----+
  |                 Token                 |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |                  Y                    |
  +              (32 bytes)               +
  |                                       |
  +                                       +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |     Noise payload (block data)        |
  +          (length varies)              +
  |      see below for allowed blocks     |
  +----+----+----+----+----+----+----+----+

  Destination Connection ID :: The Source Connection ID
                               received from Alice in Session Request

  id :: 1 byte, the network ID (currently 2, except for test networks)

  ver :: 2

  type :: 0

  flag :: 1 byte, unused, set to 0 for future compatibility

  Packet Number :: Random 4 byte number generated by Bob, ignored

  Source Connection ID :: The Destination Connection ID
                          received from Alice in Session Request

  Token :: 0 (unused)

  Y :: 32 bytes, X25519 ephemeral key, little endian

Payload

  • Блок DateTime
  • Блок Address
  • Блок Relay Tag (опциональный)
  • Блок New Token (опциональный)
  • Блок First Packet Number (опциональный)
  • Блок Options (опциональный)
  • Блок Termination (не рекомендуется, вместо этого отправляйте в retry сообщении)
  • Блок Padding (опциональный)

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

Notes

  • Alice должна подтвердить, что эфемерный ключ Bob является действительной точкой на кривой здесь.

  • Отступы должны быть ограничены разумным количеством. Alice может отклонять соединения с чрезмерными отступами. Alice укажет свои опции отступов в Session Confirmed. Рекомендации по мин/макс TBD. Случайный размер от 0 до 31 байта минимум? (Распределение будет определено, см. Приложение A.) TODO ЕСЛИ НЕ применяется минимальный размер пакета для PMTU.

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

  • Alice должна отклонять соединения, где значение временной метки слишком сильно отличается от текущего времени. Назовем максимальную разность времени “D”. Alice должна поддерживать локальный кэш ранее использованных значений handshake и отклонять дубликаты для предотвращения атак повторного воспроизведения. Значения в кэше должны иметь время жизни не менее 2*D. Значения кэша зависят от реализации, однако может использоваться 32-байтовое значение Y (или его зашифрованный эквивалент).

  • Alice должна отбросить сообщение, если исходный IP-адрес и порт не соответствуют IP-адресу назначения и порту Session Request.

  • Алиса должна отбросить сообщение, если Destination и Source Connection IDs не соответствуют Source и Destination Connection IDs из Session Request.

  • Bob отправляет блок relay tag, если это запрошено Alice в Session Request.

Issues

  • Включить опции минимального/максимального заполнения здесь?

KDF for Session Confirmed part 1, using Session Created KDF


// take h saved from Session Created KDF
  // MixHash(ciphertext)
  h = SHA256(h || encrypted Noise payload from Session Created)

  // MixHash(header)
  h = SHA256(h || header)
  // h is used as the associated data for the AEAD in Session Confirmed part 1, below

  This is the "s" message pattern:

  // Alice's X25519 static keys
  ask = GENERATE_PRIVATE()
  apk = DERIVE_PUBLIC(ask)

  // AEAD parameters
  // k is from Session Request
  n = 1
  ad = h
  ciphertext = ENCRYPT(k, n++, apk, ad)

  // MixHash(ciphertext)
  h = SHA256(h || ciphertext);

  // h is used as the associated data for the AEAD in Session Confirmed part 2

  End of "s" message pattern.

  // Header encryption keys for this message
  See Session Confirmed part 2 below

KDF for Session Confirmed part 2


This is the "se" message pattern:

  // DH(ask, bepk) == DH(besk, apk)
  sharedSecret = DH(ask, bepk) = DH(besk, apk)

  // MixKey(DH())
  //[chainKey, k] = MixKey(sharedSecret)
  keydata = HKDF(chainKey, sharedSecret, "", 64)
  chainKey = keydata[0:31]

  // AEAD parameters
  k = keydata[32:63]
  n = 0
  ad = h
  ciphertext = ENCRYPT(k, n, payload, ad)

  // h from Session Confirmed part 1 is used as the associated data for the AEAD in Session Confirmed part 2
  // MixHash(ciphertext)
  h = SHA256(h || ciphertext);

  // retain the chaining key ck for the data phase KDF
  // retain the hash h for the data phase KDF

  End of "se" message pattern.

  // Header encryption keys for this message
  // bik = Bob's intro key
  k_header_1 = bik
  k_header_2: See Session Created KDF above

  // Header protection keys for data phase
  See data phase KDF below

SessionConfirmed (Type 2)

Алиса отправляет Бобу в ответ на сообщение Session Created. Боб немедленно отвечает сообщением Data, содержащим блок ACK. Размер: 80 + размер полезной нагрузки. Минимальный размер: Около 500 (минимальный размер блока router info составляет около 420 байт)

Содержимое Noise: статический ключ Alice Часть 1 полезной нагрузки Noise: Нет Часть 2 полезной нагрузки Noise: RouterInfo Alice и другие блоки Максимальный размер полезной нагрузки: MTU - 108 (IPv4) или MTU - 128 (IPv6). Для MTU 1280: Максимальная полезная нагрузка составляет 1172 (IPv4) или 1152 (IPv6). Для MTU 1500: Максимальная полезная нагрузка составляет 1392 (IPv4) или 1372 (IPv6).

Свойства безопасности полезной нагрузки:

XK(s, rs):           Authentication   Confidentiality
    -> s, se                  2                5

    Authentication: 2.
    Sender authentication resistant to key-compromise impersonation (KCI).  The
    sender authentication is based on an ephemeral-static DH ("es" or "se")
    between the sender's static key pair and the recipient's ephemeral key
    pair.  Assuming the corresponding private keys are secure, this
    authentication cannot be forged.

    Confidentiality: 5.
    Encryption to a known recipient, strong forward secrecy.  This payload is
    encrypted based on an ephemeral-ephemeral DH as well as an ephemeral-static
    DH with the recipient's static key pair.  Assuming the ephemeral private
    keys are secure, and the recipient is not being actively impersonated by an
    attacker that has stolen its static private key, this payload cannot be
    decrypted.

    "s": Alice writes her static public key from the s variable into the
    message buffer, encrypting it, and hashes the output along with the old h
    to derive a new h.

    "se": A DH is performed between the Alice's static key pair and the Bob's
    ephemeral key pair.  The result is hashed along with the old ck to derive a
    new ck and k, and n is set to zero.

Это содержит два ChaChaPoly фрейма. Первый — это зашифрованный статический публичный ключ Alice. Второй — это полезная нагрузка Noise: зашифрованная RouterInfo Alice, опциональные параметры и опциональное заполнение. Они используют разные ключи, поскольку функция MixKey() вызывается между ними.

Необработанное содержимое:

+----+----+----+----+----+----+----+----+
  |  Short Header 16 bytes, ChaCha20      |
  +  encrypted with Bob intro key and     +
  | derived key, see Header Encryption KDF|
  +----+----+----+----+----+----+----+----+
  |   ChaCha20 frame (32 bytes)           |
  +   Encrypted and authenticated data    +
  +   Alice static key S                  +
  | k defined in KDF for Session Created  |
  +     n = 1                             +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  + Length varies (remainder of packet)   +
  |                                       |
  +   ChaChaPoly frame                    +
  |   Encrypted and authenticated         |
  +   see below for allowed blocks        +
  |                                       |
  +     k defined in KDF for              +
  |     Session Confirmed part 2          |
  +     n = 0                             +
  |     see KDF for associated data       |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

  S :: 32 bytes, ChaChaPoly encrypted Alice's X25519 static key, little endian
       inside 48 byte ChaChaPoly frame

Незашифрованные данные (теги аутентификации Poly1305 не показаны):

+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type|frag|  flags  |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |              S                        |
  +       Alice static key                +
  |          (32 bytes)                   |
  +                                       +
  |                                       |
  +                                       +
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |        Noise Payload                  |
  +        (length varies)                +
  |        see below for allowed blocks   |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  Destination Connection ID :: As sent in Session Request,
                               or one received in Session Confirmed?

  Packet Number :: 0 always, for all fragments, even if retransmitted

  type :: 2

  frag :: 1 byte fragment info:
         bit order: 76543210 (bit 7 is MSB)
         bits 7-4: fragment number 0-14, big endian
         bits 3-0: total fragments 1-15, big endian

  flags :: 2 bytes, unused, set to 0 for future compatibility

  S :: 32 bytes, Alice's X25519 static key, little endian

Payload

  • Блок RouterInfo (должен быть первым блоком)
  • Блок Options (опциональный)
  • Блок New Token (опциональный)
  • Блок Relay Request (опциональный)
  • Блок Peer Test (опциональный)
  • Блок First Packet Number (опциональный)
  • Блоки I2NP, First Fragment или Follow-on Fragment (опциональные, но вероятно нет места)
  • Блок Padding (опциональный)

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

Notes

  • Боб должен выполнить обычную проверку Router Info. Убедиться, что тип подписи поддерживается, проверить подпись, проверить, что временная метка находится в допустимых пределах, и выполнить любые другие необходимые проверки. См. ниже примечания по обработке фрагментированных Router Info.

  • Боб должен проверить, что статический ключ Алисы, полученный в первом кадре, соответствует статическому ключу в Router Info. Боб должен сначала найти в Router Info адрес NTCP или SSU2 router с соответствующей опцией версии (v). См. разделы Published Router Info и Unpublished Router Info ниже. См. ниже примечания по обработке фрагментированных Router Infos.

  • Если у Bob есть более старая версия RouterInfo Alice в его netDb, проверить, что статический ключ в router info одинаков в обеих версиях, если присутствует, и если более старая версия младше XXX (см. время ротации ключей ниже)

  • Bob должен проверить, что статический ключ Alice является действительной точкой на кривой здесь.

  • Следует включить опции для указания параметров заполнения (padding).

  • При любой ошибке, включая сбой валидации AEAD, RI, DH, временной метки или ключа, Боб должен остановить дальнейшую обработку сообщений и закрыть соединение без ответа.

  • Содержимое фрейма части 2 сообщения 3: Формат этого фрейма такой же, как формат фреймов фазы данных, за исключением того, что длина фрейма отправляется Алисой в Session Request. См. ниже формат фрейма фазы данных. Фрейм должен содержать от 1 до 4 блоков в следующем порядке:

    1. Блок Router Info Алисы (обязательный)
    2. Блок Options (необязательный)
    3. Блоки I2NP (необязательные)
    4. Блок Padding (необязательный) Этот фрейм никогда не должен содержать никаких других типов блоков. TODO: что насчет relay и peer test?
  • Рекомендуется блок заполнения части 2 сообщения 3.

  • Может не быть места или быть только небольшое количество места для I2NP блоков, в зависимости от MTU и размера Router Info. НЕ включайте I2NP блоки, если Router Info фрагментирован. Простейшая реализация может заключаться в том, чтобы никогда не включать I2NP блоки в сообщение Session Confirmed и отправлять все I2NP блоки в последующих сообщениях Data. См. раздел блока Router Info ниже для максимального размера блока.

Session Confirmed Fragmentation

Сообщение Session Confirmed должно содержать полную подписанную Router Info от Alice, чтобы Bob мог выполнить несколько обязательных проверок:

  • Статический ключ “s” в RI соответствует статическому ключу в handshake
  • Ключ введения “i” в RI должен быть извлечен и действителен для использования в фазе данных
  • Подпись RI действительна

К сожалению, Router Info, даже при сжатии gzip в блоке RI, может превышать MTU. Поэтому Session Confirmed может быть фрагментирован на два или более пакетов. Это ЕДИНСТВЕННЫЙ случай в протоколе SSU2, когда AEAD-защищенная полезная нагрузка фрагментируется на два или более пакетов.

Заголовки для каждого пакета формируются следующим образом:

  • ВСЕ заголовки являются короткими заголовками с одним и тем же номером пакета 0
  • ВСЕ заголовки содержат поле “frag” с номером фрагмента и общим количеством фрагментов
  • Незашифрованный заголовок фрагмента 0 является ассоциированными данными (AD) для “jumbo” сообщения
  • Каждый заголовок шифруется, используя последние 24 байта данных в ЭТОМ пакете

Постройте серию пакетов следующим образом:

  • Создать один блок RI (фрагмент 0 из 1 в поле фрагментации блока RI). Мы не используем фрагментацию блоков RI, это было для альтернативного метода решения той же проблемы.
  • Создать “джамбо” полезную нагрузку с блоком RI и любыми другими блоками для включения
  • Вычислить общий размер данных (не включая заголовок), который является размером полезной нагрузки + 64 байта для статического ключа и двух MAC
  • Вычислить доступное пространство в каждом пакете, которое составляет MTU минус IP заголовок (20 или 40), минус UDP заголовок (8), минус короткий заголовок SSU2 (16). Общие накладные расходы на пакет составляют 44 (IPv4) или 64 (IPv6).
  • Вычислить количество пакетов.
  • Вычислить размер данных в последнем пакете. Он должен быть больше или равен 24 байтам, чтобы шифрование заголовка работало. Если он слишком мал, либо добавить блок заполнения, ИЛИ увеличить размер блока заполнения, если он уже присутствует, ИЛИ уменьшить размер одного из других пакетов, чтобы последний пакет был достаточно большим.
  • Создать нешифрованный заголовок для первого пакета с общим количеством фрагментов в поле фрагментации и зашифровать “джамбо” полезную нагрузку с помощью Noise, используя заголовок как AD, как обычно.
  • Разделить зашифрованный джамбо пакет на фрагменты
  • Добавить нешифрованный заголовок для каждого фрагмента 1-n
  • Зашифровать заголовок для каждого фрагмента 0-n. Каждый заголовок использует ТЕ ЖЕ k_header_1 и k_header_2, как определено выше в KDF Session Confirmed.
  • Передать все фрагменты

Процесс сборки:

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

  • Сохранить заголовок для фрагмента 0, поскольку он используется как Noise AD
  • Отбросить заголовки для других фрагментов перед повторной сборкой
  • Повторно собрать “jumbo” payload с заголовком для фрагмента 0 как AD, и расшифровать с помощью Noise
  • Проверить блок RI как обычно
  • Перейти к фазе данных и отправить ACK 0, как обычно

У Bob нет механизма для подтверждения отдельных фрагментов. Когда Bob получает все фрагменты, собирает их, расшифровывает и проверяет содержимое, Bob выполняет split() как обычно, переходит в фазу данных и отправляет ACK пакета номер 0.

Если Алиса не получает подтверждение ACK для пакета номер 0, она должна повторно передать все подтвержденные пакеты сессии как есть.

Примеры:

Для MTU 1500 через IPv6 максимальная полезная нагрузка составляет 1372, накладные расходы блока RI составляют 5, максимальный размер данных RI (сжатых gzip) составляет 1367 (при условии отсутствия других блоков). При использовании двух пакетов накладные расходы второго пакета составляют 64, поэтому он может содержать еще 1436 байт полезной нагрузки. Таким образом, двух пакетов достаточно для сжатого RI размером до 2803 байт.

Наибольший сжатый RI, наблюдаемый в текущей сети, составляет около 1400 байт; поэтому на практике двух фрагментов должно быть достаточно, даже при минимальном MTU 1280. Протокол позволяет использовать максимум 15 фрагментов.

Анализ безопасности:

Целостность и безопасность фрагментированного Session Confirmed такая же, как у нефрагментированного. Любое изменение любого фрагмента приведет к сбою Noise AEAD после пересборки. Заголовки фрагментов после фрагмента 0 используются только для идентификации фрагмента. Даже если атакующий на пути передачи получил бы ключ k_header_2, используемый для шифрования заголовка (что маловероятно, поскольку он выводится из handshake), это не позволило бы атакующему подставить валидный фрагмент.

KDF for data phase

Фаза данных использует заголовок для связанных данных.

KDF генерирует два ключа шифрования k_ab и k_ba из ключа цепочки ck, используя HMAC-SHA256(key, data) как определено в RFC 2104. Это функция split(), точно как определено в спецификации Noise.

// split()
  // chainKey = from handshake phase
  keydata = HKDF(chainKey, ZEROLEN, "", 64)
  k_ab = keydata[0:31]
  k_ba = keydata[32:63]

  // key is k_ab for Alice to Bob
  // key is k_ba for Bob to Alice

  keydata = HKDF(key, ZEROLEN, "HKDFSSU2DataKeys", 64)
  k_data = keydata[0:31]
  k_header_2 = keydata[32:63]


  // AEAD parameters
  k = k_data
  n = 4 byte packet number from header
  ad = 16 byte header, before header encryption
  ciphertext = ENCRYPT(k, n, payload, ad)

  // Header encryption keys for data phase
  // aik = Alice's intro key
  // bik = Bob's intro key
  k_header_1 = Receiver's intro key (aik or bik)
  k_header_2: from above

Data Message (Type 6)

Noise payload: Разрешены все типы блоков. Максимальный размер payload: MTU - 60 (IPv4) или MTU - 80 (IPv6). Для MTU 1500: Максимальный payload составляет 1440 (IPv4) или 1420 (IPv6).

Начиная со 2-й части Session Confirmed, все сообщения находятся внутри аутентифицированной и зашифрованной полезной нагрузки ChaChaPoly. Все отступы находятся внутри сообщения. Внутри полезной нагрузки находится стандартный формат с нулевым или большим количеством “блоков”. Каждый блок имеет однобайтовый тип и двухбайтовую длину. Типы включают дату/время, I2NP сообщение, опции, завершение и отступы.

Примечание: Боб может, но не обязан, отправить свою RouterInfo Алисе в качестве первого сообщения Алисе на этапе передачи данных.

Свойства безопасности полезной нагрузки:

XK(s, rs):           Authentication   Confidentiality
    <-                        2                5
    ->                        2                5

    Authentication: 2.
    Sender authentication resistant to key-compromise impersonation (KCI).
    The sender authentication is based on an ephemeral-static DH ("es" or "se")
    between the sender's static key pair and the recipient's ephemeral key pair.
    Assuming the corresponding private keys are secure, this authentication cannot be forged.

    Confidentiality: 5.
    Encryption to a known recipient, strong forward secrecy.
    This payload is encrypted based on an ephemeral-ephemeral DH as well as
    an ephemeral-static DH with the recipient's static key pair.
    Assuming the ephemeral private keys are secure, and the recipient is not being actively impersonated
    by an attacker that has stolen its static private key, this payload cannot be decrypted.

Notes

  • Роутер должен отбросить сообщение с ошибкой AEAD.
+----+----+----+----+----+----+----+----+
  |  Short Header 16 bytes, ChaCha20      |
  +  encrypted with intro key and         +
  |  derived key, see Data Phase KDF      |
  +----+----+----+----+----+----+----+----+
  |   ChaCha20 data                       |
  +   Encrypted and authenticated data    +
  |  length varies                        |
  +  k defined in Data Phase KDF          +
  |  n = packet number from header        |
  +                                       +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

Незашифрованные данные (тег аутентификации Poly1305 не показан):

+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type|    flags     |
  +----+----+----+----+----+----+----+----+
  |     Noise payload (block data)        |
  +          (length varies)              +
  |                                       |
  +----+----+----+----+----+----+----+----+

  Destination Connection ID :: As specified in session setup

  Packet Number :: 4 byte big endian integer

  type :: 6

  flags :: 3 bytes, unused, set to 0 for future compatibility

Notes

  • Минимальный размер полезной нагрузки составляет 8 байт. Это требование будет выполнено любым блоком ACK, I2NP, First Fragment или Follow-on Fragment. Если требование не выполняется, должен быть включен блок Padding.

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

KDF for Peer Test


// AEAD parameters
  // bik = Bob's intro key
  k = bik
  n = 4 byte packet number from header
  ad = 32 byte header, before header encryption
  ciphertext = ENCRYPT(k, n, payload, ad)

  // Header encryption keys for this message
  k_header_1 = bik
  k_header_2 = bik

Peer Test (Type 7)

Чарли отправляет Алисе, а Алиса отправляет Чарли, только для фаз Peer Test 5-7. Фазы Peer Test 1-4 должны отправляться внутри сессии с использованием блока Peer Test в Data сообщении. Смотрите разделы Peer Test Block и Peer Test Process ниже для получения дополнительной информации.

Размер: 48 + размер полезной нагрузки.

Полезная нагрузка Noise: См. ниже.

Необработанное содержимое:

+----+----+----+----+----+----+----+----+
  |  Long Header bytes 0-15, ChaCha20     |
  +  encrypted with Alice or Charlie      +
  |  intro key                            |
  +----+----+----+----+----+----+----+----+
  |  Long Header bytes 16-31, ChaCha20    |
  +  encrypted with Alice or Charlie      +
  |  intro key                            |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |   ChaCha20 encrypted data             |
  +          (length varies)              +
  |                                       |
  +  see KDF for key and n                +
  |  see KDF for associated data          |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

Незашифрованные данные (тег аутентификации Poly1305 не показан):

+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type| ver| id |flag|
  +----+----+----+----+----+----+----+----+
  |        Source Connection ID           |
  +----+----+----+----+----+----+----+----+
  |                 Token                 |
  +----+----+----+----+----+----+----+----+
  |    ChaCha20 payload (block data)      |
  +          (length varies)              +
  |    see below for allowed blocks       |
  +----+----+----+----+----+----+----+----+


  Destination Connection ID :: See below

  type :: 7

  ver :: 2

  id :: 1 byte, the network ID (currently 2, except for test networks)

  flag :: 1 byte, unused, set to 0 for future compatibility

  Packet Number :: Random number generated by Alice or Charlie

  Source Connection ID :: See below

  Token :: Randomly generated by Alice or Charlie, ignored

Длинный заголовок

  • Блок DateTime
  • Блок Address (обязателен для сообщений 6 и 7, см. примечание ниже)
  • Блок Peer Test
  • Блок Padding (опционально)

Минимальный размер полезной нагрузки составляет 8 байт. Поскольку блок Peer Test в общей сложности превышает это значение, требование выполняется только с этим блоком.

В сообщениях 5 и 7 блок Peer Test может быть идентичен блоку из внутрисессионных сообщений 3 и 4, содержащему соглашение, подписанное Чарли, или может быть перегенерирован. Подпись опциональна.

В сообщении 6 блок Peer Test может быть идентичен блоку из внутрисессионных сообщений 1 и 2, содержащему запрос, подписанный Alice, или может быть сгенерирован заново. Подпись необязательна.

Connection IDs: Два connection ID выводятся из тестового nonce. Для сообщений 5 и 7, отправленных от Charlie к Alice, Destination Connection ID представляет собой две копии 4-байтного big-endian тестового nonce, т.е. ((nonce « 32) | nonce). Source Connection ID является обратным для Destination Connection ID, т.е. ~((nonce « 32) | nonce). Для сообщения 6, отправленного от Alice к Charlie, поменяйте местами два connection ID.

Содержимое блока адреса:

  • В сообщении 5: Не требуется.
  • В сообщении 6: IP и порт Чарли, выбранные из RI Чарли.
  • В сообщении 7: Фактические IP и порт Алисы, с которых было получено сообщение 6.

KDF for Retry

Требование к сообщению Retry заключается в том, что Bob не должен расшифровывать сообщение Session Request для генерации сообщения Retry в ответ. Кроме того, это сообщение должно быстро генерироваться, используя только симметричное шифрование.


// AEAD parameters
  // bik = Bob's intro key
  k = bik
  n = 4 byte packet number from header
  ad = 32 byte header, before header encryption
  ciphertext = ENCRYPT(k, n, payload, ad)

  // Header encryption keys for this message
  k_header_1 = bik
  k_header_2 = bik

Retry (Type 9)

Bob отправляет Alice в ответ на сообщение Session Request или Token Request. Alice отвечает новым Session Request. Размер: 48 + размер полезной нагрузки.

Также служит как сообщение завершения (т.е. “Не повторять”), если включён блок завершения.

Полезная нагрузка Noise: См. ниже.

Необработанное содержимое:

+----+----+----+----+----+----+----+----+
  |  Long Header bytes 0-15, ChaCha20     |
  +  encrypted with Bob intro key         +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |  Long Header bytes 16-31, ChaCha20    |
  +  encrypted with Bob intro key         +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |   ChaCha20 encrypted data             |
  +          (length varies)              +
  |                                       |
  +  see KDF for key and n                +
  |  see KDF for associated data          |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

Незашифрованные данные (тег аутентификации Poly1305 не показан):

+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type| ver| id |flag|
  +----+----+----+----+----+----+----+----+
  |        Source Connection ID           |
  +----+----+----+----+----+----+----+----+
  |                 Token                 |
  +----+----+----+----+----+----+----+----+
  |    ChaCha20 payload (block data)      |
  +          (length varies)              +
  |    see below for allowed blocks       |
  +----+----+----+----+----+----+----+----+


  Destination Connection ID :: The Source Connection ID
                               received from Alice in Token Request
                               or Session Request

  Packet Number :: Random number generated by Bob

  type :: 9

  ver :: 2

  id :: 1 byte, the network ID (currently 2, except for test networks)

  flag :: 1 byte, unused, set to 0 for future compatibility

  Source Connection ID :: The Destination Connection ID
                          received from Alice in Token Request
                          or Session Request

  Token :: 8 byte unsigned integer, randomly generated by Bob, nonzero,
           or zero if session is rejected and a termination block is included

Короткий заголовок

  • Блок DateTime
  • Блок Address
  • Блок Options (опциональный)
  • Блок Termination (опциональный, если сессия отклонена)
  • Блок Padding (опциональный)

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

Нумерация идентификаторов соединений

  • Для обеспечения устойчивости к зондированию router не должен отправлять сообщение Retry в ответ на сообщение Session Request или Token Request, если поля типа сообщения, версии протокола и идентификатора сети в сообщении Request не являются действительными.

  • Чтобы ограничить масштаб любой атаки усиления, которая может быть проведена с использованием поддельных адресов источника, сообщение Retry не должно содержать большого количества дополнительных данных. Рекомендуется, чтобы размер сообщения Retry не превышал трёхкратный размер сообщения, на которое оно отвечает. Альтернативно, используйте простой метод, такой как добавление случайного количества дополнительных данных в диапазоне 1-64 байта.

KDF for Token Request

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


// AEAD parameters
  // bik = Bob's intro key
  k = bik
  n = 4 byte packet number from header
  ad = 32 byte header, before header encryption
  ciphertext = ENCRYPT(k, n, payload, ad)

  // Header encryption keys for this message
  k_header_1 = bik
  k_header_2 = bik

Token Request (Type 10)

Алиса отправляет Бобу. Боб отвечает сообщением Retry. Размер: 48 + размер полезной нагрузки.

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

Полезная нагрузка Noise: См. ниже.

Необработанное содержимое:

+----+----+----+----+----+----+----+----+
  |  Long Header bytes 0-15, ChaCha20     |
  +  encrypted with Bob intro key         +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |  Long Header bytes 16-31, ChaCha20    |
  +  encrypted with Bob intro key         +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |   ChaCha20 encrypted data             |
  +          (length varies)              +
  |                                       |
  +  see KDF for key and n                +
  |  see KDF for associated data          |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

Незашифрованные данные (тег аутентификации Poly1305 не показан):

+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type| ver| id |flag|
  +----+----+----+----+----+----+----+----+
  |        Source Connection ID           |
  +----+----+----+----+----+----+----+----+
  |                 Token                 |
  +----+----+----+----+----+----+----+----+
  |    ChaCha20 payload (block data)      |
  +          (length varies)              +
  |    see below for allowed blocks       |
  +----+----+----+----+----+----+----+----+


  Destination Connection ID :: Randomly generated by Alice

  Packet Number :: Random number generated by Alice

  type :: 10

  ver :: 2

  id :: 1 byte, the network ID (currently 2, except for test networks)

  flag :: 1 byte, unused, set to 0 for future compatibility

  Source Connection ID :: Randomly generated by Alice,
                          must not be equal to Destination Connection ID

  Token :: zero

Нумерация пакетов

  • Блок DateTime
  • Блок Padding

Минимальный размер полезной нагрузки составляет 8 байт.

Привязка заголовка

  • Для обеспечения устойчивости к зондированию router не должен отправлять сообщение Retry в ответ на сообщение Token Request, если только поля типа сообщения, версии протокола и идентификатора сети в сообщении Token Request не являются валидными.

  • Это НЕ стандартное Noise сообщение и не является частью handshake. Оно не связано с сообщением Session Request, кроме как через идентификаторы соединения.

  • При большинстве ошибок, включая AEAD, или очевидный replay Bob должен остановить дальнейшую обработку сообщений и отбросить сообщение без ответа.

  • Bob должен отклонять соединения, где значение временной метки слишком сильно отличается от текущего времени. Назовем максимальную разность времени “D”. Bob должен поддерживать локальный кэш ранее использованных значений рукопожатия и отклонять дубликаты, чтобы предотвратить атаки повтора. Значения в кэше должны иметь время жизни не менее 2*D. Значения кэша зависят от реализации, однако может использоваться 32-байтное значение X (или его зашифрованный эквивалент).

  • Bob МОЖЕТ отправить сообщение Retry, содержащее нулевой токен и блок Termination с кодом причины расхождения часов, если временная метка в блоке DateTime слишком сильно смещена.

  • Минимальный размер: TBD, те же правила, что и для Session Created?

KDF for Hole Punch

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


// AEAD parameters
  // aik = Alice's intro key
  k = aik
  n = 4 byte packet number from header
  ad = 32 byte header, before header encryption
  ciphertext = ENCRYPT(k, n, payload, ad)

  // Header encryption keys for this message
  k_header_1 = aik
  k_header_2 = aik

Hole Punch (Type 11)

Чарли отправляет Алисе в ответ на полученное от Боба сообщение Relay Intro. Алиса отвечает новым Session Request. Размер: 48 + размер полезной нагрузки.

Noise payload: См. ниже.

Необработанное содержимое:

+----+----+----+----+----+----+----+----+
  |  Long Header bytes 0-15, ChaCha20     |
  +  encrypted with Alice intro key       +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |  Long Header bytes 16-31, ChaCha20    |
  +  encrypted with Alice intro key       +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |   ChaCha20 encrypted data             |
  +          (length varies)              +
  |                                       |
  +  see KDF for key and n                +
  |  see KDF for associated data          |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

Незашифрованные данные (тег аутентификации Poly1305 не показан):

+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type| ver| id |flag|
  +----+----+----+----+----+----+----+----+
  |        Source Connection ID           |
  +----+----+----+----+----+----+----+----+
  |                 Token                 |
  +----+----+----+----+----+----+----+----+
  |    ChaCha20 payload (block data)      |
  +          (length varies)              +
  |    see below for allowed blocks       |
  +----+----+----+----+----+----+----+----+


  Destination Connection ID :: See below

  Packet Number :: Random number generated by Charlie

  type :: 11

  ver :: 2

  id :: 1 byte, the network ID (currently 2, except for test networks)

  flag :: 1 byte, unused, set to 0 for future compatibility

  Source Connection ID :: See below

  Token :: 8 byte unsigned integer, randomly generated by Charlie, nonzero.

Шифрование заголовков

  • Блок DateTime
  • Блок Address
  • Блок Relay Response
  • Блок Padding (опционально)

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

Идентификаторы соединения: Два идентификатора соединения извлекаются из relay nonce. Destination Connection ID представляет собой две копии 4-байтового relay nonce в формате big-endian, то есть ((nonce « 32) | nonce). Source Connection ID является инверсией Destination Connection ID, то есть ~((nonce « 32) | nonce).

Alice должна игнорировать токен в заголовке. Токен, который следует использовать в Session Request, находится в блоке Relay Response.

Noise Payload

Каждая полезная нагрузка Noise содержит ноль или более “блоков”.

Это использует тот же формат блоков, как определено в спецификациях NTCP2 и ECIES. Отдельные типы блоков определяются по-разному. Эквивалентный термин в QUIC RFC 9000 — это “фреймы”.

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

Соображения безопасности

В зашифрованной полезной нагрузке содержится один или несколько блоков. Блок представляет собой простой формат Tag-Length-Value (TLV). Каждый блок содержит однобайтовый идентификатор, двухбайтовую длину и ноль или более байтов данных. Этот формат идентичен используемому в NTCP2 и ECIES, однако определения блоков отличаются.

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

(Тег аутентификации Poly1305 не показан):

+----+----+----+----+----+----+----+----+
  |blk |  size   |       data             |
  +----+----+----+                        +
  |                                       |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+
  |blk |  size   |       data             |
  +----+----+----+                        +
  |                                       |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+
  ~               .   .   .               ~

  blk :: 1 byte, see below
  size :: 2 bytes, big endian, size of data to follow, 0 - TBD
  data :: the data

Шифрование заголовка использует последние 24 байта пакета в качестве IV для двух операций ChaCha20. Поскольку все пакеты заканчиваются 16-байтовым MAC, это требует, чтобы все полезные нагрузки пакетов были минимум 8 байт. Если полезная нагрузка иначе не соответствует этому требованию, должен быть включен блок Padding.

Максимальная полезная нагрузка ChaChaPoly варьируется в зависимости от типа сообщения, MTU и типа IPv4 или IPv6 адреса. Максимальная полезная нагрузка составляет MTU - 60 для IPv4 и MTU - 80 для IPv6. Максимальные данные полезной нагрузки составляют MTU - 63 для IPv4 и MTU - 83 для IPv6. Верхний предел составляет около 1440 байт для IPv4, 1500 MTU, сообщение Data. Максимальный общий размер блока равен максимальному размеру полезной нагрузки. Максимальный размер одного блока равен максимальному общему размеру блока. Тип блока составляет 1 байт. Длина блока составляет 2 байта. Максимальный размер данных одного блока равен максимальному размеру одного блока минус 3.

Примечания:

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

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

Типы блоков:

Payload Block TypeType NumberBlock Length
DateTime07
Options115+
Router Info2varies
I2NP Message3varies
First Fragment4varies
Follow-on Fragment5varies
Termination69 typ.
Relay Request7varies
Relay Response8varies
Relay Intro9varies
Peer Test10varies
Next Nonce11TBD
ACK12varies
Address139 or 21
reserved14
Relay Tag Request153
Relay Tag167
New Token1715
Path Challenge18varies
Path Response19varies
First Packet Number207
Congestion214
reserved for experimental features224-253
Padding254varies
reserved for future extension255

Block Ordering Rules

В Session Confirmed блок Router Info должен быть первым.

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

Block Specifications

Функция вывода ключа для шифрования заголовка

Для синхронизации времени:

+----+----+----+----+----+----+----+
  | 0  |    4    |     timestamp     |
  +----+----+----+----+----+----+----+

  blk :: 0
  size :: 2 bytes, big endian, value = 4
  timestamp :: Unix timestamp, unsigned seconds.
               Wraps around in 2106

Примечания:

  • В отличие от SSU 1, в SSU 2 нет отметки времени в заголовке пакета для фазы данных.
  • Реализации должны периодически отправлять блоки DateTime в фазе данных.
  • Реализации должны округлять до ближайшей секунды, чтобы предотвратить смещение часов в сети.

Валидация заголовков

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

Блок опций будет иметь переменную длину.

+----+----+----+----+----+----+----+----+
  | 1  |  size   |tmin|tmax|rmin|rmax|tdmy|
  +----+----+----+----+----+----+----+----+
  |tdmy|  rdmy   |  tdelay |  rdelay |    |
  ~----+----+----+----+----+----+----+    ~
  |              more_options             |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 1
  size :: 2 bytes, big endian, size of options to follow, 12 bytes minimum

  tmin, tmax, rmin, rmax :: requested padding limits
      tmin and rmin are for desired resistance to traffic analysis.
      tmax and rmax are for bandwidth limits.
      tmin and tmax are the transmit limits for the router sending this options block.
      rmin and rmax are the receive limits for the router sending this options block.
      Each is a 4.4 fixed-point float representing 0 to 15.9375
      (or think of it as an unsigned 8-bit integer divided by 16.0).
      This is the ratio of padding to data. Examples:
      Value of 0x00 means no padding
      Value of 0x01 means add 6 percent padding
      Value of 0x10 means add 100 percent padding
      Value of 0x80 means add 800 percent (8x) padding
      Alice and Bob will negotiate the minimum and maximum in each direction.
      These are guidelines, there is no enforcement.
      Sender should honor receiver's maximum.
      Sender may or may not honor receiver's minimum, within bandwidth constraints.

  tdmy: Max dummy traffic willing to send, 2 bytes big endian, bytes/sec average
  rdmy: Requested dummy traffic, 2 bytes big endian, bytes/sec average
  tdelay: Max intra-message delay willing to insert, 2 bytes big endian, msec average
  rdelay: Requested intra-message delay, 2 bytes big endian, msec average

  Padding distribution specified as additional parameters?
  Random delay specified as additional parameters?

  more_options :: Format TBD

Проблемы с опциями:

  • Согласование опций TBD.

RouterInfo

Передать RouterInfo Алисы Бобу. Используется только в полезной нагрузке части 2 Session Confirmed. Не использовать в фазе данных; вместо этого используйте I2NP сообщение DatabaseStore.

Минимальный размер: Около 420 байт, если только идентичность router и подпись в router info не сжимаемы, что маловероятно.

ПРИМЕЧАНИЕ: Блок Router Info никогда не фрагментируется. Поле frag всегда имеет значение 0/1. См. раздел “Фрагментация Session Confirmed” выше для получения дополнительной информации.

+----+----+----+----+----+----+----+----+
  | 2  |  size   |flag|frag|              |
  +----+----+----+----+----+              +
  |                                       |
  +       Router Info fragment            +
  | (Alice RI in Session Confirmed)       |
  + (Alice, Bob, or third-party           +
  |  RI in data phase)                    |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 2
  size :: 2 bytes, big endian, 2 + fragment size
  flag :: 1 byte flags
         bit order: 76543210 (bit 7 is MSB)
         bit 0: 0 for local store, 1 for flood request
         bit 1: 0 for uncompressed, 1 for gzip compressed
         bits 7-2: Unused, set to 0 for future compatibility
  frag :: 1 byte fragment info:
         bit order: 76543210 (bit 7 is MSB)
         bits 7-4: fragment number, always 0
         bits 3-0: total fragments, always 1, big endian

  routerinfo :: Alice's or Bob's RouterInfo

Примечания:

  • Router Info опционально сжимается с помощью gzip, что указывается битом флага 1. Это отличается от NTCP2, где он никогда не сжимается, и от сообщения DatabaseStore, где он всегда сжимается. Сжатие является опциональным, поскольку обычно оно приносит мало пользы для небольших Router Info, где мало сжимаемого содержимого, но очень полезно для больших Router Info с несколькими сжимаемыми Router Address. Сжатие рекомендуется, если оно позволяет Router Info поместиться в один пакет Session Confirmed без фрагментации.

  • Максимальный размер первого или единственного фрагмента в сообщении Session Confirmed: MTU - 113 для IPv4 или MTU - 133 для IPv6. Предполагая стандартный MTU в 1500 байт и отсутствие других блоков в сообщении, 1387 для IPv4 или 1367 для IPv6. 97% текущих router info меньше 1367 без сжатия gzip. 99.9% текущих router info меньше 1367 при сжатии gzip. Предполагая минимальный MTU в 1280 байт и отсутствие других блоков в сообщении, 1167 для IPv4 или 1147 для IPv6. 94% текущих router info меньше 1147 без сжатия gzip. 97% текущих router info меньше 1147 при сжатии gzip.

  • Байт frag теперь не используется, блок Router Info никогда не фрагментируется. Байт frag должен быть установлен в fragment 0, total fragments 1. См. раздел Session Confirmed Fragmentation выше для получения дополнительной информации.

  • Flooding не должен запрашиваться, если в RouterInfo нет опубликованных RouterAddresses. Принимающий router не должен выполнять flood RouterInfo, если в нём нет опубликованных RouterAddresses.

  • Этот протокол не предоставляет подтверждение о том, что RouterInfo была сохранена или распространена через flood. Если требуется подтверждение, и получатель является floodfill, отправитель должен вместо этого отправить стандартное I2NP DatabaseStoreMessage с токеном ответа.

I2NP Message

Полное I2NP сообщение с модифицированным заголовком.

Это использует те же 9 байт для заголовка I2NP, как и в NTCP2 (тип, идентификатор сообщения, короткий срок истечения).

+----+----+----+----+----+----+----+----+
  | 3  |  size   |type|    msg id         |
  +----+----+----+----+----+----+----+----+
  |   short exp       |     message       |
  +----+----+----+----+                   +
  |                                       |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 3
  size :: 2 bytes, big endian, size of type + msg id + exp + message to follow
          I2NP message body size is (size - 9).
  type :: 1 byte, I2NP msg type, see I2NP spec
  msg id :: 4 bytes, big endian, I2NP message ID
  short exp :: 4 bytes, big endian, I2NP message expiration, Unix timestamp, unsigned seconds.
               Wraps around in 2106
  message :: I2NP message body

Примечания:

  • Это тот же самый 9-байтный формат заголовка I2NP, используемый в NTCP2.

  • Это точно такой же формат, как и блок First Fragment, но тип блока указывает, что это полное сообщение.

  • Максимальный размер, включая 9-байтный заголовок I2NP, составляет MTU - 63 для IPv4 и MTU - 83 для IPv6.

ChaCha20/Poly1305

Первый фрагмент (фрагмент #0) I2NP сообщения с модифицированным заголовком.

Это использует те же 9 байт для заголовка I2NP, как в NTCP2 (тип, идентификатор сообщения, короткое время истечения).

Общее количество фрагментов не указано.

+----+----+----+----+----+----+----+----+
  | 4  |  size   |type|    msg id         |
  +----+----+----+----+----+----+----+----+
  |   short exp       |                   |
  +----+----+----+----+                   +
  |          partial message              |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 4
  size :: 2 bytes, big endian, size of data to follow
          Fragment size is (size - 9).
  type :: 1 byte, I2NP msg type, see I2NP spec
  msg id :: 4 bytes, big endian, I2NP message ID
  short exp :: 4 bytes, big endian, I2NP message expiration, Unix timestamp, unsigned seconds.
               Wraps around in 2106
  message :: Partial I2NP message body, bytes 0 - (size - 10)

Примечания:

  • Это тот же 9-байтовый формат заголовка I2NP, используемый в NTCP2.

  • Это точно такой же формат, как блок I2NP Message, но тип блока указывает, что это первый фрагмент сообщения.

  • Длина частичного сообщения должна быть больше нуля.

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

  • Максимальный размер включая 9-байтовый I2NP заголовок составляет MTU - 63 для IPv4 и MTU - 83 для IPv6.

Примечания

Дополнительный фрагмент (номер фрагмента больше нуля) I2NP сообщения.

+----+----+----+----+----+----+----+----+
  | 5  |  size   |frag|    msg id         |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |          partial message              |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 5
  size :: 2 bytes, big endian, size of data to follow
          Fragment size is (size - 5).
  frag :: Fragment info:
          Bit order: 76543210 (bit 7 is MSB)
          bits 7-1: fragment number 1 - 127 (0 not allowed)
          bit 0: isLast (1 = true)
  msg id :: 4 bytes, big endian, I2NP message ID
  message :: Partial I2NP message body

Примечания:

  • Длина частичного сообщения должна быть больше нуля.

  • Как и в SSU 1, рекомендуется отправлять последний фрагмент первым, чтобы получатель знал общее количество фрагментов и мог эффективно выделить буферы для приёма.

  • Как и в SSU 1, максимальный номер фрагмента составляет 127, но практический предел составляет 63 или меньше. Реализации могут ограничивать максимум до того, что практично для максимального размера I2NP сообщения около 64 КБ, что составляет около 55 фрагментов с минимальным MTU 1280. См. раздел Максимальный размер I2NP сообщения ниже.

  • Максимальный размер частичного сообщения (не включая frag и message id) составляет MTU - 68 для IPv4 и MTU - 88 для IPv6.

Обработка ошибок AEAD

Разорвать соединение. Это должен быть последний блок без заполнения в полезной нагрузке.

+----+----+----+----+----+----+----+----+
  | 6  |  size   |    valid data packets  |
  +----+----+----+----+----+----+----+----+
      received   | rsn|     addl data     |
  +----+----+----+----+                   +
  ~               .   .   .               ~
  +----+----+----+----+----+----+----+----+

  blk :: 6
  size :: 2 bytes, big endian, value = 9 or more
  valid data packets received :: The number of valid packets received
                                (current receive nonce value)
                                0 if error occurs in handshake phase
                                8 bytes, big endian
  rsn :: reason, 1 byte:
         0: normal close or unspecified
         1: termination received
         2: idle timeout
         3: router shutdown
         4: data phase AEAD failure
         5: incompatible options
         6: incompatible signature type
         7: clock skew
         8: padding violation
         9: AEAD framing error
         10: payload format error
         11: Session Request error
         12: Session Created error
         13: Session Confirmed error
         14: Timeout
         15: RI signature verification fail
         16: s parameter missing, invalid, or mismatched in RouterInfo
         17: banned
         18: bad token
         19: connection limits
         20: incompatible version
         21: wrong net ID
         22: replaced by new session
  addl data :: optional, 0 or more bytes, for future expansion, debugging,
               or reason text.
               Format unspecified and may vary based on reason code.

Примечания:

  • Не все причины могут фактически использоваться, зависит от реализации. Большинство сбоев обычно приведет к отбрасыванию сообщения, а не к завершению. См. примечания в разделах сообщений handshake выше. Дополнительные перечисленные причины предназначены для согласованности, логирования, отладки или в случае изменения политики.
  • Рекомендуется включать ACK блок вместе с Termination блоком.
  • В фазе данных, по любой причине, отличной от “termination received”, узел должен ответить termination блоком с причиной “termination received”.

RelayRequest

Отправляется в сообщении Data внутри сессии, от Alice к Bob. См. раздел Relay Process ниже.

+----+----+----+----+----+----+----+----+
  |  7 |  size   |flag|       nonce       |
  +----+----+----+----+----+----+----+----+
  |     relay tag     |     timestamp     |
  +----+----+----+----+----+----+----+----+
  | ver| asz|AlicePort|  Alice IP address |
  +----+----+----+----+----+----+----+----+
  |              signature                |
  +            length varies              +
  |         64 bytes for Ed25519          |
  ~                                       ~
  |                 . . .                 |
  +----+----+----+----+----+----+----+----+

  blk :: 7
  size :: 2 bytes, big endian, size of data to follow
  flag :: 1 byte flags, Unused, set to 0 for future compatibility

  The data below here is covered
  by the signature, and Bob forwards it unmodified.

  nonce :: 4 bytes, randomly generated by Alice
  relay tag :: 4 bytes, the itag from Charlie's RI
  timestamp :: Unix timestamp, unsigned seconds.
               Wraps around in 2106
  ver ::  1 byte SSU version to be used for the introduction:
         1: SSU 1
         2: SSU 2
  asz :: 1 byte endpoint (port + IP) size (6 or 18)
  AlicePort :: 2 byte Alice's port number, big endian
  Alice IP :: (asz - 2) byte representation of Alice's IP address,
              network byte order
  signature :: length varies, 64 bytes for Ed25519.
               Signature of prologue, Bob's hash,
               and signed data above, as signed by
               Alice.

Примечания:

  • IP-адрес всегда включен (в отличие от SSU 1) и может отличаться от IP, используемого для сессии.

Подпись:

Алиса подписывает запрос и включает его в этот блок; Боб пересылает его в блоке Relay Intro к Чарли. Алгоритм подписи: Подписать следующие данные ключом подписи router-а Алисы:

  • prologue: 16 байт “RelayRequestData”, не завершается нулём (не включается в сообщение)
  • bhash: 32-байтовый хеш router’а Боба (не включается в сообщение)
  • chash: 32-байтовый хеш router’а Чарли (не включается в сообщение)
  • nonce: 4-байтовый nonce
  • relay tag: 4-байтовый relay tag
  • timestamp: 4-байтовая временная метка (в секундах)
  • ver: 1-байтовая версия SSU
  • asz: 1-байтовый размер endpoint’а (порт + IP) (6 или 18)
  • AlicePort: 2-байтовый номер порта Алисы
  • Alice IP: (asz - 2)-байтовый IP-адрес Алисы

KDF для начального ChainKey

Отправляется в сообщении Data внутри сессии, от Чарли к Бобу или от Боба к Алисе, И в сообщении Hole Punch от Чарли к Алисе. См. раздел Relay Process ниже.

+----+----+----+----+----+----+----+----+
  |  8 |  size   |flag|code|    nonce
  +----+----+----+----+----+----+----+----+
       |     timestamp     | ver| csz|Char
  +----+----+----+----+----+----+----+----+
   Port|   Charlie IP addr |              |
  +----+----+----+----+----+              +
  |              signature                |
  +            length varies              +
  |         64 bytes for Ed25519          |
  ~                                       ~
  |                 . . .                 |
  +----+----+----+----+----+----+----+----+
  |                 Token                 |
  +----+----+----+----+----+----+----+----+

  blk :: 8
  size :: 2 bytes, 6
  flag :: 1 byte flags, Unused, set to 0 for future compatibility
  code :: 1 byte status code:
         0: accept
         1: rejected by Bob, reason unspecified
         2: rejected by Bob, Charlie is banned
         3: rejected by Bob, limit exceeded
         4: rejected by Bob, signature failure
         5: rejected by Bob, relay tag not found
         6: rejected by Bob, Alice RI not found
         7-63: other rejected by Bob codes TBD
         64: rejected by Charlie, reason unspecified
         65: rejected by Charlie, unsupported address
         66: rejected by Charlie, limit exceeded
         67: rejected by Charlie, signature failure
         68: rejected by Charlie, Alice is already connected
         69: rejected by Charlie, Alice is banned
         70: rejected by Charlie, Alice is unknown
         71-127: other rejected by Charlie codes TBD
         128: reject, source and reason unspecified
         129-255: other reject codes TBD

  The data below is covered by the signature if the code is 0 (accept).
  Bob forwards it unmodified.

  nonce :: 4 bytes, as received from Bob or Alice

  The data below is present only if the code is 0 (accept).

  timestamp :: Unix timestamp, unsigned seconds.
               Wraps around in 2106
  ver ::  1 byte SSU version to be used for the introduction:
         1: SSU 1
         2: SSU 2
  csz :: 1 byte endpoint (port + IP) size (0 or 6 or 18)
         may be 0 for some rejection codes
  CharliePort :: 2 byte Charlie's port number, big endian
                 not present if csz is 0
  Charlie IP :: (csz - 2) byte representation of Charlie's IP address,
                network byte order
                not present if csz is 0
  signature :: length varies, 64 bytes for Ed25519.
               Signature of prologue, Bob's hash,
               and signed data above, as signed by
               Charlie.
               Not present if rejected by Bob.
  token :: Token generated by Charlie for Alice to use
           in the Session Request.
           Only present if code is 0 (accept)

Примечания:

Токен должен быть немедленно использован Алисой в Session Request.

Подпись:

Если Чарли согласен (код ответа 0) или отклоняет (код ответа 64 или выше), Чарли подписывает ответ и включает его в этот блок; Боб пересылает его в блоке Relay Response Алисе. Алгоритм подписи: Подписать следующие данные ключом подписи router’а Чарли:

  • prologue: 16 байт “RelayAgreementOK”, без null-завершения (не включается в сообщение)
  • bhash: 32-байтный хеш router’а Bob’а (не включается в сообщение)
  • nonce: 4-байтный nonce
  • timestamp: 4-байтная временная метка (секунды)
  • ver: 1 байт версии SSU
  • csz: 1 байт размера endpoint’а (порт + IP) (0 или 6 или 18)
  • CharliePort: 2-байтный номер порта Charlie (отсутствует, если csz равно 0)
  • Charlie IP: (csz - 2) байт IP-адреса Charlie (отсутствует, если csz равно 0)

Если Боб отклоняет запрос (код ответа 1-63), Боб подписывает ответ и включает его в этот блок. Алгоритм подписи: Подписать следующие данные ключом подписи router’а Боба:

  • prologue: 16 байт “RelayAgreementOK”, без null-терминатора (не включается в сообщение)
  • bhash: 32-байтный router hash Боба (не включается в сообщение)
  • nonce: 4-байтный nonce
  • timestamp: 4-байтный timestamp (секунды)
  • ver: 1 байт версии SSU
  • csz: 1 байт = 0

KDF для Session Request

Отправляется в сообщении Data внутри сессии, от Bob к Charlie. См. раздел Процесс ретрансляции ниже.

Должен предшествовать блок RouterInfo или блок I2NP сообщения DatabaseStore (или фрагмент), содержащий Router Info Алисы, либо в той же полезной нагрузке (если есть место), либо в предыдущем сообщении.

+----+----+----+----+----+----+----+----+
  |  9 |  size   |flag|                   |
  +----+----+----+----+                   +
  |                                       |
  +                                       +
  |         Alice Router Hash             |
  +             32 bytes                  +
  |                                       |
  +                   +----+----+----+----+
  |                   |      nonce        |
  +----+----+----+----+----+----+----+----+
  |     relay tag     |     timestamp     |
  +----+----+----+----+----+----+----+----+
  | ver| asz|AlicePort|  Alice IP address |
  +----+----+----+----+----+----+----+----+
  |              signature                |
  +            length varies              +
  |         64 bytes for Ed25519          |
  ~                                       ~
  |                 . . .                 |
  +----+----+----+----+----+----+----+----+

  blk :: 9
  size :: 2 bytes, big endian, size of data to follow
  flag :: 1 byte flags, Unused, set to 0 for future compatibility
  hash :: Alice's 32-byte router hash,

  The data below here is covered
  by the signature, as received from Alice in the Relay Request,
  and Bob forwards it unmodified.

  nonce :: 4 bytes, as received from Alice
  relay tag :: 4 bytes, the itag from Charlie's RI
  timestamp :: Unix timestamp, unsigned seconds.
               Wraps around in 2106
  ver ::  1 byte SSU version to be used for the introduction:
         1: SSU 1
         2: SSU 2
  asz :: 1 byte endpoint (port + IP) size (6 or 18)
  AlicePort :: 2 byte Alice's port number, big endian
  Alice IP :: (asz - 2) byte representation of Alice's IP address,
              network byte order
  signature :: length varies, 64 bytes for Ed25519.
               Signature of prologue, Bob's hash,
               and signed data above, as signed by
               Alice.

Примечания:

  • Для IPv4 IP-адрес Alice всегда составляет 4 байта, поскольку Alice пытается подключиться к Charlie через IPv4. IPv6 поддерживается, и IP-адрес Alice может составлять 16 байт.

  • Для IPv4 это сообщение должно быть отправлено через установленное IPv4 соединение, поскольку это единственный способ для Боба узнать IPv4 адрес Чарли, чтобы вернуть его Алисе в RelayResponse_. IPv6 поддерживается, и это сообщение может быть отправлено через установленное IPv6 соединение.

  • Любой SSU адрес, опубликованный с introducers, должен содержать “4” или “6” в опции “caps”.

Подпись:

Алиса подписывает запрос, и Боб пересылает его в этом блоке Чарли. Алгоритм верификации: Проверьте следующие данные с помощью ключа подписи router’а Алисы:

  • prologue: 16 байт “RelayRequestData”, не завершается нулем (не включается в сообщение)
  • bhash: 32-байтный хеш router’а Боба (не включается в сообщение)
  • chash: 32-байтный хеш router’а Чарли (не включается в сообщение)
  • nonce: 4-байтный nonce
  • relay tag: 4-байтный relay tag
  • timestamp: 4-байтный timestamp (секунды)
  • ver: 1-байтная версия SSU
  • asz: 1-байтный размер endpoint (порт + IP) (6 или 18)
  • AlicePort: 2-байтный номер порта Алисы
  • Alice IP: (asz - 2) байт IP-адреса Алисы

PeerTest

Отправляется либо в сообщении Data внутри сессии, либо в сообщении Peer Test вне сессии. См. раздел “Процесс тестирования пиров” ниже.

Для сообщения 2 должен предшествовать блок RouterInfo или блок I2NP сообщения DatabaseStore (или фрагмент), содержащий Router Info Алисы, либо в той же полезной нагрузке (если есть место), либо в предыдущем сообщении.

Для сообщения 4, если relay принят (код причины 0), должен предшествовать блок RouterInfo или блок I2NP сообщения DatabaseStore (или фрагмент), содержащий Router Info Чарли, либо в той же полезной нагрузке (если есть место), либо в предыдущем сообщении.

+----+----+----+----+----+----+----+----+
  | 10 |  size   | msg|code|flag|         |
  +----+----+----+----+----+----+         +
  | Alice router hash (message 2 only)    |
  +             or                        +
  | Charlie router hash (message 4 only)  |
  + or all zeros if rejected by Bob       +
  | Not present in messages 1,3,5,6,7     |
  +                             +----+----+
  |                             | ver|
  +----+----+----+----+----+----+----+----+
     nonce       |     timestamp     | asz|
  +----+----+----+----+----+----+----+----+
  |AlicePort|  Alice IP address |         |
  +----+----+----+----+----+----+         +
  |              signature                |
  +            length varies              +
  |         64 bytes for Ed25519          |
  ~                                       ~
  |                 . . .                 |
  +----+----+----+----+----+----+----+----+

  blk :: 10
  size :: 2 bytes, big endian, size of data to follow
  msg :: 1 byte message number 1-7
  code :: 1 byte status code:
         0: accept
         1: rejected by Bob, reason unspecified
         2: rejected by Bob, no Charlie available
         3: rejected by Bob, limit exceeded
         4: rejected by Bob, signature failure
         5: rejected by Bob, address unsupported
         6-63: other rejected by Bob codes TBD
         64: rejected by Charlie, reason unspecified
         65: rejected by Charlie, unsupported address
         66: rejected by Charlie, limit exceeded
         67: rejected by Charlie, signature failure
         68: rejected by Charlie, Alice is already connected
         69: rejected by Charlie, Alice is banned
         70: rejected by Charlie, Alice is unknown
         70-127: other rejected by Charlie codes TBD
         128: reject, source and reason unspecified
         129-255: other reject codes TBD
         reject codes only allowed in messages 3 and 4
  flag :: 1 byte flags, Unused, set to 0 for future compatibility
  hash :: Alice's or Charlie's 32-byte router hash,
          only present in messages 2 and 4.
          All zeros (fake hash) in message 4 if rejected by Bob.

  For messages 1-4, the data below here is covered
  by the signature, if present, and Bob forwards it unmodified.

  ver :: 1 byte SSU version:
         1: SSU 1 (not supported)
         2: SSU 2 (required)
  nonce :: 4 byte test nonce, big endian
  timestamp :: Unix timestamp, unsigned seconds.
               Wraps around in 2106
  asz :: 1 byte endpoint (port + IP) size (6 or 18)
  AlicePort :: 2 byte Alice's port number, big endian
  Alice IP :: (asz - 2) byte representation of Alice's IP address,
              network byte order
  signature :: length varies, 64 bytes for Ed25519.
               Signature of prologue, Bob's hash,
               and signed data above, as signed by
               Alice or Charlie.
               Only present for messages 1-4.
               Optional in message 5-7.

Примечания:

  • В отличие от SSU 1, сообщение 1 должно включать IP-адрес и порт Alice.

  • Тестирование IPv6-адресов поддерживается, и связь Alice-Bob и Alice-Charlie может осуществляться через IPv6, если Bob и Charlie указывают поддержку с помощью возможности ‘B’ в своих опубликованных IPv6-адресах. См. Proposal 126 для получения подробной информации.

Алиса отправляет запрос Бобу, используя существующую сессию через транспорт (IPv4 или IPv6), который она желает протестировать. Когда Боб получает запрос от Алисы через IPv4, Боб должен выбрать Чарли, который анонсирует IPv4-адрес. Когда Боб получает запрос от Алисы через IPv6, Боб должен выбрать Чарли, который анонсирует IPv6-адрес. Фактическая коммуникация между Бобом и Чарли может происходить через IPv4 или IPv6 (т.е. независимо от типа адреса Алисы).

  • Сообщения 1-4 должны содержаться в Data сообщении в существующей сессии.

  • Bob должен отправить RI Alice к Charlie перед отправкой сообщения 2.

  • Боб должен отправить RI Чарли Алисе до отправки сообщения 4, если принято (код причины 0).

  • Сообщения 5-7 должны содержаться в сообщении Peer Test вне сессии.

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

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

Подписи:

Алиса подписывает запрос и включает его в сообщение 1; Боб пересылает его в сообщении 2 Чарли. Чарли подписывает ответ и включает его в сообщение 3; Боб пересылает его в сообщении 4 Алисе. Алгоритм подписи: Подпишите или проверьте следующие данные с помощью ключа подписи Алисы или Чарли:

  • prologue: 16 байт “PeerTestValidate”, не завершается нулем (не включается в сообщение)
  • bhash: 32-байтовый хеш router’а Bob (не включается в сообщение)
  • ahash: 32-байтовый хеш router’а Alice (Используется только в подписи для сообщений 3 и 4; не включается в сообщения 3 или 4)
  • ver: 1 байт версии SSU
  • nonce: 4 байта тестового nonce
  • timestamp: 4 байта временной метки (секунды)
  • asz: 1 байт размера конечной точки (порт + IP) (6 или 18)
  • AlicePort: 2 байта номера порта Alice
  • Alice IP: (asz - 2) байт IP-адреса Alice

Полезная нагрузка

TODO только если мы ротируем ключи

+----+----+----+----+----+----+----+----+
  | 11 |  size   |      TBD               |
  +----+----+----+                        +
  |                                       |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 11
  size :: 2 bytes, big endian, size of data to follow

Примечания

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

Данная схема адаптирована и упрощена из QUIC. Цели проектирования следующие:

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

Кодирование, описанное ниже, достигает этих целей проектирования путем отправки номера старшего бита, который установлен в 1, вместе с дополнительными последовательными битами младше этого, которые также установлены в 1. После этого, если есть место, одного или более “диапазонов”, указывающих количество последовательных битов 0 и последовательных битов 1 младше этого. См. QUIC RFC 9000 раздел 13.2.3 для дополнительной информации.

+----+----+----+----+----+----+----+----+
  | 12 |  size   |    Ack Through    |acnt|
  +----+----+----+----+----+----+----+----+
  |  range  |  range  |     .   .   .     |
  +----+----+----+----+                   +
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 12
  size :: 2 bytes, big endian, size of data to follow,
          5 minimum
  ack through :: highest packet number acked
  acnt :: number of acks lower than ack through also acked,
          0-255
  range :: If present,
           1 byte nack count followed by 1 byte ack count,
           0-255 each

Примеры:

Мы хотим отправить ACK только для пакета 10:

  • Ack Through: 10
  • acnt: 0
  • диапазоны не включены

Мы хотим отправить ACK только для пакетов 8-10:

  • Ack Through: 10
  • acnt: 2
  • диапазоны не включены

Мы хотим ACK 10 9 8 6 5 2 1 0, и NACK 7 4 3. Кодирование ACK Block:

  • Ack Through: 10
  • acnt: 2 (ack 9 8)
  • range: 1 2 (nack 7, ack 6 5)
  • range: 2 3 (nack 4 3, ack 2 1 0)

Примечания:

  • Диапазоны могут отсутствовать. Максимальное количество диапазонов не указано, может быть столько, сколько поместится в пакет.
  • Range nack может быть равен нулю при подтверждении более 255 последовательных пакетов.
  • Range ack может быть равен нулю при отклонении более 255 последовательных пакетов.
  • Range nack и ack не могут быть одновременно равны нулю.
  • После последнего диапазона пакеты не подтверждаются и не отклоняются. Длина блока подтверждений и обработка старых подтверждений/отклонений зависит от отправителя блока подтверждений. См. разделы о подтверждениях ниже для обсуждения.
  • Ack through должен быть наивысшим номером полученного пакета, и любые пакеты с большими номерами не были получены. Однако в ограниченных ситуациях он может быть меньше, например, при подтверждении одного пакета, который “заполняет пробел”, или при упрощенной реализации, которая не поддерживает состояние всех полученных пакетов. Выше наивысшего полученного пакеты не подтверждаются и не отклоняются, но после нескольких блоков подтверждений может быть уместно перейти в режим быстрой повторной передачи.
  • Этот формат является упрощенной версией формата из QUIC. Он разработан для эффективного кодирования большого количества ACK, вместе с всплесками NACK.
  • Блоки ACK используются для подтверждения пакетов фазы данных. Они должны включаться только для пакетов фазы данных в рамках сессии.

Address

2-байтный порт и 4- или 16-байтный IP-адрес. Адрес Alice, отправленный Alice от Bob, или адрес Bob, отправленный Bob от Alice.

+----+----+----+----+----+----+----+----+
  | 13 | 6 or 18 |   Port  | IP Address    
  +----+----+----+----+----+----+----+----+
       |
  +----+

  blk :: 13
  size :: 2 bytes, big endian, 6 or 18
  port :: 2 bytes, big endian
  ip :: 4 byte IPv4 or 16 byte IPv6 address,
        big endian (network byte order)

Relay Tag Request

Это может быть отправлено Alice в сообщении Session Request, Session Confirmed или Data. Не поддерживается в сообщении Session Created, поскольку Bob еще не имеет RI Alice и не знает, поддерживает ли Alice relay. Также, если Bob получает входящее соединение, ему, вероятно, не нужны introducers (за исключением, возможно, другого типа ipv4/ipv6).

При отправке в Session Request, Bob может ответить Relay Tag в сообщении Session Created, или может выбрать подождать до получения RouterInfo от Alice в Session Confirmed для проверки личности Alice перед ответом в Data сообщении. Если Bob не желает выполнять ретрансляцию для Alice, он не отправляет блок Relay Tag.

+----+----+----+
  | 15 |    0    |
  +----+----+----+

  blk :: 15
  size :: 2 bytes, big endian, value = 0

Полезная нагрузка

Это может быть отправлено Бобом в сообщении Session Confirmed или Data в ответ на Relay Tag Request от Алисы.

Когда Relay Tag Request отправляется в Session Request, Bob может ответить с Relay Tag в сообщении Session Created, или может выбрать подождать до получения RouterInfo от Alice в Session Confirmed, чтобы проверить личность Alice перед ответом в Data сообщении. Если Bob не желает выполнять relay для Alice, он не отправляет блок Relay Tag.

+----+----+----+----+----+----+----+
  | 16 |    4    |    relay tag      |
  +----+----+----+----+----+----+----+

  blk :: 16
  size :: 2 bytes, big endian, value = 4
  relay tag :: 4 bytes, big endian, nonzero

Примечания

Для последующего подключения. Обычно включается в сообщения Session Created и Session Confirmed. Также может быть отправлен повторно в сообщении Data долгоживущей сессии, если предыдущий токен истекает.

+----+----+----+----+----+----+----+----+
  | 17 |   12    |     expires       |
  +----+----+----+----+----+----+----+----+
                  token              |
  +----+----+----+----+----+----+----+

  blk :: 17
  size :: 2 bytes, big endian, value = 12
  expires :: Unix timestamp, unsigned seconds.
             Wraps around in 2106
  token :: 8 bytes, big endian

Проблемы

Ping с произвольными данными, которые должны быть возвращены в Path Response, используется как keep-alive или для проверки изменения IP/порта.

+----+----+----+----+----+----+----+----+
  | 18 |  size   |    Arbitrary Data      |
  +----+----+----+                        +
  |                                       |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 18
  size :: 2 bytes, big endian, size of data to follow
  data :: Arbitrary data to be returned in a Path Response
          length as selected by sender

Примечания:

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

Path Response

Pong с данными, полученными в Path Challenge, как ответ на Path Challenge, используется для поддержания соединения или для валидации изменения IP/порта.

+----+----+----+----+----+----+----+----+
  | 19 |  size   |                        |
  +----+----+----+                        +
  |    Data received in Path Challenge    |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 19
  size :: 2 bytes, big endian, size of data to follow
  data :: As received in a Path Challenge

First Packet Number

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

Не полностью определено, в настоящее время не поддерживается.

+----+----+----+----+----+----+----+
  | 20 |  size   |  First pkt number |
  +----+----+----+----+----+----+----+

  blk :: 20
  size :: 4
  pkt num :: The first packet number to be sent in the data phase

Congestion

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

Это позволяет исключить любую информацию о перегрузках из часто используемых блоков I2NP, First Fragment, Followon Fragment и ACK, где нет места для выделенных флагов. Хотя в заголовке пакета Data есть три байта неиспользуемых флагов, это также обеспечивает ограниченное пространство для расширяемости и более слабую защиту шифрования.

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

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

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

+----+----+----+----+
  | 21 |  size   |flag|
  +----+----+----+----+

  blk :: 21
  size :: 1 (or more if extended)
  flag :: 1 byte flags
         bit order: 76543210 (bit 7 is MSB)
         bit 0: 1 to request immediate ack
         bit 1: 1 for explicit congestion notification (ECN)
         bits 7-2: Unused, set to 0 for future compatibility

Полезная нагрузка

Это предназначено для заполнения внутри полезных нагрузок AEAD. Заполнение для всех сообщений находится внутри полезных нагрузок AEAD.

Заполнение должно приблизительно соответствовать согласованным параметрам. Bob отправил свои запрошенные параметры tx/rx min/max в Session Created. Alice отправила свои запрошенные параметры tx/rx min/max в Session Confirmed. Обновлённые опции могут быть отправлены во время фазы передачи данных. См. информацию о блоке опций выше.

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

+----+----+----+----+----+----+----+----+
  |254 |  size   |      padding           |
  +----+----+----+                        +
  |                                       |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 254
  size :: 2 bytes, big endian, size of padding to follow
  padding :: random data

Примечания:

  • Размер = 0 разрешен.

  • Стратегии заполнения подлежат определению.

  • Минимальное заполнение подлежит определению.

  • Полезные нагрузки, содержащие только заполнение, разрешены.

  • Заполнение по умолчанию подлежит определению.

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

  • См. блок опций для параметров мин./макс. заполнения

  • Не превышать MTU. Если необходимо больше заполнения, отправьте несколько сообщений.

  • Ответ router’а на нарушение согласованного заполнения зависит от реализации.

  • Длина padding должна определяться либо для каждого сообщения отдельно с учетом оценок распределения длины, либо должны добавляться случайные задержки. Эти контрмеры должны быть включены для противодействия DPI, поскольку размеры сообщений иначе выдавали бы, что I2P трафик передается транспортным протоколом. Точная схема padding является областью будущих исследований, Приложение A документа NTCP2 предоставляет дополнительную информацию по этой теме.

Replay Prevention

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

Сообщения Token Request, Retry, Session Request, Session Created, Hole Punch и внесессионные Peer Test должны содержать блоки DateTime.

И Алиса, и Боб проверяют, что время для этих сообщений находится в пределах допустимого отклонения (рекомендуется +/- 2 минуты). Для “устойчивости к зондированию” Боб не должен отвечать на сообщения Token Request или Session Request, если отклонение недопустимо, поскольку эти сообщения могут быть атакой повтора или зондирования.

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

Система токенов значительно минимизирует воздействие повторно отправленных сообщений Session Request. Поскольку токены могут использоваться только один раз, повторно отправленное сообщение Session Request никогда не будет иметь действительный токен. Боб может выбрать отклонение дублированных сообщений Session Request, даже если смещение действительно, через фильтр Блума или другой механизм. Однако размер и CPU-затраты на ответ сообщением Retry невелики. В худшем случае отправка сообщения Retry может аннулировать ранее отправленный токен.

Дублированные сообщения Session Created и Session Confirmed не будут проходить валидацию, поскольку состояние рукопожатия Noise не будет находиться в правильном состоянии для их расшифровки. В худшем случае узел может повторно передать Session Confirmed в ответ на очевидно дублированное сообщение Session Created.

Повторные сообщения Hole Punch и Peer Test должны иметь незначительное влияние или не влиять вообще.

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

Handshake Retransmission

Session Request

Если Alice не получает Session Created или Retry:

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

Рекомендуемые интервалы повторной передачи: 1.25, 2.5 и 5 секунд (1.25, 3.75 и 8.75 секунд после первой отправки). Рекомендуемый таймаут: всего 15 секунд

Session Created

Если Bob не получает Session Confirmed:

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

Рекомендуемые интервалы повторной передачи: 1, 2 и 4 секунды (1, 3 и 7 секунд после первой отправки). Рекомендуемый таймаут: 12 секунд общее время

Session Confirmed

В SSU 1 Alice не переходит к фазе данных, пока не получит первый пакет данных от Bob. Это делает SSU 1 установкой соединения в два round-trip.

Для SSU 2, рекомендуемые интервалы повторной передачи Session Confirmed: 1,25, 2,5 и 5 секунд (1,25, 3,75 и 8,75 секунд после первой отправки).

Существует несколько альтернатив. Все имеют 1 RTT:

  1. Алиса предполагает, что Session Confirmed было получено, отправляет сообщения данных немедленно, никогда не передает Session Confirmed повторно. Пакеты данных, полученные не по порядку (до Session Confirmed), будут нерасшифруемыми, но будут переданы повторно. Если Session Confirmed потеряно, все отправленные сообщения данных будут отброшены.

  2. Как в 1), отправлять сообщения с данными немедленно, но также повторно передавать Session Confirmed до получения сообщения с данными.

  3. Мы могли бы использовать IK вместо XK, поскольку он имеет только два сообщения в handshake, но он использует дополнительный DH (4 вместо 3).

Рекомендуемая реализация — это вариант 2). Alice должен сохранить информацию, необходимую для повторной передачи сообщения Session Confirmed. Alice также должен повторно передать все сообщения Data после того, как сообщение Session Confirmed будет повторно передано.

При ретрансляции Session Confirmed сохраняйте те же идентификаторы источника и соединения, эфемерный ключ и номер пакета 1. Или просто сохраните зашифрованный пакет. Номер пакета не должен увеличиваться, поскольку это изменит значение цепного хеша, которое является входным параметром для функции split().

Боб может сохранить (поставить в очередь) сообщения с данными, полученные до сообщения Session Confirmed. Ни ключи защиты заголовков, ни ключи дешифрования недоступны до получения сообщения Session Confirmed, поэтому Боб не знает, что это сообщения с данными, но это можно предположить. После получения сообщения Session Confirmed Боб может расшифровать и обработать сообщения с данными из очереди. Если это слишком сложно, Боб может просто отбросить нерасшифровываемые сообщения с данными, так как Алиса их ретранслирует.

Примечание: Если подтверждающие сессию пакеты потеряны, Bob повторно передаст session created. Заголовок session created не сможет быть расшифрован с помощью intro key Alice, поскольку он установлен с intro key Bob (если только не выполняется резервная расшифровка с intro key Bob). Bob может немедленно повторно передать подтверждающие сессию пакеты, если они ранее не были подтверждены, и получен нерасшифровываемый пакет.

Token Request

Если Алиса не получает Retry:

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

Рекомендуемые интервалы повторной передачи: 3 и 6 секунд (3 и 9 секунд после первой отправки). Рекомендуемый таймаут: 15 секунд общее время

Retry

Если Bob не получает Session Request:

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

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

Если получено второе сообщение Session Request с другим, но по-прежнему недействительным токеном, отбросить ожидающую сессию и не отвечать.

При повторной отправке сообщения Retry: Сохраняйте те же идентификаторы источника и соединения, а также токен. Реализация может сгенерировать новый случайный номер пакета и зашифровать новый пакет; Или может повторно использовать тот же номер пакета или просто сохранить и повторно передать тот же зашифрованный пакет.

Total Timeout

Рекомендуемый общий таймаут для handshake составляет 20 секунд.

Duplicates and Error Handling

Дубликаты трех сообщений Noise handshake Session Request, Session Created и Session Confirmed должны быть обнаружены до выполнения MixHash() заголовка. Хотя обработка Noise AEAD предположительно не удастся после этого, хэш handshake уже будет поврежден.

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

Tokens

Токен в заголовке Session Request используется для защиты от DoS-атак, предотвращения подмены адреса источника и обеспечения устойчивости к атакам повторного воспроизведения.

Если Bob не принимает токен в сообщении Session Request, Bob НЕ расшифровывает сообщение, поскольку это требует дорогостоящей операции DH. Bob просто отправляет сообщение Retry с новым токеном.

Если затем получено последующее сообщение Session Request с этим токеном, Боб приступает к расшифровке этого сообщения и продолжает процедуру handshake.

Токен должен быть случайно сгенерированным 8-байтным значением, если генератор токена сохраняет значения и связанные IP и порт (в памяти или постоянно). Генератор не может создавать непрозрачное значение, например, используя SipHash (с секретным ключом K0, K1) от IP, порта и текущего часа или дня, для создания токенов, которые не нужно сохранять в памяти, поскольку этот метод затрудняет отклонение повторно используемых токенов и replay-атак.

Токены могут использоваться только один раз. Токен, отправленный от Bob к Alice в сообщении Retry, должен быть использован немедленно и истекает через несколько секунд. Токен, отправленный в блоке New Token в установленной сессии, может быть использован в последующем соединении, и он истекает в время, указанное в этом блоке. Время истечения указывается отправителем; рекомендуемые значения составляют минимум один час, максимум несколько часов.

Если IP-адрес или порт router’а изменяется, он должен удалить все сохранённые токены (как входящие, так и исходящие) для старого IP-адреса или порта, поскольку они больше не действительны. Токены могут опционально сохраняться при перезапуске router’а, в зависимости от реализации. Принятие неистёкшего токена не гарантируется; если Bob забыл или удалил свои сохранённые токены, он отправит Retry сообщение Alice. Router может выбрать ограничение хранения токенов и удалять самые старые сохранённые токены, даже если они ещё не истекли.

Блоки New Token могут отправляться от Алисы к Бобу или от Боба к Алисе. Обычно они отправляются один раз, во время или вскоре после установления сессии. Token может быть повторно отправлен до или после истечения срока действия с новым временем истечения, или может быть отправлен новый token. Роутеры должны предполагать, что действителен только последний полученный token; нет требования хранить несколько входящих или исходящих token для одного и того же IP/порта.

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

Если любой из узлов мигрирует на новый IP или порт во время сессии (см. раздел Connection Migration), любые ранее обмененные токены становятся недействительными, и необходимо обменяться новыми токенами.

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

I2NP Message Fragmentation

Различия от SSU 1

Примечание: Как и в SSU 1, начальный фрагмент не содержит информации об общем количестве фрагментов или общей длине. Последующие фрагменты не содержат информации о своем смещении. Это предоставляет отправителю гибкость фрагментации “на лету” на основе доступного места в пакете. (Java I2P этого не делает; он выполняет “предварительную фрагментацию” перед отправкой первого фрагмента) Однако это возлагает на получателя бремя хранения фрагментов, полученных не по порядку, и задержки сборки до получения всех фрагментов.

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

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

I2NP Message Duplication

Этот протокол НЕ предотвращает полностью дублированную доставку I2NP сообщений. Дубликаты на IP-уровне или атаки повторного воспроизведения будут обнаружены на уровне SSU2, поскольку каждый номер пакета может использоваться только один раз.

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

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

Congestion Control

Данное предложение определяет протокол для нумерации пакетов и ACK блоков. Это обеспечивает достаточную информацию в реальном времени для передатчика, чтобы реализовать эффективный и отзывчивый алгоритм контроля перегрузки, при этом позволяя гибкость и инновации в данной реализации. Этот раздел обсуждает цели реализации и предоставляет рекомендации. Общие руководящие принципы можно найти в RFC 9002. См. также RFC 6298 для руководства по таймерам повторной передачи.

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

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

  • Тест узла
  • Запрос/представление/ответ ретранслятора
  • Вызов/ответ пути

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

Packet Numbers

В SSU 1 подтверждения (ACK) и отрицательные подтверждения (NACK) содержали номера сообщений I2NP и битовые маски фрагментов. Передатчики отслеживали статус подтверждения исходящих сообщений (и их фрагментов) и повторно передавали фрагменты по мере необходимости.

В SSU 2 ACK и NACK содержат номера пакетов. Передатчики должны поддерживать структуру данных с сопоставлением номеров пакетов и их содержимого. Когда пакет получает ACK или NACK, передатчик должен определить, какие I2NP сообщения и фрагменты находились в этом пакете, чтобы решить, что повторно передавать.

Session Confirmed ACK

Боб отправляет ACK пакета 0, который подтверждает сообщение Session Confirmed и позволяет Алисе перейти к фазе передачи данных, а также отбросить большое сообщение Session Confirmed, сохраненное для возможной повторной передачи. Это заменяет DeliveryStatusMessage, отправляемое Бобом в SSU 1.

Боб должен отправить ACK как можно скорее после получения сообщения Session Confirmed. Небольшая задержка (не более 50 мс) допустима, поскольку по крайней мере одно сообщение Data должно прибыть почти сразу после сообщения Session Confirmed, чтобы ACK мог подтвердить как сообщение Session Confirmed, так и сообщение Data. Это предотвратит необходимость повторной передачи сообщения Session Confirmed со стороны Боба.

Generating ACKs

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

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

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

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

Пакеты данных внутри сессии, содержащие любой блок ЗА ИСКЛЮЧЕНИЕМ следующих, требуют подтверждения:

  • Блок ACK
  • Блок адреса
  • Блок DateTime
  • Блок заполнения
  • Блок завершения
  • Любые блоки в том же пакете, что и блок завершения
  • Другие?

Пакеты, содержащие блок Termination с причиной, отличной от “termination received”, подтверждаются пакетом, содержащим блок Termination с “termination received”.

Пакеты вне сессии, включая сообщения handshake и сообщения peer test 5-7, имеют свои собственные механизмы подтверждения. См. ниже.

Handshake ACKs

Это особые случаи:

  • Запрос токена неявно подтверждается через Retry
  • Запрос сессии неявно подтверждается через Session Created или Retry
  • Retry неявно подтверждается через Session Request
  • Session Created неявно подтверждается через Session Confirmed
  • Session Confirmed должен быть подтвержден немедленно

Sending ACK Blocks

ACK блоки используются для подтверждения пакетов фазы данных. Они должны включаться только для пакетов фазы данных в рамках сессии.

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

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

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

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

Конечная точка, которая отправляет только ACK блоки, не будет получать подтверждения от своего партнера, если эти подтверждения не включены в пакеты с блоками, требующими подтверждения. Конечная точка должна отправлять ACK блок с другими блоками, когда есть новые пакеты, требующие подтверждения, которые нужно подтвердить. Когда нужно подтвердить только пакеты, не требующие подтверждения, конечная точка МОЖЕТ выбрать не отправлять ACK блок с исходящими блоками до тех пор, пока не будет получен пакет, требующий подтверждения.

Конечная точка, которая отправляет только пакеты, не требующие подтверждения, может иногда добавлять к таким пакетам блок, требующий подтверждения, чтобы гарантировать получение acknowledgment. В таком случае конечная точка НЕ ДОЛЖНА отправлять блок, требующий подтверждения, во всех пакетах, которые иначе не требовали бы подтверждения, чтобы избежать бесконечного цикла обратной связи подтверждений.

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

  • Когда полученный пакет имеет номер пакета меньше, чем у другого пакета, требующего подтверждения, который уже был получен

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

  • Когда установлен флаг ack-immediate в заголовке пакета

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

ACK Frequency

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

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

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

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

Получатель может обработать несколько доступных пакетов перед тем, как определить, следует ли отправить блок ACK в ответ. В общем случае, получатель не должен задерживать ACK более чем на RTT / 6, или максимум 150 мс.

Флаг ack-immediate в заголовке пакета данных является запросом на то, чтобы получатель отправил подтверждение вскоре после получения, вероятно, в течение нескольких миллисекунд. В общем случае получатель не должен задерживать немедленное ACK более чем на RTT / 16 или максимум 5 мс.

Immediate ACK Flag

Получатель не знает размер окна отправки отправителя и поэтому не знает, как долго задерживать отправку ACK. Флаг немедленного ACK в заголовке пакета данных является важным способом поддержания максимальной пропускной способности путем минимизации эффективного RTT. Флаг немедленного ACK находится в байте 13 заголовка, бит 0, т.е. (header[13] & 0x01). Когда установлен, запрашивается немедленный ACK. См. раздел о коротком заголовке выше для подробностей.

Существует несколько возможных стратегий, которые отправитель может использовать для определения того, когда устанавливать флаг immediate-ack:

  • Устанавливается один раз каждые N пакетов, для некоторого малого N
  • Устанавливается на последнем пакете в серии пакетов
  • Устанавливается когда окно отправки почти заполнено, например заполнено более чем на 2/3
  • Устанавливается на всех пакетах с повторно переданными фрагментами

Флаги немедленного ACK должны быть необходимы только для пакетов данных, содержащих I2NP сообщения или фрагменты сообщений.

ACK Block Size

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

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

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

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

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

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

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

Limiting Ranges by Tracking ACK Blocks

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

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

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

Congestion

I2P транспорты не гарантируют доставку I2NP сообщений в порядке отправки. Поэтому потеря Data сообщения, содержащего одно или несколько I2NP сообщений или фрагментов, НЕ препятствует доставке других I2NP сообщений; блокировки начала очереди не происходит. Реализации должны продолжать отправку новых сообщений во время фазы восстановления после потерь, если окно отправки это позволяет.

Retransmission

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

Window

TBD. Общие рекомендации можно найти в RFC 9002.

Connection Migration

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

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

Миграция соединения — это процесс, при котором проверяется новая исходная конечная точка (IP+порт), предотвращая изменения, которые не были проверены. Этот процесс представляет собой упрощенную версию процесса, определенного в QUIC RFC 9000. Данный процесс определен только для фазы передачи данных сессии. Миграция не разрешена во время хэндшейка. Все пакеты хэндшейка должны быть проверены как отправленные с того же IP и порта, что и ранее отправленные и полученные пакеты. Другими словами, IP и порт узла должны оставаться постоянными во время хэндшейка.

Threat Model

(Адаптировано из QUIC RFC 9000)

Примечания

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

Фрагментация подтвержденной сессии

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

Off-Path Packet Forwarding

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

Privacy Implications

QUIC RFC 9000 определяет изменение идентификаторов соединения при смене сетевых путей. Использование стабильного идентификатора соединения на нескольких сетевых путях позволило бы пассивному наблюдателю коррелировать активность между этими путями. Конечная точка, которая перемещается между сетями, может не желать, чтобы её активность коррелировалась каким-либо субъектом, кроме её партнёра. Однако QUIC не шифрует идентификаторы соединения в заголовке. SSU2 это делает, поэтому утечка конфиденциальности потребовала бы от пассивного наблюдателя также иметь доступ к базе данных сети для получения ключа представления, необходимого для расшифровки идентификатора соединения. Даже с ключом представления это не является сильной атакой, и мы не изменяем идентификаторы соединения после миграции в SSU2, поскольку это было бы значительным усложнением.

Initiating Path Validation

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

Дополнительно, узел должен проверить, что новые IP и порт являются действительными согласно локальным правилам валидации (не заблокированы, не являются запрещенными портами и т.д.). Узлы НЕ обязаны поддерживать миграцию между IPv4 и IPv6, и могут рассматривать новый IP из другого семейства адресов как недействительный, поскольку это не ожидаемое поведение и может добавить значительную сложность реализации. При получении пакета с недействительного IP/порта, реализация может просто отбросить его, или может инициировать валидацию пути со старым IP/портом.

После входа в фазу валидации пути выполните следующие шаги:

  • Запустить таймер тайм-аута валидации пути на несколько секунд, или несколько раз больше текущего RTO (уточняется)
  • Уменьшить окно перегрузки до минимума
  • Уменьшить PMTU до минимума (1280)
  • Отправить пакет данных, содержащий блок Path Challenge, блок Address (содержащий новый IP/порт), и, как правило, блок ACK, на новый IP и порт. Этот пакет использует тот же connection ID и ключи шифрования, что и текущая сессия. Данные блока Path Challenge должны содержать достаточную энтропию (не менее 8 байт), чтобы их нельзя было подделать.
  • Опционально, также отправить Path Challenge на старый IP/порт, с другими данными блока. См. ниже.
  • Запустить таймер тайм-аута Path Response на основе текущего RTO (обычно RTT + кратное RTTdev)

Во время фазы валидации пути сессия может продолжать обрабатывать входящие пакеты. Как от старого, так и от нового IP/порта. Сессия также может продолжать отправлять и подтверждать пакеты данных. Однако окно перегрузки и PMTU должны оставаться на минимальных значениях во время фазы валидации пути, чтобы предотвратить их использование для атак типа “отказ в обслуживании” путем отправки больших объемов трафика на подложный адрес.

Реализация может, но не обязана, пытаться проверить несколько путей одновременно. Вероятно, это не стоит сложности. Она может, но не обязана, запоминать предыдущий IP/порт как уже проверенный и пропускать проверку пути, если узел возвращается к своему предыдущему IP/порту.

Если получен Path Response, содержащий идентичные данные, отправленные в Path Challenge, то Path Validation прошла успешно. Исходный IP/порт сообщения Path Response не обязан совпадать с тем, на который был отправлен Path Challenge.

Если Path Response не получен до истечения таймера Path Response, отправить другой Path Challenge и удвоить таймер Path Response.

Если Path Response не получен до истечения таймера Path Validation, то проверка пути не удалась.

Message Contents

Сообщения Data должны содержать следующие блоки. Порядок не указан, за исключением того, что Padding должен быть последним:

  • Блок Path Validation или Path Response. Path Validation содержит непрозрачные данные, рекомендуется минимум 8 байт. Path Response содержит данные из Path Validation.
  • Блок Address, содержащий видимый IP получателя
  • Блок DateTime
  • Блок ACK
  • Блок Padding

Не рекомендуется включать какие-либо другие блоки (например, I2NP) в сообщение.

Разрешается включать блок Path Validation в сообщение, содержащее Path Response, для инициации валидации в обратном направлении.

Блоки Path Challenge и Path Response вызывают подтверждение. Path Challenge будет подтвержден Data-сообщением, содержащим блоки Path Response и ACK. Path Response должен быть подтвержден Data-сообщением, содержащим блок ACK.

Routing during Path Validation

Спецификация QUIC не является четкой относительно того, куда отправлять пакеты данных во время валидации пути - на старый или новый IP/порт? Необходимо найти баланс между быстрым реагированием на изменения IP/порта и предотвращением отправки трафика на поддельные адреса. Также поддельные пакеты не должны существенно влиять на существующую сессию. Изменения только порта, вероятно, вызваны повторным связыванием NAT после периода простоя; изменения IP могут происходить во время фаз высокого трафика в одном или обоих направлениях.

Стратегии подлежат исследованию и усовершенствованию. Возможности включают:

  • Не отправлять пакеты данных на новый IP/порт до валидации
  • Продолжать отправлять пакеты данных на старый IP/порт до тех пор, пока новый IP/порт не будет валидирован
  • Одновременно повторно валидировать старый IP/порт
  • Не отправлять никаких данных до тех пор, пока не будет валидирован старый или новый IP/порт
  • Различные стратегии для изменения только порта и для изменения IP
  • Различные стратегии для изменения IPv6 в той же подсети /32, вероятно вызванного ротацией временных адресов

Responding to Path Challenge

При получении Path Challenge, узел должен ответить пакетом данных, содержащим Path Response, с данными из Path Challenge. TODO Возможно???: Path Response должен быть отправлен на IP/порт, с которого был получен Path Challenge. Это НЕ ОБЯЗАТЕЛЬНО тот же IP/порт, который был ранее установлен для узла. Это гарантирует, что валидация пути узлом успешна только в том случае, если путь функционален в обоих направлениях. См. раздел “Валидация после локального изменения” ниже.

Если IP/порт отличается от ранее известного IP/порта для пира, обрабатывайте Path Challenge как простой ping и отвечайте безусловно с помощью Path Response. Получатель не сохраняет и не изменяет никакого состояния на основе полученного Path Challenge. Если IP/порт отличается, пир должен проверить, что новый IP и порт являются действительными согласно локальным правилам валидации (не заблокированы, не являются запрещенными портами и т.д.). Пиры НЕ обязаны поддерживать межсемейственные ответы между IPv4 и IPv6 и могут рассматривать новый IP в другом семействе адресов как недействительный, поскольку это неожиданное поведение.

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

Блок Path Challenge обычно сопровождается блоком Address в том же сообщении. Если блок адреса содержит новый IP/порт, узел может проверить этот IP/порт и инициировать тестирование узла для этого нового IP/порта с сессионным узлом или любым другим узлом. Если узел считает, что он находится за firewall, и изменился только порт, это изменение вероятно вызвано повторной привязкой NAT, и дальнейшее тестирование узла вероятно не требуется.

Successful Path Validation

При успешной валидации пути соединение полностью мигрирует на новый IP/порт. При успехе:

  • Выйти из фазы валидации пути
  • Все пакеты отправляются на новый IP и порт.
  • Ограничения на окно перегрузки и PMTU снимаются, и им разрешается увеличиваться. Не следует просто восстанавливать их до старых значений, поскольку новый путь может иметь другие характеристики.
  • Если IP изменился, установить рассчитанные RTT и RTO в исходные значения. Поскольку изменения только порта обычно являются результатом NAT rebinding или другой активности middlebox, узел может вместо этого сохранить свое состояние контроля перегрузки и оценку времени приема-передачи в таких случаях вместо возврата к исходным значениям.
  • Удалить (аннулировать) любые токены, отправленные или полученные для старого IP/порта (необязательно)
  • Отправить новый блок токенов для нового IP/порта (необязательно)

Cancelling Path Validation

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

При отмене валидации пути:

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

Failed Path Validation

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

При неудачной проверке пути:

  • Выйти из фазы валидации пути
  • Все пакеты отправляются на старый IP и порт.
  • Ограничения на окно перегрузки и PMTU снимаются, и им разрешается увеличиваться.
  • Опционально, запустить валидацию пути на старом IP и порту. Если она не удается, завершить сессию.
  • В противном случае, следовать стандартным правилам тайм-аута и завершения сессии.
  • Повторно передать любые пакеты данных, которые ранее были отправлены на новый IP/порт, на старый IP/порт.

Validation After Local Change

Описанный выше процесс определен для peers, которые получают пакет с измененного IP/порта. Однако он также может быть инициирован в обратном направлении peer’ом, который обнаруживает, что его IP или порт изменились. Peer может быть способен обнаружить, что его локальный IP изменился; однако гораздо менее вероятно, что он обнаружит изменение своего порта из-за повторного связывания NAT. Поэтому это необязательно.

При получении path challenge от peer, чей IP или порт изменился, другой peer должен инициировать path challenge в обратном направлении.

Безопасность релея

Блоки Path Validation и Path Response могут использоваться в любое время как пакеты Ping/Pong. Получение блока Path Validation не изменяет никакого состояния у получателя, если только он не получен с другого IP/порта.

Multiple Sessions

Пиры не должны устанавливать несколько сессий с одним и тем же пиром, будь то SSU 1 или 2, или с одним и тем же или разными IP-адресами. Однако это может произойти либо из-за ошибок, либо из-за потери предыдущего сообщения о завершении сессии, либо в состоянии гонки, когда сообщение о завершении еще не пришло.

Если Боб имеет существующую сессию с Алисой, когда Боб получает Session Confirmed от Алисы, завершая handshake и устанавливая новую сессию, Боб должен:

  • Перенести все неотправленные или неподтверждённые исходящие I2NP сообщения из старой сессии в новую
  • Отправить завершение с кодом причины 22 в старой сессии
  • Удалить старую сессию и заменить её новой

Session Termination

Безопасность тестирования пиров

Сессии в фазе handshake обычно завершаются простым истечением времени ожидания или прекращением дальнейшего ответа. При желании они могут быть завершены включением блока Termination в ответ, но на большинство ошибок невозможно ответить из-за отсутствия криптографических ключей. Даже если ключи доступны для ответа, включающего блок завершения, обычно не стоит тратить процессорное время на выполнение DH для ответа. Исключением МОЖЕТ быть блок Termination в сообщении повторной попытки, который недорого генерировать.

Цели проектирования Relay и Peer Test

Сессии в фазе передачи данных завершаются отправкой сообщения с данными, которое включает блок Termination. Это сообщение также должно включать блок ACK. Оно может, если сессия была активна достаточно долго, чтобы ранее отправленный токен истёк или вот-вот истечёт, включать блок New Token. Это сообщение не требует подтверждения. При получении блока Termination с любой причиной, кроме “Termination Received”, узел отвечает сообщением с данными, содержащим блок Termination с причиной “Termination Received”.

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

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

После получения блока Termination с причиной “Termination Received”, сессия может выйти из фазы закрытия.

Cleanup

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

MTU

Требования различаются в зависимости от того, используется ли опубликованный адрес совместно с SSU 1. Текущий минимум для SSU 1 IPv4 составляет 620, что определенно слишком мало.

Минимальный SSU2 MTU составляет 1280 для IPv4 и IPv6, что соответствует спецификации в RFC 9000. См. ниже. Увеличение минимального MTU позволяет сообщениям туннелей размером 1 КБ и коротким сообщениям построения туннелей помещаться в одну датаграмму, что значительно снижает типичный объем фрагментации. Это также позволяет увеличить максимальный размер I2NP сообщения. Потоковые сообщения размером 1820 байт должны помещаться в две датаграммы.

Маршрутизатор не должен включать SSU2 или публиковать адрес SSU2, если MTU для этого адреса составляет менее 1280.

Router-ы должны публиковать MTU, отличный от значения по умолчанию, в каждом SSU или SSU2 адресе router-а.

Резюме

Общий адрес с SSU 1, должен следовать правилам SSU 1. IPv4: По умолчанию и максимум составляет 1484. Минимум 1292. (IPv4 MTU + 4) должно быть кратно 16. IPv6: Должно быть опубликовано, минимум 1280 и максимум 1488. IPv6 MTU должно быть кратно 16.

Гарантии доставки

IPv4: По умолчанию и максимум 1500. Минимум 1280. IPv6: По умолчанию и максимум 1500. Минимум 1280. Нет правил кратности 16, но вероятно должно быть кратным 2 как минимум.

Фреймворк протокола Noise

Для SSU 1 текущая Java I2P выполняет обнаружение PMTU, начиная с малых пакетов и постепенно увеличивая размер, или увеличивая на основе размера полученного пакета. Это грубый подход, который значительно снижает эффективность. Продолжение этой функции в SSU 2 еще предстоит определить.

Недавние исследования PMTU предполагают, что минимум для IPv4 в 1200 или более байт будет работать для более чем 99% соединений. QUIC RFC 9000 требует минимальный размер IP-пакета в 1280 байт.

цитата RFC 9000:

Максимальный размер датаграммы определяется как наибольший размер 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 байт, если путь поддерживает только минимальный MTU IPv6 в 1280 байт. Это влияет на Initial пакеты и валидацию пути.

конец цитаты

Дополнения к Framework

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

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

QUIC требует, чтобы Боб отправлял не более чем в три раза больше данных, чем получено, пока адрес клиента не будет проверен. SSU2 по своей природе соответствует этому требованию, поскольку сообщение Retry примерно такого же размера, как сообщение Token Request, и меньше, чем сообщение Session Request. Также сообщение Retry отправляется только один раз.

Оценка накладных расходов на обработку

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

Мы могли бы потребовать это также, ценой значительных затрат пропускной способности. Однако такие случаи должны быть редкими. TBD

Max I2NP Message Size

IPv4: Предполагается отсутствие IP-фрагментации. Заголовок IP + датаграммы составляет 28 байт. Это предполагает отсутствие IPv4-опций. Максимальный размер сообщения равен MTU - 28. Заголовок фазы данных составляет 16 байт, а MAC — 16 байт, в сумме 32 байта. Размер полезной нагрузки равен MTU - 60. Максимальная полезная нагрузка фазы данных составляет 1440 для максимального MTU 1500. Максимальная полезная нагрузка фазы данных составляет 1220 для минимального MTU 1280.

IPv6: Фрагментация IP не разрешена. Заголовок IP + датаграммы составляет 48 байт. Это предполагает отсутствие расширенных заголовков IPv6. Максимальный размер сообщения равен MTU - 48. Заголовок фазы данных составляет 16 байт, а MAC - 16 байт, всего 32 байта. Размер полезной нагрузки равен MTU - 80. Максимальная полезная нагрузка фазы данных составляет 1420 для максимального MTU 1500. Максимальная полезная нагрузка фазы данных составляет 1200 для минимального MTU 1280.

В SSU 1 рекомендации предусматривали строгий максимум около 32 КБ для I2NP сообщения на основе максимум 64 фрагментов и минимального MTU 620. Из-за накладных расходов на объединенные LeaseSet’ы и ключи сессии, практический лимит на уровне приложения был примерно на 6КБ ниже, или около 26КБ. Протокол SSU 1 допускает 128 фрагментов, но текущие реализации ограничивают это до 64 фрагментов.

Увеличив минимальный MTU до 1280, с полезной нагрузкой фазы данных приблизительно 1200, SSU 2 сообщение размером около 76 КБ возможно в 64 фрагментах и 152 КБ в 128 фрагментах. Это легко позволяет максимум в 64 КБ.

Из-за фрагментации в туннелях и фрагментации в SSU 2 вероятность потери сообщений экспоненциально возрастает с увеличением размера сообщения. Мы продолжаем рекомендовать практическое ограничение примерно в 10 КБ на уровне приложения для I2NP датаграмм.

Peer Test Process

Смотрите раздел “Безопасность тестирования узлов” выше для анализа SSU1 Peer Test и целей SSU2 Peer Test.

Alice                     Bob                  Charlie
1. PeerTest ------------------->
                              Alice RI ------------------->
2.                          PeerTest ------------------->
3.                             <------------------ PeerTest
          <---------------- Charlie RI
4.      <------------------ PeerTest

5.      <----------------------------------------- PeerTest
6. PeerTest ----------------------------------------->
7.      <----------------------------------------- PeerTest

Когда отклонено Бобом:

Alice                     Bob                  Charlie
1. PeerTest ------------------->
4.      <------------------ PeerTest (reject)

Когда отклонено Charlie:

Alice                     Bob                  Charlie
1. PeerTest ------------------->
                              Alice RI ------------------->
2.                          PeerTest ------------------->
3.                             <------------------ PeerTest (reject)
                        (optional: Bob could try another Charlie here)
4.      <------------------ PeerTest (reject)

ПРИМЕЧАНИЕ: RI может отправляться либо в сообщениях I2NP Database Store в блоках I2NP, либо как блоки RI (если достаточно малы). Они могут содержаться в тех же пакетах, что и блоки peer test, если достаточно малы.

Сообщения 1-4 находятся в сеансе с использованием блоков Peer Test в сообщении Data. Сообщения 5-7 находятся вне сеанса с использованием блоков Peer Test в сообщении Peer Test.

ПРИМЕЧАНИЕ: Как и в SSU 1, сообщения 4 и 5 могут прибыть в любом порядке. Сообщение 5 и/или 7 могут вообще не быть получены, если Alice находится за файрволом. Когда сообщение 5 прибывает раньше сообщения 4, Alice не может немедленно отправить сообщение 6, потому что у неё ещё нет intro key Чарли для шифрования заголовка. Когда сообщение 4 прибывает раньше сообщения 5, Alice не должна немедленно отправлять сообщение 6, потому что ей следует подождать и посмотреть, прибудет ли сообщение 5, не открывая файрвол сообщением 6.

MessagePathIntro Key
1A->B sessionin-session
2B->C sessionin-session
3C->B sessionin-session
4B->A sessionin-session
5C->AAlice
6A->CCharlie
7C->AAlice

Versions

Кросс-версионное тестирование peers не поддерживается. Единственная допустимая комбинация версий — когда все peers используют версию 2.

Alice/BobBob/CharlieAlice/CharlieSupported
111SSU 1
112no, use 1/1/1
121no, Bob must s
122no, Bob must s
211no, Bob must s
212no, Bob must s
221no, use 2/2/2
222yes

Установка сессии

Сообщения 1-4 находятся в сессии и покрываются процессами ACK фазы данных и повторной передачи. Блоки Peer Test требуют подтверждения.

Сообщения 5-7 могут быть переданы повторно без изменений.

Заголовок пакета

Как и в SSU 1, поддерживается тестирование IPv6-адресов, и связь между Alice-Bob и Alice-Charlie может осуществляться через IPv6, если Bob и Charlie указывают поддержку с помощью возможности ‘B’ в своем опубликованном IPv6-адресе. Подробности см. в Proposal 126.

Как и в SSU 1 до версии 0.9.50, Алиса отправляет запрос Бобу, используя существующую сессию по транспорту (IPv4 или IPv6), который она хочет протестировать. Когда Боб получает запрос от Алисы по IPv4, Боб должен выбрать Чарли, который анонсирует IPv4-адрес. Когда Боб получает запрос от Алисы по IPv6, Боб должен выбрать Чарли, который анонсирует IPv6-адрес. Фактическая коммуникация между Бобом и Чарли может происходить по IPv4 или IPv6 (т.е. независимо от типа адреса Алисы). Это НЕ поведение SSU 1 начиная с версии 0.9.50, где разрешены смешанные IPv4/v6 запросы.

Processing by Bob

В отличие от SSU 1, Alice указывает запрашиваемый тестовый IP и порт в сообщении 1. Bob должен проверить этот IP и порт, и отклонить с кодом 5, если они недействительны. Рекомендуемая проверка IP заключается в том, что для IPv4 он должен совпадать с IP Alice, а для IPv6 должны совпадать по крайней мере первые 8 байтов IP. Проверка порта должна отклонять привилегированные порты и порты для известных протоколов.

Relay Process

См. раздел “Безопасность ретрансляции” выше для анализа SSU1 Relay и целей SSU2 Relay.

Alice                         Bob                  Charlie
     lookup Bob RI

     SessionRequest -------------------->
          <------------  SessionCreated
     SessionConfirmed  ----------------->

1. RelayRequest ---------------------->
                                           Alice RI  ------------>
2.                                       RelayIntro ----------->
3.                                  <-------------- RelayResponse
4.      <-------------- RelayResponse

5.      <-------------------------------------------- HolePunch
6. SessionRequest -------------------------------------------->
7.      <-------------------------------------------- SessionCreated
8. SessionConfirmed ------------------------------------------>

Когда отклонено Бобом:

Alice                         Bob                  Charlie
     lookup Bob RI

     SessionRequest -------------------->
          <------------  SessionCreated
     SessionConfirmed  ----------------->

1. RelayRequest ---------------------->
4.      <-------------- RelayResponse

Когда отклонено Charlie:

Alice                         Bob                  Charlie
     lookup Bob RI

     SessionRequest -------------------->
          <------------  SessionCreated
     SessionConfirmed  ----------------->

1. RelayRequest ---------------------->
                                           Alice RI  ------------>
2.                                       RelayIntro ----------->
3.                                  <-------------- RelayResponse
4.      <-------------- RelayResponse

ПРИМЕЧАНИЕ: RI может отправляться либо в виде I2NP Database Store сообщений в I2NP блоках, либо в виде RI блоков (если достаточно малы). Они могут содержаться в тех же пакетах, что и relay блоки, если достаточно малы.

В SSU 1 информация о роутере Чарли содержит IP, порт, intro key, relay tag и время истечения каждого introducer.

В SSU 2 информация о роутере Чарли содержит хеш роутера, тег ретрансляции и время истечения каждого introducer.

Alice должна сократить количество необходимых циклов передачи данных, сначала выбрав introducer (Bob), к которому у неё уже есть соединение. Во-вторых, если такого нет, выбрать introducer, информацию о router которого у неё уже есть.

Cross-version relaying также должна поддерживаться, если это возможно. Это облегчит постепенный переход с SSU 1 на SSU 2. Допустимые комбинации версий (TODO):

Alice/BobBob/CharlieAlice/CharlieSupported
111SSU 1
112no, use 1/1/1
121yes?
122no, use 1/2/1
211yes?
212yes?
221no, use 2/2/2
222yes

Retransmissions

Relay Request, Relay Intro и Relay Response являются внутрисеансовыми и покрываются процессами подтверждения и повторной передачи фазы данных. Блоки Relay Request, Relay Intro и Relay Response требуют подтверждения.

Hole punch может быть повторно передан, как в SSU 1.

IPv4/v6

Все функции SSU 1 relay поддерживаются, включая те, что документированы в Предложении 158 и поддерживаются начиная с версии 0.9.50. IPv4 и IPv6 представления поддерживаются. Relay Request может быть отправлен через IPv4 сессию для IPv6 представления, и Relay Request может быть отправлен через IPv6 сессию для IPv4 представления.

Processing by Alice

Ниже приведены отличия от SSU 1 и рекомендации для реализации SSU 2.

Примечания

В SSU 1 введение относительно недорого, и Alice обычно отправляет Relay Request всем introducers. В SSU 2 введение более затратно, поскольку сначала необходимо установить соединение с introducer. Для минимизации задержки и накладных расходов на введение рекомендуются следующие шаги обработки:

  • Игнорировать любые introducers, которые истекли на основании значения iexp в адресе
  • Если SSU2 соединение уже установлено с одним или несколькими introducers, выбрать один и отправить Relay Request только этому introducer.
  • В противном случае, если Router Info локально известен для одного или нескольких introducers, выбрать один и подключиться только к этому introducer.
  • В противном случае, найти Router Infos для всех introducers, подключиться к introducer, чей Router Info получен первым.

Примечания

В SSU 1 и SSU 2 Relay Response и Hole Punch могут быть получены в любом порядке или могут не быть получены вообще.

В SSU 1 Алиса обычно получает Relay Response (1 RTT) раньше Hole Punch (1 1/2 RTT). Это может быть не очень хорошо задокументировано в тех спецификациях, но Алиса должна получить Relay Response от Боба перед продолжением, чтобы получить IP-адрес Чарли. Если Hole Punch получен первым, Алиса его не распознает, поскольку он не содержит данных, а исходный IP не распознан. После получения Relay Response Алиса должна ждать ЛИБО получения Hole Punch от Чарли, ЛИБО короткой задержки (рекомендуется 500 мс) перед началом рукопожатия с Чарли.

В SSU 2 Алиса обычно получит Hole Punch (1 1/2 RTT) раньше, чем Relay Response (2 RTT). SSU 2 Hole Punch легче обрабатывать, чем в SSU 1, поскольку это полное сообщение с определенными ID соединений (производными от relay nonce) и содержимым, включающим IP-адрес Чарли. Relay Response (сообщение Data) и сообщение Hole Punch содержат идентичный подписанный блок Relay Response. Поэтому Алиса может инициировать handshake с Чарли после ЛЮБОГО из событий: получения Hole Punch от Чарли ИЛИ получения Relay Response от Боба.

Проверка подписи Hole Punch включает хеш router’а представителя (Bob’а). Если Relay Request’ы были отправлены более чем одному представителю, существует несколько вариантов для валидации подписи:

  • Попробуйте каждый хеш, на который был отправлен запрос
  • Используйте разные nonce для каждого introducer и используйте это, чтобы определить, какой introducer этот Hole Punch был в ответ на
  • Не переvalidируйте подпись, если содержимое идентично тому, что в Relay Response, если уже получено
  • Вообще не проверяйте подпись

Если Чарли находится за симметричным NAT, его указанный порт в Relay Response и Hole Punch может быть неточным. Поэтому Алиса должна проверить UDP порт источника сообщения Hole Punch и использовать его, если он отличается от указанного порта.

Tag Requests by Bob

В SSU 1 только Алиса могла запросить тег в Session Request. Боб никогда не мог запросить тег, и Алиса не могла ретранслировать для Боба.

В SSU2 Алиса обычно запрашивает тег в Session Request, но и Алиса, и Боб могут также запросить тег в фазе данных. Боб обычно не находится за файрволом после получения входящего запроса, но это может произойти после relay, или состояние Боба может измениться, или он может запросить introducer для другого типа адреса (IPv4/v6). Таким образом, в SSU2 возможно, чтобы и Алиса, и Боб одновременно были relay для другой стороны.

Published Router Info

Address Properties

Следующие свойства адресов могут быть опубликованы без изменений по сравнению с SSU 1, включая изменения в Предложении 158, поддерживаемые начиная с API 0.9.50:

  • caps: возможности [B,C,4,6]

  • host: IP (IPv4 или IPv6). Разрешены сокращенные IPv6-адреса (с “::”). Может присутствовать или отсутствовать при наличии firewall. Имена хостов не разрешены.

  • iexp[0-2]: Истечение срока действия этого introducer. ASCII цифры, в секундах с начала эпохи. Присутствует только если брандмауэр активен и introducers требуются. Необязательно (даже если присутствуют другие свойства для этого introducer).

  • ihost[0-2]: IP-адрес introducer’а (IPv4 или IPv6). Сокращённый IPv6-адрес (с “::”) разрешён. Присутствует только если за файрволлом, и требуются introducer’ы. Имена хостов не разрешены. Только для SSU-адресов.

  • ikey[0-2]: Base 64 ключ представления вводящего узла. Присутствует только если находится за файрволом и требуются вводящие узлы. Только для SSU адреса.

  • iport[0-2]: Порт introducer’а 1024 - 65535. Присутствует только если заблокирован файрволлом и требуются introducer’ы. Только для SSU адреса.

  • itag[0-2]: Тег представляющего (introducer) 1 - (2**32 - 1) ASCII цифры. Присутствует только если находится за файрволом и требуются представляющие (introducers).

  • key: Ключ введения Base 64.

  • mtu: Опционально. См. раздел MTU выше.

  • port: 1024 - 65535 Может присутствовать или отсутствовать при наличии файрвола.

Published Addresses

Опубликованный RouterAddress (часть RouterInfo) будет иметь идентификатор протокола либо “SSU”, либо “SSU2”.

RouterAddress должен содержать три опции для указания поддержки SSU2:

  • s=(Base64 key) Текущий статический публичный ключ Noise (s) для данного RouterAddress. Кодируется в Base 64 с использованием стандартного алфавита I2P Base 64. 32 байта в двоичном формате, 44 байта в кодировке Base 64, публичный ключ X25519 в little-endian формате.

  • i=(Base64 key) Текущий ключ введения для шифрования заголовков данного RouterAddress. Кодируется в Base 64 с использованием стандартного алфавита I2P Base 64. 32 байта в двоичном формате, 44 байта в кодировке Base 64, ключ ChaCha20 в формате big-endian.

  • v=2 Текущая версия (2). При публикации как “SSU” подразумевается дополнительная поддержка версии 1. Поддержка будущих версий будет осуществляться через значения, разделенные запятыми, например v=2,3 Реализация должна проверять совместимость, включая несколько версий при наличии запятой. Версии, разделенные запятыми, должны быть в числовом порядке.

Алиса должна проверить, что все три опции присутствуют и действительны перед подключением с использованием протокола SSU2.

Когда опубликовано как “SSU” с опциями “s”, “i” и “v”, а также с опциями “host” и “port”, router должен принимать входящие соединения на этом хосте и порту для обоих протоколов SSU и SSU2, и автоматически определять версию протокола.

Когда опубликован как “SSU2” с опциями “s”, “i” и “v”, а также с опциями “host” и “port”, маршрутизатор принимает входящие соединения на этом хосте и порту только для протокола SSU2.

Если роутер поддерживает как SSU1, так и SSU2 соединения, но не реализует автоматическое определение версии для входящих соединений, он должен объявлять как адреса “SSU”, так и “SSU2”, и включать опции SSU2 только в адрес “SSU2”. Роутер должен установить более низкое значение стоимости (более высокий приоритет) в адресе “SSU2”, чем в адресе “SSU”, чтобы SSU2 имел предпочтение.

Если несколько SSU2 RouterAddresses (как “SSU”, так и “SSU2”) публикуются в одном RouterInfo (для дополнительных IP-адресов или портов), все адреса, указывающие один и тот же порт, должны содержать идентичные SSU2 опции и значения. В частности, все они должны содержать один и тот же статический ключ “s” и ключ представления “i”.

Introducers

При публикации как SSU или SSU2 с introducers присутствуют следующие опции:

  • ih[0-2]=(Base64 hash) Хэш router’а для introducer’а. Кодируется в Base 64 с использованием стандартного алфавита I2P Base 64. 32 байта в двоичном формате, 44 байта в кодировке Base 64

  • iexp[0-2]: Истечение срока действия этого introducer. Не изменено по сравнению с SSU 1.

  • itag[0-2]: Тег представляющего узла 1 - (2**32 - 1) Не изменился с SSU 1.

Следующие опции предназначены только для SSU и не используются для SSU2. В SSU2 Алиса получает эту информацию из RI Чарли вместо этого.

  • ihost[0-2]
  • ikey[0-2]
  • itag[0-2]

Router не должен публиковать хост или порт в адресе при публикации introducers. Router должен публиковать caps 4 и/или 6 в адресе при публикации introducers для указания поддержки IPv4 и/или IPv6. Это то же самое, что и текущая практика для недавних SSU 1 адресов.

Примечание: Если публикуется как SSU, и имеется смесь introducer-ов SSU 1 и SSU2, introducer-ы SSU 1 должны находиться под меньшими индексами, а introducer-ы SSU2 должны находиться под большими индексами, для совместимости со старыми router-ами.

Unpublished SSU2 Address

Если Alice не публикует свой SSU2 адрес (как “SSU” или “SSU2”) для входящих соединений, она должна опубликовать адрес роутера “SSU2”, содержащий только её статический ключ и версию SSU2, чтобы Bob мог валидировать ключ после получения RouterInfo Alice в части 2 Session Confirmed.

  • s=(Base64 key) Как определено выше для опубликованных адресов.

  • i=(Base64 key) Как определено выше для опубликованных адресов.

  • v=2 Как определено выше для опубликованных адресов.

Этот адрес маршрутизатора не будет содержать опции “host” или “port”, поскольку они не требуются для исходящих SSU2 соединений. Опубликованная стоимость для этого адреса не имеет строгого значения, так как он предназначен только для входящих соединений; однако, это может быть полезно для других маршрутизаторов, если стоимость установлена выше (более низкий приоритет), чем у других адресов. Рекомендуемое значение — 14.

Алиса также может просто добавить параметры “i”, “s” и “v” к существующему опубликованному адресу “SSU”.

Целостность пакетов

Использование одинаковых статических ключей для NTCP2 и SSU2 разрешено, но не рекомендуется.

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

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

Если router имеет какие-либо опубликованные SSU2 RouterAddresses (как SSU или SSU2), минимальное время простоя перед ротацией должно быть намного больше, например один месяц, если только локальный IP-адрес не изменился или router не выполнил “rekeys”.

Если router имеет какие-либо опубликованные SSU RouterAddresses, но не SSU2 (как SSU или SSU2), минимальное время простоя перед ротацией должно быть больше, например один день, если только локальный IP-адрес не изменился или router не выполнил “rekeys”. Это применимо даже если опубликованный SSU адрес имеет introducers.

Если router не имеет опубликованных RouterAddresses (SSU, SSU2 или SSU), минимальное время простоя перед ротацией может составлять всего два часа, даже при смене IP-адреса, если только router не выполняет “rekeys”.

Если router “перегенерирует ключи” на другой Router Hash, он должен также сгенерировать новый noise ключ и intro ключ.

Реализации должны учитывать, что изменение статического публичного ключа или IV заблокирует входящие SSU2 соединения от роутеров, которые кэшировали старую RouterInfo. Публикация RouterInfo, выбор партнеров туннеля (включая как OBGW, так и ближайший IB хоп), выбор zero-hop туннеля, выбор транспорта и другие стратегии реализации должны это учитывать.

Ротация intro ключей подчиняется тем же правилам, что и ротация ключей.

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

Identity Hiding

Отрицание не является целью. См. обзор выше.

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

Данный раздел рассматривает только утечку идентификационных данных через статические поля открытых ключей в handshake-процедурах. Разумеется, идентичности участников Noise могут быть раскрыты другими способами, включая поля полезной нагрузки, анализ трафика или метаданные, такие как IP-адреса.

Алиса: (8) Зашифровано с прямой секретностью для аутентифицированной стороны.

Боб: (3) Не передается, но пассивный атакующий может проверить кандидатов для приватного ключа отвечающей стороны и определить, правильный ли кандидат.

Боб публикует свой статический публичный ключ в netDb. Алиса может не делать этого, но должна включить его в RI, отправляемый Бобу.

Packet Guidelines

Аутентифицированное шифрование

Сообщения handshake (Session Request/Created/Confirmed, Retry) основные шаги, по порядку:

  • Создать заголовок размером 16 или 32 байта
  • Создать полезную нагрузку
  • Выполнить mixHash() для заголовка (кроме Retry)
  • Зашифровать полезную нагрузку с использованием Noise (кроме Retry, использовать ChaChaPoly с заголовком в качестве AD)
  • Зашифровать заголовок, а для Session Request/Created — ephemeral key

Основные этапы сообщений фазы данных, по порядку:

  • Создать 16-байтовый заголовок
  • Создать полезную нагрузку
  • Зашифровать полезную нагрузку, используя ChaChaPoly с заголовком в качестве AD
  • Зашифровать заголовок

Inbound Packet Handling

Полезная нагрузка

Первоначальная обработка всех входящих сообщений:

  • Расшифровать первые 8 байт заголовка (Destination Connection ID) с помощью intro key
  • Найти соединение по Destination Connection ID
  • Если соединение найдено и находится в фазе передачи данных, перейти к разделу фазы передачи данных
  • Если соединение не найдено, перейти к разделу handshake
  • Примечание: Сообщения Peer Test и Hole Punch также могут быть найдены по Destination Connection ID, созданному из test или relay nonce.

Обработка сообщений handshake (Session Request/Created/Confirmed, Retry, Token Request) и других сообщений вне сессии (Peer Test, Hole Punch):

  • Расшифровать байты 8-15 заголовка (тип пакета, версию и net ID) с помощью intro key. Если это валидный Session Request, Token Request, Peer Test или Hole Punch, продолжить
  • Если не валидное сообщение, найти ожидающее исходящее соединение по IP/порту источника пакета, обработать пакет как Session Created или Retry. Заново расшифровать первые 8 байтов заголовка с правильным ключом, и байты 8-15 заголовка (тип пакета, версию и net ID). Если это валидный Session Created или Retry, продолжить
  • Если не валидное сообщение, завершить с ошибкой или поставить в очередь как возможный пакет фазы данных вне очереди
  • Для Session Request/Created, Retry, Token Request, Peer Test и Hole Punch расшифровать байты 16-31 заголовка
  • Для Session Request/Created расшифровать эфемерный ключ
  • Проверить все поля заголовка, остановиться если не валидны
  • mixHash() заголовка
  • Для Session Request/Created/Confirmed расшифровать полезную нагрузку используя Noise
  • Для Retry и фазы данных расшифровать полезную нагрузку используя ChaChaPoly
  • Обработать заголовок и полезную нагрузку

Обработка сообщений фазы данных:

  • Расшифровать байты 8-15 заголовка (тип пакета, версию и net ID) правильным ключом
  • Расшифровать полезную нагрузку с помощью ChaChaPoly, используя заголовок как AD
  • Обработать заголовок и полезную нагрузку

Details

В SSU 1 классификация входящих пакетов затруднена, поскольку отсутствует заголовок для указания номера сессии. Маршрутизаторы должны сначала сопоставить исходный IP и порт с существующим состоянием узла, а если совпадение не найдено, попытаться выполнить множественные расшифровки с различными ключами, чтобы найти подходящее состояние узла или начать новое. В случае изменения исходного IP или порта для существующей сессии, возможно из-за поведения NAT, маршрутизатор может использовать ресурсозатратные эвристики для попытки сопоставления пакета с существующей сессией и восстановления содержимого.

SSU 2 разработан для минимизации усилий по классификации входящих пакетов при сохранении устойчивости к DPI и другим угрозам на пути передачи. Номер Connection ID включен в заголовок для всех типов сообщений и зашифрован (обфусцирован) с использованием ChaCha20 с известным ключом и nonce. Дополнительно, тип сообщения также включен в заголовок (зашифрован с защитой заголовка известным ключом, а затем обфусцирован с помощью ChaCha20) и может использоваться для дополнительной классификации. Ни в коем случае не требуется пробная операция DH или другая асимметричная криптографическая операция для классификации пакета.

Для почти всех сообщений от всех узлов ключ ChaCha20 для шифрования Connection ID является introduction key целевого router, как опубликовано в netDb.

Единственными исключениями являются первые сообщения, отправленные от Bob к Alice (Session Created или Retry), где ключ знакомства Alice еще неизвестен Bob. В этих случаях в качестве ключа используется ключ знакомства Bob.

Протокол разработан для минимизации обработки классификации пакетов, которая может потребовать дополнительных криптографических операций в нескольких резервных шагах или сложной эвристики. Кроме того, подавляющее большинство получаемых пакетов не будет требовать (возможно, дорогостоящего) резервного поиска по исходному IP/порту и второй расшифровки заголовка. Только Session Created и Retry (и возможно другие, которые будут определены) потребуют резервной обработки. Если конечная точка изменит IP или порт после создания сессии, ID соединения по-прежнему используется для поиска сессии. Никогда не требуется использовать эвристику для поиска сессии, например, путем поиска другой сессии с тем же IP, но другим портом.

Поэтому рекомендуемые шаги обработки в логике цикла получателя:

  1. Расшифруйте первые 8 байт с помощью ChaCha20, используя локальный ключ введения, чтобы восстановить Destination Connection ID. Если Connection ID соответствует текущей или ожидающей входящей сессии:

a) Используя соответствующий ключ, расшифровать байты заголовка 8-15

  to recover the version, net ID, and message type.

b) Если тип сообщения Session Confirmed, это длинный заголовок.

  Verify the net ID and protocol version are valid.
  Decrypt the bytes 15-31 of the header with ChaCha20
  using the local intro key. Then MixHash() the
  decrypted 32 byte header and decrypt the message with Noise.

в) Если тип сообщения действителен, но не Session Confirmed,

  it is a short header.
  Verify the net ID and protocol version are valid.
  decrypt the rest of the message with ChaCha20/Poly1305
  using the session key, using the decrypted 16-byte header
  as the AD.

d) (необязательно) Если connection ID является ожидающей входящей сессией

  awaiting a Session Confirmed message,
  but the net ID, protocol, or message type is not valid,
  it could be a Data message received out-of-order before the
  Session Confirmed, so the data phase header protection keys are not yet known,
  and the header bytes 8-15 were incorrectly decrypted.
  Queue the message, and attempt to decrypt it once the
  Session Confirmed message is received.

е) Если b) или c) не удается, отбросить сообщение.

  1. Если ID соединения не соответствует текущей сессии: Проверить, что заголовок открытого текста в байтах 8-15 является корректным (без выполнения каких-либо операций защиты заголовка). Убедиться, что net ID и версия протокола корректны, а тип сообщения — Session Request или другой тип сообщения, разрешённый вне сессии (TBD).

a) Если все корректно и тип сообщения — Session Request,

  decrypt bytes 16-31 of the header and the 32-byte X value
  with ChaCha20 using the local intro key.
  • Если токен в байтах заголовка 24-31 принят, то выполнить MixHash() расшифрованного 32-байтного заголовка и расшифровать сообщение с помощью Noise. Отправить Session Created в ответ.
    • Если токен не принят, отправить сообщение Retry на исходный IP/порт с токеном. Не пытаться расшифровать сообщение с помощью Noise во избежание DDoS-атак.

b) Если тип сообщения является каким-либо другим действительным сообщением

  out-of-session, presumably with a short header,
  decrypt the rest of the message with ChaCha20/Poly1305
  using the intro key, and using the decrypted 16-byte header
  as the AD. Process the message.

c) Если a) или b) не удается, переходите к шагу 3)

  1. Найти ожидающую исходящую сессию по IP-адресу/порту источника пакета.

a) Если найден, повторно расшифровать первые 8 байт с помощью ChaCha20, используя introduction key Боба

  to recover the Destination Connection ID.

б) Если ID соединения соответствует ожидающей сессии:

  Using the correct key, decrypt bytes 8-15 of the header
  to recover the version, net ID, and message type.
  Verify the net ID and protocol version are valid, and
  the message type is Session Created or Retry, or other message type
  allowed out-of-session (TBD).
  • Если все действительно и тип сообщения — Session Created, расшифровать следующие 16 байт заголовка и 32-байтное значение Y с помощью ChaCha20, используя intro key Боба. Затем выполнить MixHash() для расшифрованного 32-байтного заголовка и расшифровать сообщение с помощью Noise. Отправить Session Confirmed в ответ.

    • Если все действительно и тип сообщения — Retry, расшифровать байты 16-31 заголовка с помощью ChaCha20, используя intro key Боба. Расшифровать и проверить сообщение, используя ChaCha20/Poly1305 с TBD в качестве ключа и TBD в качестве nonce, и расшифрованный 32-байтный заголовок в качестве AD. Повторно отправить Session Request с полученным токеном в ответ.
    • Если тип сообщения — какое-то другое сообщение, которое действительно вне сессии, предположительно с коротким заголовком, расшифровать остальную часть сообщения с помощью ChaCha20/Poly1305, используя intro key и расшифрованный 16-байтный заголовок в качестве AD. Обработать сообщение.

    c) If a pending outbound session is not found, or the connection ID does not match the pending session, drop the message, unless the port is shared with SSU 1.

  1. Если SSU 1 работает на том же порту, попытаться обработать сообщение как SSU 1 пакет.

Error Handling

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

В большинстве случаев просто отбрасывайте пакет. Реализация может, но не обязана, повторно передать ранее отправленный пакет (handshake сообщение или ACK 0) в ответ.

После отправки Session Created как Bob, неожиданными пакетами обычно являются пакеты Data, которые не могут быть расшифрованы, поскольку пакеты Session Confirmed были потеряны или получены не по порядку. Поместите пакеты в очередь и попытайтесь расшифровать их после получения пакетов Session Confirmed.

После получения Session Confirmed в качестве Bob, неожиданные пакеты обычно представляют собой повторно переданные пакеты Session Confirmed, поскольку ACK 0 пакета Session Confirmed был утерян. Неожиданные пакеты могут быть отброшены. Реализация может, но не обязана, отправить пакет Data, содержащий блок ACK в ответ.

Notes

Для Session Created и Session Confirmed реализации должны тщательно проверять все расшифрованные поля заголовка (Connection IDs, номер пакета, тип пакета, версия, id, frag и флаги) ПЕРЕД вызовом mixHash() на заголовке и попыткой расшифровки полезной нагрузки с помощью Noise AEAD. Если расшифровка Noise AEAD не удается, дальнейшая обработка не может быть выполнена, поскольку mixHash() повредит состояние handshake, если только реализация не сохраняет и не “откатывает” состояние хеша.

Version Detection

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

Будет определено при необходимости.

  • Таймаут повторной передачи исходящего handshake: 1,25 секунды, с экспоненциальным откатом (повторные передачи через 1,25, 3,75 и 8,75 секунд)
  • Общий таймаут исходящего handshake: 15 секунд
  • Таймаут повторной передачи входящего handshake: 1 секунда, с экспоненциальным откатом (повторные передачи через 1, 3 и 7 секунд)
  • Общий таймаут входящего handshake: 12 секунд
  • Таймаут после отправки повтора: 9 секунд
  • Задержка ACK: max(10, min(rtt/6, 150)) мс
  • Задержка немедленного ACK: min(rtt/16, 5) мс
  • Максимальное количество диапазонов ACK: 256?
  • Максимальная глубина ACK: 512?
  • Распределение дополнения: 0-15 байт или больше

Variants, Fallbacks, and General Issues

Будет определено позже

Packet Overhead Analysis

Предполагает IPv4, не включая дополнительное заполнение, не включая размеры заголовков IP и UDP. Заполнение представляет собой выравнивание по модулю 16 только для SSU 1.

SSU 1

MessageHeader+MACKeysDataPaddingTotalNotes
Session Request4025653304Incl.
Session Created37256791336Incl.
Session Confirmed3746213512Incl.
Data (RI)3710141051Incl.
Data (1 full msg)371451Incl.
Total2254
SSU 2
MessageHeader+MACsKeysDataPaddingTotalNotes
Session Request4832787DateTi
Session Created48321696DateTi
Session Confirmed4832100510851000 b
Data (1 full msg)321446
Total1314
TODO ЕСЛИ минимальный размер пакета в Session Request и Created не обеспечивается для PMTU.