Это опять Revertron, в прошлой статье я разобрал, как устроена сеть Yggdrasil: криптоадресация, spanning tree, жадная маршрутизация, bloom-фильтры. Я обещал, что это первая статья цикла - и обещал рассказать новости. А новостей много: я переписал Yggdrasil с Go на Rust. Это и есть Yggdrasil-ng (next generation).

Сразу спойлер: рерайт у меня занял 3.5 дня. После этого я неделю чинил один баг. И на этом проекте я уже собрал Android-мессенджер. Обо всём по порядку.

Откуда вообще взялась эта идея

У меня есть свой проект - мессенджер Mimir для Android, основанный на Yggdrasil. До недавнего времени сетевая часть в нём работала через Go-библиотеку yggquic (Yggdrasil с QUIC внутри). Я туда регулярно вносил правки, но… делал это через веб-интерфейсы разных нейросетей - ChatGPT, Kimi и других. Кидаешь файл, просишь поменять, копируешь обратно. Каждое изменение - отдельный ритуал.

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

Потом по работе я попробовал Claude Code - это CLI-инструмент от Anthropic, который интегрируется с IDE (у меня RustRover от JetBrains плюс Android Studio). Принципиальное отличие - Claude видит весь проект сам, читает файлы, запускает тесты, правит код прямо в репозитории. Не “скопируй мне функцию, я её перепишу”, а “вот задача, разберись и сделай”. Я вдохновился разработкой с LLM как таковой, причём на новом уровне - не для генерации отдельных функций, а для реальной работы над проектами.

А в русскоязычном сообществе Yggdrasil давно ходила шутка: “надо бы переписать Yggdrasil на Rust”. Несколько лет об этом смеялись. Браться за такой крупный проект без знания Go было страшно - Yggdrasil это не “hello world”, это сетевой стек с криптографией, async I/O, CRDT-маршрутизацией и особенно с каким-то кастомным актор-фреймворком.

И в один вечер опять зашёл разговор на эту тему, я прикинул то, насколько легче мне будет разрабатывать мессенджер, и психанул! Склонировал три репозитория - yggdrasil-go (сам демон), ironwood (библиотека маршрутизации) и phony (actor framework, на котором построен Go-код). Открыл Claude Code в этой папке. Запустил команду /init, и понеслось!

3,5 дня на рерайт

Это не опечатка. От git init Rust-проекта до работающего демона, который пингует Go-узлы по сети - три с половиной дня.

Конечно, “работающий” - это не “production-ready”. Тестов было мало, фич меньше, чем в Go-версии, кое-где вместо нормальной обработки ошибок стояло unwrap() (этот пассаж написала нейронка, на самом деле она такого не допускала ;) ). Но базовая сеть работала: Rust-узел подключался к публичным пирам, строил spanning tree, искал маршруты через bloom-фильтры, шифровал трафик и обменивался пакетами с Go-узлами.

Что важно понять: я сам не писал код. Я давал задания. Всё началось с анализа кода на Го. Я не помню точный промпт, но он был примерно из трёх предложений. Claude долго жевал гошные исходники и выдал некий обширный план того, как будет переписывать проект на Rust. Я очень внимательно читал план, чтобы нейронка не пошла по неверному пути прямо с самого начала, ибо дальше будет сложнее развернуться. Упирался в лимиты Claude Pro, приходилось делать перерывы на кофе, еду и даже какие-то дела по дому. Ложился спать в шесть утра. Да, наверное именно поэтому получилось 3,5 суток на перевод.

Получилось 7 фаз работы:

  • Фаза 1. Фундамент: типы, криптография, wire-протокол, конфиг.

  • Фаза 2. Маршрутизация: spanning tree, bloom-фильтры, pathfinder, роутер.

  • Фаза 3. Сеть: peers, ядро, публичный API.

  • Фаза 4. Шифрование: сессии, рэтчетинг ключей, подписи.

  • Фаза 5. Интеграционные тесты.

  • Фаза 6. Yggdrasil-демон поверх ironwood: TCP-транспорт, TUN, админ-сокет.

  • Фаза 7. Критические фичи: backpressure очередей, оптимизация keepalive.

(Это подсказала нейронка, я уже точно не помню.)

Местами Claude Code справлялся блестяще. Например, он сам обнаружил, что в моей реализации bloom-фильтра нужен тот же алгоритм хеширования (FNV-128), что и в Go-библиотеке bits-and-blooms, иначе Rust-узел не сможет договориться с Go-узлом. Растовые крейты почему-то использовали другие реализации.

Местами было тяжелее. Особенно с конвертацией ключей Ed25519 → Curve25519: в Go-коде использовался кастомный bilinear map (u = (1+y)/(1-y) mod p), и стандартные Rust-крейты так не умеют (так подумал Клод). Пришлось реализовать big-integer арифметику вручную и проверять побайтово, что результат совпадает с Go. Но потом стало понятно, что реализация дичайше медленная! Пришлось хорошо поискать и найти стандартный curve25519-dalek, который это делает быстро.

Через 3,5 дня я подключился к публичной сети Yggdrasil с Rust-узла. Пинговал известные серверы, открывал сайты внутри сети - всё работало. Установил ноду на один из домашних серверов.

Неделя на один баг

А потом начался ад.

Симптом был издевательский: первый час всё работало нормально. Дальше - постепенная деградация. Сначала отваливались один-два узла, потом часть сети, потом маршруты начинало плющить совсем, и сеть шатало (извините). Перезапустишь - снова час всё в порядке, потом опять хрень. На маленьких тестовых сетях (3–5 узлов) баг не воспроизводился вообще: всё чисто. Только в реальной публичной сети с сотнями пиров (на моём публичном пире), и только когда пир проработает достаточно долго.

Я неделю ковырялся по этому поводу вместе с Claude. Перерывали Go-исходники, сравнивали логи, добавляли отладочные сообщения, гоняли захваты пакетов. Несколько раз казалось, что нашли - патч применили, узел подержали час, баг вернулся. Это было особенно обидно, потому что весь остальной код, переписанный с Go, работал правильно - handshake, шифрование, bloom-фильтры, pathfinder.

В итоге всё свелось к пяти строчкам в обработчике пира.

В Yggdrasil узлы периодически обмениваются “подписями” (SigReq/SigRes) - это часть протокола построения spanning tree. Заодно по разнице между отправкой запроса и получением ответа измеряется RTT (время до пира). Этот RTT потом используется при выборе родителя в дереве и вычислении наилучшего пути: при прочих равных предпочитается пир с меньшей задержкой.

Так вот, в моей реализации время отправки засекалось так:

async fn peer_reader(...) {
    let mut reader = BufReader::new(conn_read);
    let sig_req_send_time = Instant::now();  // ← один раз на весь reader
    loop {
        //...
        // на каждый входящий SigRes:
        let rtt = sig_req_send_time.elapsed();
        router.handle_response(peer_id, &peer_key, &res, rtt);
    }
}

Заметили? sig_req_send_time создавалась один раз, при старте обработчика пира. И дальше elapsed() от неё измерял не “время с момента отправки запроса”, а время с момента подключения к этому пиру.

Что это означало на практике:

  • Только подключились - RTT 0 секунд, всё норм.

  • Через минуту - RTT каждого ответа от этого пира 60 секунд.

  • Через 10 минут - 600 секунд.

  • Через час - 3600 секунд.

Алгоритм Spanning tree смотрел на эти цифры и принимал решения: “у пира A задержка час, у пира B - два часа, выберу A”. Потом тот же узел через минуту: “у A - час и одна минута, у B - две и одна минута”. Дерево начинало плыть, координаты узлов разъезжались, и маршруты ломались - причём тем сильнее, чем дольше узел работал. На свежем подключении всё было ок, поэтому на коротких тестах баг не ловился.

Фикс - буквально хранить время отправки по каждому SigReq отдельно, в HashMap<PeerId, Instant> внутри роутера. Когда отправляем запрос - записываем время. Когда приходит ответ - берём оттуда. Дельта получается осмысленная.

Мораль простая. LLM сегодня может за несколько дней переписать сетевой стек средней сложности - это правда, я это видел своими глазами. Но это не значит, что человек больше не нужен. Большой проект Claude Code тащит на себе уверенно. А на тонком семантическом нюансе в пяти строках - где Instant::now() стоит не в той функции - может споткнуться так, что баг будет ловиться неделю. Особенно если он не воспроизводится на коротких прогонах, и обнаружить его можно только в живой сети.

И ещё одна вещь, важная для понимания. Это не баг “Claude написал плохо”. В Go-коде это решено правильно (там время отправки хранится в структуре пира). Но при переписывании логики на Rust LLM “оптимизировал”: подумал, что один раз засечь время хватит, ведь reader всё равно читает только этого пира.

Что нового в Yggdrasil-ng

Раз уж я переписывал, я не стал слепо копировать Go-версию. Несколько вещей в Rust-варианте сделаны иначе или добавлены с нуля.

Единый бинарник. В оригинале два исполняемых файла: yggdrasil (демон) и yggdrasilctl (управление). В Rust-версии это один бинарник. Запускаешь без аргументов - это демон. Запускаешь с yggdrasil getPeers - это команда управления. Удобнее ставить, удобнее писать скрипты.

Конфиг в формате TOML. Для проектов на Rust это идиоматичный формат, и я помню тысячи раз за эти семь лет как люди совершали простейшие ошибки в HJSON, который использует гошная версия.

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

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

И главное - CKR.

CKR: VPN через Yggdrasil

CKR - Crypto-Key Routing. Идея простая: вы прокидываете обычные IPv4 или IPv6-подсети поверх mesh-сети Yggdrasil, маршрутизируя их по ключу через конкретный узел.

Зачем это нужно - несколько типичных сценариев:

  • Многоузловой VPN. Произвольное число узлов, можно создать свою IPv4-локалку внутри Yggdrasil, о которой знают только ваши узлы. Можно играть в старые сетевые игры, не поддерживающие IPv6, как Hamachi - помните такой?

  • Site-to-site. Соединить две локальные сети (например, домашнюю и офисную) - устройства в обеих сетях видят друг друга по обычным локальным IP, как будто они в одной подсети, а под капотом трафик идёт через Yggdrasil.

  • Exit-node. Один узел в сети раздаёт через себя “обычный” интернет - например, у вас сервер в неавторитарной стране, и весь ваш трафик идёт через Yggdrasil до сервера, а оттуда уже в интернет.

Технически это работает так: в конфиге клиента вы пишете соответствие “такая-то подсеть → такой-то ключ” (подсетью может быть 10.0.0.0/24 или даже 0.0.0.0/0). Когда на TUN-интерфейс приходит пакет с адресом из этой подсети, Yggdrasil не дропает его, а заворачивает в свой собственный зашифрованный туннель и отправляет узлу-владельцу подсети. Тот разворачивает и пускает в свою локальную сеть (или в интернет, если это exit-node).

Это полноценная альтернатива WireGuard или OpenVPN (никому не говорите!). И намного легче делать Multi-hop VPN (или Double VPN), когда вы входите в сеть через один IP, а в интрнет выходите через другой. Пакеты летят через всю сеть.

CKR работает на Linux, Windows и macOS (и как клиент на Android). Маршруты в системе устанавливаются автоматически через кросс-платформенную библиотеку route_manager - никаких ручных ip route add.

Приложения на новом стеке

После того как Rust-демон стал стабильным, я вернулся к мессенджеру Mimir. Старая Go-библиотека yggquic (QUIC-стек внутри Yggdrasil) пошла на свалку. Вместо неё теперь - отдельный Rust-крейт ygg_stream, построенный поверх Yggdrasil-ng.

ygg_stream - это транспортный слой поверх Yggdrasil. Он реализует TCP/KEY: TCP-подобный протокол, в котором вместо IPv4/IPv6-адресов используются 32-байтные ed25519-ключи. Полная семантика TCP (3-way handshake, надёжная упорядоченная доставка, FIN/RST, congestion control по Reno, RTT по Jacobson/Karels), плюс UDP-подобные датаграммы - fire-and-forget, без рукопожатия. Адресацию обеспечивает сам Yggdrasil, шифрование - тоже его, поверх ничего лишнего не накручивается (а в случае с QUIC добавлялся ненужный оверхед с сертификатами и шифрованием).

Mimir получает из этого крейта обычные “соединения” и “датаграммы”, и вся прикладная логика мессенджера работает с ними так же, как раньше с QUIC-соединениями из Go. API получился практически идентичный старому: Node.connect(key, port), Conn.read/write, send_datagram.

В Android-проект ygg_stream экспортируется через UniFFI - инструмент Mozilla (используется даже в Firefox for Android), который из публичного API Rust-крейта генерирует биндинги под Kotlin/Swift/Python. Один раз пишешь Rust - получаешь готовые обёртки. Сборка идёт через cargo ndk - нативные .so-файлы плюс сгенерированные .kt-обёртки.

Mimir - это “лёгкий” сценарий: приложение использует только клиентскую часть стека, без TUN-интерфейса. Полный узел внутрь мобильного приложения с TUN-ом - это уже Yggdrasil-ng для Android. Это второе приложение, которое я сейчас разрабатываю - аналог официального Android-клиента Yggdrasil (я тоже его мейнтейнер, и у которого внутри Go-демон), только с Rust-сердцем. Здесь уже доступны все “взрослые” фичи: TUN-интерфейс, внутрисетевые DNS-серверы с блокировкой рекламы и аналитики, и главное - CKR. То есть с телефона можно поднять туннель к серверу и пустить через него весь трафик устройства, или объединить телефон с домашней сетью site-to-site.

В опенсорс это приложение я пока не выложил - думаю, как его правильно распространять. На сегодня оно живёт в виде бесплатных APK-сборок, которые я выкладываю в Telegram-чат сообщества.

И буквально сегодня я доделал ещё одну важную вещь, которая стоит отдельного упоминания. Раньше у меня TUN-интерфейс читался и писался с Kotlin-стороны: Android поднимает TUN, Kotlin-код в цикле читает из него пакеты, передаёт в Rust-библиотеку, получает обратно пакеты, отправляет в TUN. Каждый пакет совершал минимум четыре пересечения JNI-границы и проходил через Java-аллокаторы.

Сегодня я перенёс работу с TUN целиком внутрь Rust-крейта: FileDescriptor отдаётся в Rust один раз, дальше всё (чтение, шифрование, маршрутизация, расшифровка, запись) живёт на Rust-стороне без участия JVM. Результат - прирост скорости в 9–10 раз (пропускная способность через CKR-туннель), резко меньшее потребление памяти и почти полное снятие нагрузки с GC.

Что дальше

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

  • Шифрование сессий - как именно работает сессионный handshake, рэтчетинг ключей, почему Ed25519 приходится конвертировать в Curve25519 и как это устроено.

  • Pathfinder изнутри - bloom-фильтры, path lookup, broken paths.

  • CKR на практике - отдельная статья с конкретными конфигами: как поднять exit-node, как сделать site-to-site, какие подводные камни.

  • Android-разработка с UniFFI - для тех, кто хочет встраивать Rust-код в мобильные приложения.

Что больше интересно - пишите в комментариях, расставлю приоритеты по запросам.

Спасибо, что дочитали. Yggdrasil-ng - открытый проект, исходники здесь, баг-репорты приветствуются, PR-ы не очень.

Комментарии (33)


  1. nitro80
    25.04.2026 03:09

    Автор, похоже в https://t.me/Yggdrasil_ru меня забанили, как туда попасть?


    1. Revertis Автор
      25.04.2026 03:09

      Писать мне в личку. Да, надо быть осторожным, мой бот на входе даёт только 30 секунд на ввод цифр.


  1. qazpoi12
    25.04.2026 03:09

    Огромное спасибо за статью! Теперь понял, что такое CKR и зачем он нужен.


    1. Revertis Автор
      25.04.2026 03:09

      Ну вот, значит уже не зря писал.


  1. Dhwtj
    25.04.2026 03:09

    Если сделали новые крейты то опубликуйте их в git и на crates.io

    Дело, похоже, полезное. Ну не люблю я Go.

    P.S. ночью надо спать


  1. Dhwtj
    25.04.2026 03:09

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


    1. Revertis Автор
      25.04.2026 03:09

      Да, я не стал добавлять транспорты QUIC и WS, о добавлении которых автор yggdrasil-go уже жалеет.


      1. ufm
        25.04.2026 03:09

        Добавь, пожалуйста, автопиринг. Без него - беда-печаль-огорчение.


        1. Revertis Автор
          25.04.2026 03:09

          Что за автопиринг?


          1. ufm
            25.04.2026 03:09

            MulticastInterfaces


            1. Revertis Автор
              25.04.2026 03:09

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


      1. Pinkbyte
        25.04.2026 03:09

        Ну WS-транспорт может быть полезным чтобы подольше от DPI прятаться. Другие варианты имеют уж очень приметные сигнатуры, а QUIC бывает целиком отсыхает из-за РКН - вот тут да, в наших реалиях он бесполезен.

        Да, "это не цель Yggdrasil" (c), но все же если что-то работает - оно имеет право на жизнь.

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


        1. mikluha
          25.04.2026 03:09

          Поверх go реализации отлично строятря GRE и GIF туннели с ipv4/ipv6 внутри. Учитывая что MTU на yggdrasil интерфейсе большой (на порядки больше 1500 байт), то туннели не страдают от низкого MTU. Все работает идеально


          1. Pinkbyte
            25.04.2026 03:09

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

            Хотелось бы встроенного функционала, чтоб не конфигурять в куче мест, но я понимаю - "не цель" :-)


      1. mikluha
        25.04.2026 03:09

        А какие с ним проблемы? У меня на одной публичной ноде (рф) 25% QUIC и 27% WS клиентов.

        QUIC работает в РФ не везде и не у всех, а как поднял WS транспорт жалоб на него не было

        На другой ноде (в Азии) почти 31% QUIC соединений (там WS не настроено)

        Я сам обычно QUIC использую и проблем с ним не замечал.

        Прелесть WS в том что оно отлично замаскировано если ygg-go работает как бэк для nginxа где еще и сайты крутятся (у меня такие инсталляции тоже есть, но это не публичные ноды)


        1. Pinkbyte
          25.04.2026 03:09

          Я лично замечал когда HTTP/3 подымал на своих сервисах - что браузеры начинают "болеть" при доступе на них на некоторых провайдерах. Сервера как в РФ, так и зарубежом, провайдеры разные, но все в РФ. При этом если пробовать достучаться до зарубежного сервера с других места(не из РФ) - всё тип-топ. А самая дичь - что это непостоянно и не везде такие проблемы, что добавляет увлекательности отладке. Глазеть на то, что значительная часть пакетов по UDP/443 не долетает до точки назначения - веселого мало.


  1. gudvinr
    25.04.2026 03:09

    But why?


    1. Revertis Автор
      25.04.2026 03:09

      Я в статье хорошо это объяснил.


  1. Xelld
    25.04.2026 03:09

    Интересно, пишите ещё :)

    Я бы почитал про pathfinder и вообще про сходимость сети подробнее.


  1. casper_por
    25.04.2026 03:09

    Отличная работа! С точки зрения выбирания что дальше - интересно всё, но в данный момент больше интересует CKR на практике ввиду новых ограничений, ну и так же очень рассчитываю на полную транспортную совместимость в перспективе с go версией


  1. NickUkoloff
    25.04.2026 03:09

    ох уж это неутомимое желание переписать всё на раст...
    особенно с помощью ллмки


    1. Revertis Автор
      25.04.2026 03:09

      Каковы минусы?


      1. gudvinr
        25.04.2026 03:09

        Всё на раст

        https://www.opennet.ru/opennews/art.shtml?num=65278

        С помощью ллмки


        1. Revertis Автор
          25.04.2026 03:09

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


      1. QtRoS
        25.04.2026 03:09

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


        1. Revertis Автор
          25.04.2026 03:09

          Почему это? Язык программирования вдруг сменился чем-то нечитаемым, что ли?


          1. QtRoS
            25.04.2026 03:09

            Давайте "обстучим" мнение об нейтрального/нейронного арбитра. Вот что отвечает LLM, если попросить расписать какие могут быть минусы перехода вашего проекта на Rust:

            1. Точка зрения "Контрибьюторы и Сообщество"

            Это, вероятно, самый болезненный аспект перехода.

            • Потеря текущего пула контрибьюторов: Оригинальный yggdrasil-go написан на Go, который известен своей простотой и низким порогом входа. Многие текущие контрибьюторы (особенно из "энтузиастской" среды, сетевых инженеров и Go-разработчиков), скорее всего, не владеют Rust. Рерайт фактически заставит их либо изучать новый язык (что требует времени), либо уйти из проекта

            Читать целиком
            • Проблема "Псевдо-активных контрибьюторов": Автор рерайта (Yggdrasil-ng) честно признался, что не писал код сам, а давал задания нейросети Claude. Если основная масса "новых" контрибьюторов будет генерировать код через LLM, в проекте резко возрастет количество кода, который компилируется, но содержит логические ошибки. Это приведет к падению качества ревью, так как поддерживать и проверять такой код сложнее, чем написанный вручную.

            2. Точка зрения "Стабильность и Логические Ошибки"

            В отличие от memory safety ошибок, Rust не спасает от ошибок логики и многопоточности (data races), которые являются бичом сетевых протоколов.

            • Пример из практики (Гонка таймеров): В ходе переписывания на Rust была совершена классическая ошибка — изменение замыкания переменной в асинхронном потоке. Автор подсчитал время RTT для пиров неправильно (один раз в момент старта читателя), из-за чего задержка росла с каждой секундой работы сети. Этот баг не проявился на малых тестовых сетях, но убивал большую публичную сеть через час работы.

              • Парадокс: Rust безупречно управляет памятью, но для сетевых протоколов критична математика состояний. Проверка borrow checker не нашла бы проблему, которая убивала сеть через 60 минут.

            • Сложность отладки в распределенных системах: Yggdrasil — это не монолит, а распределенный маршрутизатор с DHT, Spanning Tree и CRDT-подходами. Баги, которые в Go можно было отловить дебаггером и panic() с стектрейсом, в Rust при неправильном использовании unwrap() или expect() приведут к тихому падению узла, что в распределенной системе диагностировать крайне трудно.

            3. Точка зрения "Поддержка и Сопровождение"

            Проект Yggdrasil имеет сложную кодовую базу, основанную на акторной модели (фреймворк phony).

            • Миграция "Бездны": Полный рерайт — это не перевод синтаксиса 1:1. Языки имеют разные парадигмы конкурентности. Go использует горутины и каналы (свой акторный фреймворк). Rust использует async/await (tokio) или акторные крейты (actix, ractor). Переписывать логику акторов, управляющих маршрутизацией, нужно вручную. Малейшее различие в порядке обработки сообщений приведет к рассинхронизации с протоколом оригинальной сети.

            • Долг перед совместимостью: Rust-версия должна быть байт-код-совместима с Go-версией по wire-протоколу. Как показала практика, это очень тонкая работа: даже реализация хеширования FNV-128 или алгоритма конвертации ключей Ed25519->Curve25519 должна идеально совпадать, иначе ноды не увидят друг друга в DHT.

            • Документация vs Код: Go версия уже много лет является "черным ящиком" со сложной матчастью, где оригинальный автор признавался, что документирует мысли "в виде каши". Rust версия, написанная нейросетью, рискует стать еще более сложной для понимания будущими сопровождающими, которые не участвовали в "магии" конвертации ключей и алгоритмов.

            4. Точка зрения "Технический долг и Цикл разработки"

            • Инкрементальные улучшения против "Big Rewrite": В разработке ПО известен анти-паттерн "полного переписывания". Go-версия, хоть и имеет свои недостатки (сборщик мусора, который мешает встраиванию в другие языки), работает и стабильна в продакшене (игрушечный проект вырос в рабочую сеть). Переписывание замораживает развитие функциональности на годы (пока Rust-версия не догонит Go по возможностям).

            • Проблема с Embedded-разработкой (Ironwood): Рерайт на Rust был мотивирован созданием Android-мессенджера Mimir. Однако текущая архитектура Go изначально плохо подходит для мобильных платформ без накладных расходов на CGO и GC. Rust решает эту проблему (компиляция в lib, отсутствие рантайма). Но: поддержка Rust на мобильных платформах (iOS/Android) сложнее, чем Go. Собирать .so и .a библиотеки и биндить их через FFI (Foreign Function Interface) в Swift/Kotlin — технически сложная задача, требующая специфического DevOps-скилла.

            5. Точка зрения "Архитектура протокола"

            • Проблема GC не так страшна: Основная причина рерайта — "GC мешает интеграции". Однако в сетевых overlay-сетях главным тормозом обычно является не GC, а системные вызовы (syscalls) чтения/записи в TUN/TAP интерфейс и копирование пакетов в пространстве пользователя. Оригинальный автор явно указывал, что накладные расходы Go на TUN очень высоки. Rust может это исправить, но также может и оптимизированная Go-библиотека. Переписывать весь проект ради "ускорения в 2 раза", рискуя "полным падением сети каждые 2 часа", — сомнительная экономия.

            И выводы (картинкой для красоты)

            Важно: данная статья учитывалась в ответе.


  1. kujoro
    25.04.2026 03:09

    то есть поставить этот через гайд ацетона не получится?


    1. Revertis Автор
      25.04.2026 03:09

      Не знаю что вы имеете ввиду.


      1. kujoro
        25.04.2026 03:09

        https://habr.com/ru/articles/567012/


        1. Revertis Автор
          25.04.2026 03:09

          Нет, всё так же. Только формат конфига чуть отличается.


  1. K0Jlya9
    25.04.2026 03:09

    переписал Yggdrasil на Rust за 3.5 дня

    :рукалецо:

    Третий день пытаюсь навайбкодить простейшую гуи утилитку для установки yggdrasil на шиндоус комп. Установить/добавить пиров/запустить итп одной кнопкой.

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

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

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


  1. Nemridis
    25.04.2026 03:09

    Спасибо за статью! Пробовал ставить Ygg несколько лет назад, но неудобная настройка и неустойчивая работа отбивали энтузиазм. Теперь еще раз попробую, рад что проект развивается и совершенствуется.