Обнаружение узлов и зашифрованная многошаговая ретрансляция
Как узлы AeroNyx обнаруживают друг друга с помощью подписанных дескрипторов, ведут зеркалируемую Directory Chain и пересылают многослойно зашифрованную полезную нагрузку от перехода к переходу. Реальный чат по умолчанию использует центральный ретранслятор; двухшаговый луковый маршрут включается по желанию.
Узлы AeroNyx находят друг друга с помощью подписанных дескрипторов с ограниченным сроком действия и могут пересылать полезную нагрузку, зашифрованную сквозным шифрованием, от перехода к переходу, причём каждый ретранслятор снимает только свой слой шифрования. Сегодня реальный пользовательский чат по умолчанию проходит через центральный ретранслятор AeroNyx (RelayWS). Маршрутизация чата через узлы — это настройка в приложении, которая включается по желанию (opt-in).
Что работает сегодня
| Возможность | Состояние |
|---|---|
| Подписанное обнаружение узлов и gossip-обмен между пирами | Работает на рабочих (production) узлах |
| Directory Chain (подписанная история дескрипторов каждого узла, зеркалируемая между узлами) | Работает на рабочих узлах |
| Двухшаговая луковая ретрансляция между узлами | Работает на рабочих узлах. В приложении включается по желанию и по умолчанию выключена |
| Анонимные почтовые ящики, доступные через луковую ретрансляцию | Работают на рабочих узлах. Обычный чат их не использует. В приложении есть отдельная бета-функция отправки в почтовый ящик |
| Маршруты с тремя переходами ретрансляции | Политика и зонд существуют в исходном коде узла. Приложение их не использует |
Эндпоинты с именем хоста https:// для узлов за шлюзом | В текущих выпусках узла |
| TLS с привязкой к идентичности на порту публичного API, без доменного имени и центра сертификации | Работает на рабочих узлах. Узлы используют его между собой, если пир объявляет о нём. Поддержка в приложении находится в разработке |
| Передача конечным луковым узлом во входящие ретранслятора получателя | Работает на рабочих узлах |
Начальные узлы, закреплённые оператором (discovery.pinned_seeds) | В текущих выпусках узла |
| Транспорт чата по умолчанию | Центральный сервис RelayWS под управлением AeroNyx |
Централизованные и децентрализованные пути работают параллельно.
Как работает обнаружение
Каждый узел публикует дескриптор, подписанный ключом его идентичности Ed25519. Дескриптор включает идентификатор узла, время выпуска и истечения срока действия, необязательный публичный эндпоинт, флаги возможностей (например, промежуточный луковый ретранслятор или ретранслятор чата), приблизительные подсказки о ёмкости и ключ, используемый для лукового шифрования. Узлы отклоняют дескрипторы, срок действия которых истёк или подпись которых недействительна.
- Gossip-обмен ограничен. Обмен с пирами ограничен по частоте и регулируется политикой, а сообщения имеют ограничения по размеру.
- Восстановление после перезапуска. Узел хранит локальный кеш пиров и после перезапуска возвращается к настроенным начальным (seed) эндпоинтам. Операторы также могут закреплять начальные узлы.
- Выбор маршрута. В качестве кандидатов на роль ретранслятора рассматриваются только свежие дескрипторы с пригодным эндпоинтом и луковым ключом.
Какие эндпоинты может указывать дескриптор
Подпись доказывает, кто опубликовал дескриптор, но не то, что к его эндпоинту безопасно обращаться. Поэтому узел принимает только две формы эндпоинта:
- публичный IP-адрес по
httpилиhttps; диапазоны loopback, частные, link-local, CGNAT, документационные, многоадресные и зарезервированные отклоняются; - URL
https://с публичным DNS-именем. Одноуровневые имена,localhostи частные суффиксы, такие как.local,.internalи.home.arpa, отклоняются.
Имена хостов разрешаются в момент подключения через резолвер, который отбрасывает все непубличные адреса, поэтому имя нельзя направить на сам узел, частную сеть или сервис метаданных облака. Клиенты пиров также игнорируют настройки прокси и никогда не следуют перенаправлениям.
Форма с именем хоста существует для того, чтобы в сети могли участвовать узлы без собственного IP-адреса, например TEE-узел за облачным шлюзом.
Закреплённые начальные узлы
Узел, который запускается без снимка от оператора, доверяет только тем идентичностям, которые у него уже есть, поэтому в итоге он может доверять только самому себе. На этот случай оператор может указать идентичность, ожидаемую по определённому адресу:
[discovery]
pinned_seeds = ["<64-hex node id>@<public ip>:<port>"]
- Закреплённая идентичность принимается впервые только после обмена по TLS с привязкой к идентичности, закреплённому за этой идентичностью.
- Каждый последующий дескриптор закреплённой идентичности, из любого источника, должен сохранять закреплённый адрес и объявлять TLS с привязкой к идентичности.
- Доверие не передаётся: другие дескрипторы в ответе начального узла остаются недоверенными кандидатами.
- Снятое закрепление не может вернуться из старого кеша или резервной копии.
Directory Chain
Каждый узел также ведёт подписанную историю событий своего дескриптора, связанную хешами, которая называется его Directory Chain. Другие узлы могут зеркалировать эту историю, получать объекты дескрипторов и запрашивать доказательства включения для конкретного дескриптора. Пиры, закреплённые оператором, могут подписывать контрольные точки наблюдения по историям, которые они видели.
Нет ни глобального реестра, ни единственного координатора: каждый узел подписывает собственную историю, а другие её зеркалируют и проверяют.
TLS с привязкой к идентичности
Для доступа к узлу по HTTPS обычно нужны доменное имя и сертификат от центра сертификации, а большинство узлов AeroNyx доступны только по IP-адресу. Вместо этого узел подтверждает свой HTTPS-эндпоинт собственной идентичностью Ed25519.
- Как это работает. Узел создаёт обычный TLS-ключ ECDSA P-256 и самоподписанный сертификат. Одно альтернативное имя субъекта несёт привязку,
aeronyx-tls-binding:v1:<node id>:<expiry>:<signature>, где подпись создаётся ключом идентичности узла над дайджестом с разделением доменов, построенным из открытого ключа самого сертификата, идентификатора узла и срока действия. Рукопожатие TLS 1.3 доказывает, что узел владеет ключом сертификата. Ключ идентичности никогда не подписывает рукопожатие. - Что проверяет клиент. Проверяющая сторона принимает сертификат только для того узла, к которому намеревалась подключиться: ровно одна привязка, ожидаемый идентификатор узла, срок действия не истёк, остаток срока действия не более 31 дня и действительная подпись над ключом именно этого сертификата. Сертификат, выданный центром сертификации, этой проверке не удовлетворяет.
- Тот же порт. Порт публичного API (
8422/TCP) обслуживает оба варианта: соединение, которое начинается с рукопожатия TLS, получает TLS, а всё остальное, как и прежде, получает обычный HTTP. Он включён по умолчанию (discovery.public_api_identity_tls). - Между узлами. Узел, чей подписанный дескриптор объявляет функцию протокола
anpf1-ibt1, обслуживает TLS с привязкой к идентичности. Пир, увидевший эту функцию, обязан подключаться к такому узлу по TLS, закреплённому за его идентичностью, и никогда не переходит на обычный HTTP. Функция покрыта подписью дескриптора, поэтому сетевой атакующий не может убрать её, чтобы вынудить к понижению защиты. Если несколько идентичностей заявляют один и тот же эндпоинт, TLS-адрес не формируется и запрос завершается отказом (fail closed). Старые узлы без этой функции и эндпоинты шлюзов с DNS-именем сохраняют прежнее поведение. - Справочные материалы. Исходный код и зафиксированные тестовые векторы: aeronyx-node-tls.
В результате информация о маршруте луковых переходов, gossip-обмен, синхронизация каталога и трафик свидетелей между узлами больше не читаются в канале. Поддержка подключения к узлам таким способом в приложении находится в разработке.
Как работает многошаговая ретрансляция
- Отправитель оборачивает полезную нагрузку в один слой шифрования на каждый переход, используя опубликованный луковый ключ каждого ретранслятора.
- Каждый ретранслятор проверяет подпись, временную метку и состояние защиты от повторов предыдущего перехода, снимает свой слой и пересылает оставшийся непрозрачный блок данных. Он никогда не видит внутренние слои.
- Последний (конечный) узел передаёт сообщение во входящие ретранслятора получателя (по умолчанию это центральный ретранслятор) и лишь после того, как ретранслятор его примет, возвращает подписанную квитанцию. Квитанция связывает идентификатор маршрута, обязательство по полезной нагрузке, идентичность конечного узла и время доставки. Она доказывает, что сообщение принято на хранение ретранслятором, а не то, что получатель его прочитал. Узел с отключённой передачей хранит сообщение в собственном хранилище и подписывает квитанцию того же вида, поэтому по одной квитанции эти два случая различить нельзя.
Что видит каждая сторона
| Сторона | Видит | Не видит |
|---|---|---|
| Входной узел | Сетевой адрес отправителя, запечатанный слой и следующий переход | Кому адресовано сообщение и его содержимое |
| Конечный узел | Ключи отправителя и получателя и шифртекст | Сетевой адрес отправителя и содержимое |
| Центральный ретранслятор (получает переданное сообщение) | То, что показывает ему любая отправка: ключи отправителя и получателя, временные метки и размеры | Сетевой адрес отправителя и содержимое |
Ни один отдельный узел не связывает ваш сетевой адрес с тем, кому вы пишете. Конечный узел и центральный ретранслятор оба видят, кто кому писал.
Протокол принимает не более трёх проверенных переходов ретрансляции. Приватный маршрут приложения использует два. Ограничения против злоупотреблений на ретрансляторах описаны в статье Защита слепого ретранслятора от злоупотреблений.
Чат в приложении
- По умолчанию: сообщения проходят через центральный сервис RelayWS. Содержимое сообщений зашифровано сквозным шифрованием, но сервис обрабатывает метаданные доставки. См. Интеграция клиента с ретранслятором чата.
- Приватный маршрут (по желанию, по умолчанию выключен): когда он включён и маршрут готов, приложение сначала отправляет личные сообщения по двухшаговому луковому маршруту. Если ни один луковый маршрут не принимает сообщение, приложение удерживает его на устройстве и не использует стандартный ретранслятор, пока вы не разрешите это для данного сообщения.
- Анонимный почтовый ящик (бета): отдельный канал отправки, который работает, только пока установлено подключение к сети приватности. Обычные разговоры его не используют.
Размеры при получении из анонимного почтового ящика
Раньше результат получения из почтового ящика был одним образом фиксированного размера в 163 130 байт независимо от элемента, поэтому короткое сообщение обходилось ответом примерно в 160 КиБ. Версия 2 получения, согласуемая подписанной функцией протокола anpf1-ampc1, дополняет запечатанный элемент до наименьшего из пяти классов размера (4 204, 16 492, 65 644 или 131 180 байт либо максимум кодека). Элемент размером 4 096 байт теперь передаётся как 4 518 байт.
TEE-узел
Один рабочий узел работает внутри доверенной среды выполнения Phala Cloud (dstack на Intel TDX). Он служит только анонимным почтовым ящиком и луковым ретранслятором: его VPN отключён, MemChain выключен, а ключ его идентичности поступает из сервиса ключей dstack. Он доступен только через имя хоста TLS на шлюзе, и именно поэтому были добавлены эндпоинты с именем хоста. Приложение в настоящее время не проверяет TEE-аттестацию узла.
Актуальное состояние
Агрегированное состояние сети публикуется по адресу:
GET https://api.aeronyx.network/api/privacy_network/vpn/public/network-stats/
Агрегаты ретрансляции и обнаружения отображаются в разделе data.protocol_status, например peer_store.blind_relay и peer_store.peer_quorum. При их чтении учитывайте два момента:
- Агрегаты на уровне узлов учитывают только узлы с heartbeat за последние 120 секунд, поэтому узел, находящийся не в сети, исчезает из таких счётчиков, как
protocol_status.reported_nodes.network.total_nodesиnetwork.vpn_nodesпо-прежнему считают зарегистрированные активные узлы, в сети они или нет. - Счётчики синтетических зондов (
probe_*,two_hop_probe_*) измеряют работоспособность путей. Они не являются пользовательским трафиком.
Публичный ответ содержит только счётчики, группы состояний и временные метки. Он никогда не включает идентификаторы узлов, эндпоинты, идентификаторы маршрутов, полезную нагрузку, получателей, IP-адреса клиентов, данные DNS или рёбра социального графа. См. Статистика сети и граница приватности.
<!-- faq:start -->Часто задаваемые вопросы
Проходят ли мои сообщения в чате AeroNyx через децентрализованные узлы?
По умолчанию нет. Сообщения проходят через центральный сервис RelayWS. Вы можете включить в приложении приватный маршрут, который отправляет личные сообщения по двухшаговому луковому маршруту через узлы, когда такой маршрут готов. Если ни один маршрут не принимает сообщение, приложение удерживает его, пока маршрут не станет доступен или пока вы не разрешите отправить это сообщение через стандартный ретранслятор.
Может ли узел-ретранслятор читать пересылаемые сообщения?
Нет. Ретранслятор снимает только свой слой шифрования и пересылает непрозрачный блок данных. Кроме того, содержимое сообщений зашифровано сквозным шифрованием между участниками разговора.
Что такое Directory Chain?
Directory Chain — это собственная подписанная история дескрипторов каждого узла, связанная хешами. Другие узлы её зеркалируют и могут запрашивать доказательства включения. У неё нет глобального координатора.
Как узел за шлюзом может присоединиться к сети?
Он может опубликовать имя хоста https:// в качестве своего эндпоинта. Другие узлы разрешают это имя в момент подключения и используют только публичные адреса, поэтому имя нельзя перенаправить на частные или внутренние цели.
Почему публичная страница статистики показывает больше зарегистрированных узлов, чем находится в сети?
network.total_nodes и network.vpn_nodes считают зарегистрированные активные узлы независимо от того, в сети они или нет. Сравнивайте их с network.online_vpn_nodes. Количества по протоколу и пересылке включают только узлы со свежим heartbeat.
Нужны ли узлам доменное имя или центр сертификации для HTTPS?
Нет. Узел может подтвердить свой HTTPS-эндпоинт собственным ключом идентичности: его TLS-сертификат несёт подпись идентичности узла над ключом сертификата, и клиент или пир, знающий идентификатор узла, может её проверить. Узлы за шлюзом по-прежнему могут использовать вместо этого имя хоста https://.
Что доказывает подписанная квитанция о доставке?
Она доказывает, что конечный узел принял сообщение на хранение в ретрансляторе, на практике — во входящие ретранслятора получателя. Она не доказывает, что получатель увидел или прочитал сообщение. Для этого используйте квитанции о доставке и прочтении протокола чата.
<!-- faq:end -->