Продолжение статьи "Yggdrasil Network: Заря бытовых меш-сетей, или Интернет будущего".
Если вы знакомы с сетью, либо читали предыдущую статью, должно быть знаете о феномене «сетевых штормов», которые всплыли при расширении Yggdrasil и явились основным слабым местом протокола. Сетевой шторм, как это явление прозвали энтузиасты, – недочет в логике маршрутизации, над решением которого команда разработчиков трудилась много месяцев.
Далее вы увидите как борьба с одним багом вылилась в фундаментальную переделку протокола.
Релиз
Релиз Yggdrasil Network 0.4.0 состоялся 04.07.2021. Разработчики потратили больше года на новую реализацию, работа над которой велась отдельно от предыдущей ветки. Начиная с самого зарождения проекта и до появления первого релиза 0.4 (с февраля 2018 года по июль 2021) протокол обновлялся мягко - полная совместимость с предыдущими версиями. Мягкое обновление означает, что внутренние адреса IPv6 оставались неизменны (не нужно менять никакие серверные и клиентские конфиги в прикладных программах), а также нет критической зависимости от актуальности ПО других участников сети - сам обновился и ладно.
Заменив клиент сети Yggdrasil 0.3 на новый 0.4, неискушенный пользователь может не заметить разницы: тот же виртуальный сетевой адаптер и адрес IPv6 из диапазона 200::/7
; Yggdrasil по прежнему автоматически организует подключение только в пределах локальной сети, а для связи с глобальным сегментом необходимо прописать в конфигурационном файле одного или нескольких локальных узлов адрес публичного пира. Однако под капотом произошли большие перемены, самое желанное из которых - значительный прирост стабильности соединений, а тяжелое - потеря обратной совместимости с предыдущей версией сети.
Разработчики имели целью решение выявленных проблем, а также упрощение и оптимизацию кодовой базы - рефакторинг. Это логичный шаг на пути к интуитивно понятному ПО, код которого наименьшим образом подвержен нелогичным нагромождениям и трудно отлавливаемым багам. В итоге были убраны опции встроенного файрволла и туннелирования трафика, так как для этих нужд существует отдельное специализированное программное обеспечение.
Чтобы понять роковое решение разработчиков о новом релизе, который несовместим с предыдущей сетью, необходимо понять решение каких проблем легло на их плечи, в чем причина этих недочетов и как они были исправлены. В конечном счете переход на новую версию сети - единовременная операция, а качественно новый уровень работы с сетью быстро изгладит неприятный осадок. Переделка протокола происходила кропотливо, было проведено много практических опытов и теоретических изысканий, поэтому можно полагать, что в ближайшие годы новых несовместимых релизов не будет, если это вообще когда-то случится.
Сетевой шторм - недочет маршрутизации
В предыдущей статье достаточно подробно рассматривалась маршрутизация Yggdrasil 0.3. Логику можно резюмировать так: IPv6 в Yggdrasil генерируются случайным образом и не имеет потенциала для логической маршрутизации. Алгоритм нахождения узлов друг другом и маршрутизацию между ними через десятки промежуточных узлов обеспечивают графы DHT, которые для удобства называются координатами.
Природа появления сетевого шторма кроется в логике построения маршрутов между узлами, которая напрямую завязана на координатах. За точку отсчета координат берется узел с неким характерным публичным ключом. При передачи трафика в сети 0.3, узлы опирались на динамическую информацию о своих координатах и координатах соседей. Если из сети пропадал корневой узел, являющийся началом отсчета координат, сеть начинала перестраиваться. Во время выбора нового корня каждый узел сети лавинообразно менял свои координаты. В силу хаотичности координат было невозможно построить стабильный маршрут, поэтому связность сети на время перестройки резко падала. При нормальном сценарии подобный шторм длился несколько секунд, после чего все узлы приходили к консенсусу о центре, однако иногда штормы длились часами. Выбор корня в Yggdrasil 0.3 описан в предыдущей статье.
Критичность проблемы сетевых штормов особенно сильно и отчасти комично проявлялась при использовании Yggdrasil Network в локальной сети. Частный случай случай выглядит так: два компьютера стоят в метре друг от друга, между ними проложен локальной кабель. Локальный сегмент Yggdrasil из двух участников подключен к глобальному сегменту через подключение одного из компьютеров к публичному пиру. Во время шторма физические соседи переставали видеть друг друга из-за постоянной смены координат и адекватное сообщение в локальной сети прекращалось. Стабильность налаживалась только тогда, когда вся сеть Yggdrasil, включая два локальных компьютера, имели устойчивые координаты.
Новый подход
В Yggdrasil 0.4 маршрутизация абсолютно переработана - реализована с нуля. Логика работы в дереве, знакомая с предыдущей версии сети теперь имеет два дополнительных понятия: маршрутизация по пространству ключей (keyspace) и маршрутизация от источника (source routing или "ленивая маршрутизация").
По большей части в современной реализации меш-сети используется ленивая маршрутизация, которая не зависит от каких-либо координат - лишь бы фактический путь следования трафика не был нарушен. За этим следит каждый из промежуточных узлов и в случае обрыва соединения на своем участке явно оповещает соседей для мобильного решения ситуации. Проще говоря: адресат и путь до него находится по внутрисетевым координатам, а в рамках сессии трафик идет по статичному оптимальному маршруту, основанному на реальной топологии (а не логической по DHT).
Вычисление точки отсчета координат также как и в Yggdrasil 0.3 завязано на ключ подписи, но алгоритм сильно упрощен. Публичный ключ - это 32 байта информации, которые можно представить в любом виде: в бинарном, шестнадцатеричном, кодировке base32 или base64, но в конечном счете любое значение является неким числом. Началом пространства координат сети Yggdrasil считается узел, чей ключ является наименьшим в математическом смысле.
Концептуально новым явлением относительно более ранних версий является маршрутизация в пространстве ключей, которая изменила прежнее представление о координатах. Новая DHT (распределенная хеш-таблица) использует тот факт, что узлы идентифицируются просто публичными ключами Ed25519, и тем, что корнем дерева является узел с минимальным ключом. Каждый узел знает путь до корня и то, что корень лежит на одном из концов пространства ключей. Таким образом, новая DHT является просто прямой из ключей, отсортированной от минимального к максимальному ключу, начиная с корня дерева.
Каждый узел обязан построить маршрут от себя к предыдущему узлу на этой прямой (к узлу с более низким ключом, расположенным по DHT ближе к корню). Предшественник использует этот путь для направления трафика вниз по DHT, то есть в сторону возрастания ключей. Все промежуточные узлы сохраняют запись в таблице маршрутизации для этого пути. Таким образом, если узел Б устанавливает маршрут к узлу А, то каждый узел на пути от А до Б тоже имеет запись в таблице маршрутизации о пути, которым пойдёт трафик в сторону Б. Если трафик по этому пути не дойдёт (получит таймаут), то узлы на любом конце этого оборванного пути шлют явное уведомление том, что путь прерван, что позволяет DHT быстро реагировать на обрывы путей и изменения топологии.
Пакеты перенаправляются в сторону максимального ключа, который не выше узла назначения. Эти решения маршрутизации принимаются не только на концах пути, а любой нодой по пути следования пакета: если А является предком узла Б (имеет более низкий ключ), А не обязан маршрутизировать трафик до Б. Трафик, проходящий через какой-нибудь узел между А и Б пойдёт к Б, не попадая к А. Корень дерева, как и все другие пиры-предки, служат лишь дополнительными каналами DHT, о которых узлы знают "просто так", так как они узнали об этом при начальном построении дерева.
Чтобы узнать о своих соседях по ключам, узлы без предков периодически шлют бутстрап-пакет. Этот бутстрап-пакет перемещается по DHT пока не достигнет максимального предка. Этот пакет содержит метку расстояния от корня дерева до отправителя, которая используется предком для отправки подтверждающего пакета. Подтверждающий пакет содержит содержит метку расстояния от корня до предка, которая используется отправителем для нахождения пути по DHT.
Вместо поиска путей к узлам, узлы просто направляют трафик по направлению к ключам узлов через DHT. Во время установки сессии узлы устанавливают исходный маршрут и прозрачно переключаются на него в фоне.
Пути через пространство ключей DHT обычно имеют большую протяженность, нежели пути через связи древовидного пространства (treespace). Дерево является понятием, соответствующим физической топологии (связи узлов). Смешение двух подходов (начальной маршрутизации по DHT и оптимальной передачи информации по реальной топологии) является фактором стабильности. В случае устойчивой сети трафик передается по дереву (ленивая маршрутизация), как это было в более ранних версиях Yggdrasil, при этом нет зависимости от изменений сети на участках, которые не входят в конкретный маршрут, так как при стабильном канале нет зависимости от DHT-координат. В обратном случае, когда устойчивый канал связи нарушается, происходит быстрое реагирование и поиск возможного пути по DHT, который постоянно поддерживается в актуальном состоянии.
IPv6
Сеть работает таким образом, чтобы обратиться к любому узлу можно было лишь по его известному IPv6-адресу из диапазона 200::/7
. В силу основательного изменения протокола сети, теперь вся маршрутизация основана на простой таблице DHT, единственно состоящей из публичных ключей подписи. В Yggdrasil 0.3 и более ранних версиях адрес IPv6 выводился из ключа шифрования, а теперь этот ключ как отдельное значение вовсе отсутствует и выводится математическим путем из ключа подписи.
Yggdrasil 0.4 использует следующий алгоритм образования IPv6-адреса из публичного ключа подписи: 1) первый байт "0x02" является константой, 2) ключ подписи побитово инвертируется, 3) количество лидирующих ненулевых битов составляет второй байт адреса, 4) первый ноль усекается, 5) последующие 14 байт ключа образуют тело адреса.
Итог
Замеры производительности переделанного протокола Yggdrasil внушают большие надежды на стабильность. В свою очередь стабильность - важнейший показатель популяризации сети.
После релиза Yggdrasil 0.4 старый список публичных сервисов и публичных пиров был обнулен. Для связности вашего узла с глобальным сегментом сети необходимо прописать в конфигурационный файл один или несколько новых публичных пиров. Администраторам ресурсов необходимо обновить клиент сети и освежить в конфигурационных файлах веб-сервера и прочего прикладного ПО используемый IPv6, после чего снова добавить свой сервис в список общедоступных.
Стартовые узлы I2P в сети Yggdrasil также обновились, изменения в исходный код уже добавлены. Возможность обращения за ресидом I2P через Yggdrasil возобновится в ближайшем релизе i2pd (2.39.0), но уже сейчас вы можете собрать текущую версию из гит-репозитория вручную и продолжить комфортное использование сети I2P без обращения в обычный интернет.
Ознакомиться с Yggdrasil 0.4 более детально можно в официальном англоязычном блоге, а также на странице релиза.
Оригинальная статья опубликована в блоге дата-центра ITSOFT.