К контенту
habrforever
ЖИВА #router 2026 · ~9 мин чтения

От десктопа к Android и в роутеры — актуализация 2026

оригинал на Хабре habr.com/…/1070276
снимок Wayback не сохранялся
статус на Хабре (ноябрь 2026) доступна
права © автор, переиздание в архивных целях с указанием источника

От десктопа к Android и в роутеры

Архивное переиздание с актуализацией. Оригинал опубликован на Habr (2026), автор — неизвестен. оригинал доступен на Habr по состоянию на ноябрь 2026. Ниже — редакция ноября 2026: что работает сейчас, что изменилось и как правильно повторить рецепт сегодня. Полный текст оригинала — в конце, без купюр.

TL;DR — версия 2026

Идея «роутер раздаёт обход всем устройствам дома» в 2026 живее всех: ставьте OpenWrt 24.x + контейнеры (Xray/sing-box) или MikroTik с нативным WireGuard; прозрачный прокси-тюнель — как в оригинале, только современнее туннель.

Оригинал решал правильную задачу: «включил в розетку — дома всё работает, на всех устройствах, без настроек». В 2026 решение то же, инструменты поменялись: OpenWrt (24.10/25.x) с DSA и контейнерами, RouterOS 7 с контейнерами на ARM-роутерах, GL.iNet «Beryl» серии с предустановленным OpenWrt и поддержкой AWG. ТСПУ (DPI-боксы) стоят у всех крупных российских провайдеров и умеют резать VPN-хендшейки WireGuard, OpenVPN и «голый» Shadowsocks — поэтому «прозрачный» режим требует туннеля с маскировкой, а не голого WireGuard.

Статус оригинала

Архитектура 2026: прозрачный туннель на роутере

Схема из оригинала (все устройства → роутер → политика: «заблокированные подсети/домены → в туннель, остальное — напрямую») осталась идеалом. В 2026 в качестве туннеля берут:

  • sing-box на OpenWrt (TUN-режим, route по гео/спискам), в контейнере или статарте;
  • Xray с TUN-фронтом (tun2socks) и route-set от community;
  • MikroTik: WG-туннель + mangle/route-mark по address-list; на ARM-моделях контейнер с Xray;
  • Awg-роутеры GL.iNet — «из коробки» для нетехнаев.

Списки доменов для «что в туннель»: community-листы (типа antifilter) + свои дополнения.

Что проверить, чего не было в оригинале

  • DNS: роутер должен сам ходить за DoH/DoT, иначе «прозрачность» обходится по DNS-подмене;
  • QUIC: часть блокировок — по UDP/443; решается выключением QUIC в политике или обработкой в туннеле;
  • IPv6: если провайдер даёт v6 — фильтровать и его, иначе «двойная реальность»;
  • апдейты списка: cron-скрипт обновления списков раз в сутки;
  • MTU: туннель с маскировкой чувствителен к фрагментации.

Иллюстрации из оригинала

Иллюстрация из оригинала статьи Иллюстрация из оригинала статьи

Что изменилось с 2026 года

  • OpenWrt 24.10/25.x: DSA-синтаксис, luci-приложения контейнеров
  • RouterOS 7: нативный WireGuard, containers (ARM), обновлённый firewall
  • появились готовые «тревел-роутеры» с AWG/Amnezia из коробки
  • «прозрачный OpenVPN» из старых статей — мёртвая тема: OpenVPN виден DPI
  • в тексте оригинала: у «ванильного» WireGuard статичный хендшейк — DPI его режет; обфусцированный вариант — AmneziaWG

Чек-лист 2026

  • туннель с маскировкой (VLESS/ss2022/AWG), не vanilla WG
  • свои DNS (DoH) на самом роутере
  • политика «в туннель — только то, что надо», остальное напрямую
  • автообновление списков
  • IPv6 не забыт

Вердикт

Оригинальные статьи о «прозрачном обходе в домашней сети» — лучшие своего жанра. В 2026 жанр не умер: просто слово «OpenVPN» в них замените на «sing-box/VLESS», а всё остальное — таблицы маршрутов, списки, DNS — не изменилось.


ОРИГИНАЛ СТАТЬИ (без изменений)

Всем привет, возможно, вы уже пользовались моими L×Box или Sing-box Launcher, я про них уже писал. Если нет, то коротко: на сегодня это уникальные VPN клиенты, которые предоставляют гибкую машрутизацию на множестве VPN соединений одновременно, поддерживают сложные сценарии туннелирования, адаптированы прод экстремальные сценарии использования и обладают широкой диагностикой.

Я сегодня расскажу про развитие ядра этой экосистемы (первая часть тут) Ядро тоже OpenSource https://github.com/Leadaxe/sing-box-lx/ и входит в 10ку самых популярных форков sing-box.

Все оказалось сложнее

В прошлой статье я говорил про два протокола — XHTTP и AmneziaWG 2.0 — и про три правила, которые не дают форку сгнить: минимальное касание апстрима, регулярный ребейз, воспроизводимые сборки. Заканчивалась она обещанием «но это уже следующая история».

История получилась объёмнее, чем я планировал. С июня в репозитории больше 1700 коммитов, 24 стабильных тега линейки 1.14 и под семь десятков спек. Вам интересно, наверное, траектория развития и она такая: ядро, которое начиналось как движок для десктопного лаунчера, сначала обросло адаптациями на Android, а теперь едет на роутер, потому что адаптации одни и те же. Об этом и расскажу.

Новые протоколы

MASQUE. В апстримном sing-box этого протокола нет. У меня теперь есть клиентский outbound type: masque: CONNECT-IP по RFC 9484 — именно CONNECT-IP, а не CONNECT-UDP, который часто под этим словом подразумевают. Разница принципиальная: туннелируются целые IP-пакеты, поверх потока поднимается тот же userspace-сетевой стек, что у WireGuard-эндпоинта, и приложения получают полноценный туннель, а не проброс датаграмм. Главный профиль — Cloudflare WARP, но протокольная часть написана как общий CONNECT-IP, WARP — лишь пресет поверх. Регистрация устройства в WARP сознательно вынесена из ядра: это можете в клиентах смотреть, там есть.

AmneziaWG. В первой статье AWG 2.0 был «фичей форка»; за лето я его довел, до уровня, эталонной клиентской реализации. Тут есть методологическая засада: у AmneziaWG нет спецификации — ни RFC, ни whitepaper, протокол задан реализациями. Поэтому вместо «вроде всё сделали» я провёл формальную сверку по трём независимым первоисточникам: конфиг-парсер amneziawg-tools, netlink-контракт ядерного модуля и наш форк. Результат — паритет 16 из 16 параметров обфускации: junk-пакеты Jc/Jmin/Jmax, паддинги S1–S4, магические заголовки H1–H4 (включая диапазонные) и сигнатурные пакеты I1–I5 с их CPS-мини-языком — все восемь тегов, один в один с эталоном, сквозной цепочкой от конфига до устройства. Причём проверено живым прогоном IpcSet → IpcGet, а не грепом по исходникам — грепом такое как раз легко проглядеть. Добил вопрос AWG поверх WireGuard: вложенные туннели работают, включая AWG-over-AWG через detour —для этого пришлось разрешить фрагментацию внешней UDP-датаграммы, которую ядро по умолчанию запрещает.

Android: среда, где всё против тебя

Десктоп прощает почти всё. Телефон — вообще ничего.

Энергетика. Держать одновременно пару десятков WireGuard/AWG-туннелей на телефоне — это превратить телефон в грелку. Пришлось построить полноценную машину состояний: простаивающие эндпоинты усыпляются (вплоть до полного сноса userspace-устройства), просыпаются лениво при первом дайле, health-check’и научились пропускать циклы, если через узел только что успешно ходил реальный трафик. Результат — минус 31% RSS (Resident Set Size) на боевом конфиге и -80% нагрузки на ядро. Самое сложное здесь было— не усыпить, а понять, кого усыпить. Конфиг sing-box — это граф, обратно направленный: каждый узел знает, через кого он дайлит (detour), но никто не знает, кто дайлит через него. При этом граф ещё и динамический: selector — ручные переключения и urltest автоматические. Все это сделано: теперь сокеты закрываются пачкой, эндпоинты — конкурентно; стопы укладываются в доли секунды.

Сон и пробуждение. После doze телефон просыпается, пользователь первым делом меряет пинг — ну вы поняли: раньше задержка была до 90сек, теперь окно ошибок схлопнулось до одного RTT рукопожатия.

127 секунд тишины. Самый красивый из унаследованных багов: TCP-дайлы через userspace-netstack были единственным классом путей в ядре вообще без таймаута. Единственной границей оставался SYN-бэкофф gVisor: 1+2+4+8+16+32+64 — две с лишним минуты до ошибки, а для доменных назначений — умножить на число адресов. Исправил и это, не ввел ни одного нового таймера — все проверки считаются дельтами по меткам времени, потому что таймеры на Android переживают сон непредсказуемо.

Лето — сезон детективов

Есть класс багов, которые я не люблю больше всего: узел мёртв, а в логе — ни строчки. За лето таких набралось на маленький сериал.

REALITY и три байта из 2023 года. Xray v26.7.11 включил проверку минимальной версии клиента по умолчанию. А апстримный sing-box объявляет в REALITY-рукопожатии версию 1.8.1, зашитую константой ещё в 2023-м. Самое коварное — при провале проверки сервер не рвёт соединение, а прозрачно проксирует его на камуфляжный сайт с настоящим сертификатом. Так и задумано, иначе цензор отличал бы REALITY-сервер по форме отказа. Для пользователя это «узел не работает, лог чист» — неотличимо от кривого short_id или разъехавшихся часов. Фикс — три байта.

XHTTP и косая черта. Сервер XHTTP нормализует свой путь до завершающего / и матчит запросы по префиксу. Наш stream-one слэш срезал: узел, настроенный как /api/v1/feed, дайлился ровно туда, сервер ждал /api/v1/feed/. Итог — 404, который наружу выглядел как вечное молчание, и все XHTTP-узлы подписки казались мёртвыми. Следом довёл packet-up (взаимная блокировка: Xray отдаёт downlink только после первого uplink-пакета, а мы не отдавали conn наверх, пока не придёт ответ на download — обе стороны вежливо ждали друг друга, а reverse-proxy добивал 504-м) и реализовал XMUX — переиспользование HTTP-соединений, которое приходит в конфигах подписок и до сих пор молча отбрасывалось.

Постквантовый VLESS. Узлы из подписки: WebSocket-апгрейд проходит со 101, gRPC отвечает на SETTINGS — и затем сервер молча рвёт соединение. Клиентскую половину encryption: mlkem768x25519plus сделал, серверную сознательно не взял — форк у меня клиентский.

1488 байт проходит, а 1502 байт исчезает :) как тебе такое? Связки вида «VLESS за WARP’ом» (masque → detour → VLESS) на части узлов висли 15 секунд и падали с tls handshake: EOF. Причина такая: второй сегмент соединения пересыл наш ClientHello от своего имени, и если PMTU за ним меньше размера ClientHello, пакет теряется молча — ICMP «fragmentation needed» до клиента не доходит. Лечение: фрагментация первой TLS-записи теперь включается сама, когда outbound дайлит через detour.

Большая часть уникального сетевого профайлера L×Box и Sing-box Launcher строилась на том, что ядро я последовательно учил быть диагностируемым. Это большая работа со своей историей (смотреть тут: OBSERVABILITY), и вот она оказалась супер важной для роутеров и серверов.

Идем в роутеры и на сервера

Иллюстрация из оригинала статьи

У ядра появилась третья жизнь: **sing-box lxd**** — headless-демон**, который хостит ядро внутри себя и выставляет долгоживущий канал управления. Целевой сценарий — роутер: ядро крутится например на OpenWrt, а лаунчер управляет им по сети.

Чем это отличается от классического sing-box run на роутере:

в sing-box же есть Clash API — зачем что-то ещё? Clash API — это REST-эмуляция интерфейса другого ядра, и всё, что в модель Clash не влезает, туда физически не пролезает. Суммарный трафик, список соединений, переключить селектор, померить задержку — да; а вот цепочки detour, структурный DNS-поток, подробности urltest-групп, apply конфига с валидацией и откатом — этих сущностей в Clash-схеме просто не существует. Весь OBSERVABILITY через эту щель не просунуть. Поэтому мой демон lxd говорит на gRPC-протоколе — том же, что CommandClient у Android-линейки: типизированные стримы вместо поллинга, полная модель данных ядра, и один код клиентской стороны на телефон и роутер.

Канал переживает reload. У run смена конфига — это рестарт процесса: клиент теряет соединение, стримы наблюдаемости рвутся. У демона слушающий порт принадлежит демону, а не box-инстансу: apply подменяет ядро «под» живым сервером.

Демон доступен именно тогда, когда данные не ходят. Канал управления поднимается до ядра: битый конфиг оставляет демон на связи — чинить конфиг можно по тому же каналу, который нужен ровно при лежащем data-plane.

Конфиг с гарантиями. POST /admin/apply валидирует кандидата собственным sing-box check, при провале старта откатывается на последний рабочий, помнит прерванный apply через рестарты и ребуты. Залить кривой конфиг на удалённый роутер и потерять его — невозможно by design.

Доверие без боли. mTLS, где демон — сам себе CA: клиент регистрируется одноразовым инвайтом вида адрес#отпечаток#код и дальше опознаётся по сертификату в обе стороны. Никаких паролей в конфигах лаунчера.

Один демон несёт две ключевые фишки: gRPC-наблюдаемость (тот же протокол, что у Android-линейки — статусы, логи, группы, DNS-поток, соединения, детали) и admin-REST. И на этом же порту, за тем же клиентским сертификатом, демон умеет рассказывать о себе и о сервере: свой лог, память процесса, трафик ядра, полный набор pprof-профилей, и диагностика состоний и интерфейсов. Апстримная альтернатива ужасна — experimental.debug.listen — открывает второй порт вообще без аутентификации (здесь выключена), у меня второго порта нет намеренно, все на одном порту за сертификатом.

Отдельная фича, которой я откровенно доволен, — справочник «IP → устройство». Сетевой инспектор на роутере показывал Client: 192.168.20.238:50558; для сети из пятнадцати устройств это ребус. Демон крутится на той стороне, которая имена и раздаёт, — поэтому ручка GET /admin/clients-info собирает карту из пяти источников, каждый следующий уточняет предыдущий: DHCP-лизы (шесть форматов уже разобраны ядром апстрима — свой парсер писать не пришлось) → ARP-таблица (закрывает статические IP) → bridge fdb (в какую физическую розетку воткнут проводной клиент) → hostapd через ubus (SSID и точный AP-интерфейс) → метки оператора. Теперь соединение подписано именем устройства, а в каждой записи есть поле source — когда устройство теряет имя, сразу ясно какой источник замолчал и что докрутить.

Туда же — доставка файловых ресурсов конфига (.srs-рулсеты) по REST с sha256 для диффа, и защита целостности: удалить ресурс, на который ссылается активный конфиг, нельзя.

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

Практическая сторона уже тоже закрыта: релизы собирают статические musl-бинари под роутерные архитектуры (включая big-endian MIPS для старых Atheros).

В доках лежит пошаговый рецепт отдельного VPN-SSID на OpenWrt: гостевой Wi-Fi, весь трафик которого уходит через ядро, не трогая основную домашнюю сеть: https://github.com/Leadaxe/sing-box-lx/blob/lx/docs-lx/openwrt-vpn-ssid-ru.md

Дисциплина, два месяца спустя

Три правила из первой статьи выжили, и оказались ключевыми:

Дрейф от апстрима меряется по merge-base, а не по счётчику коммитов. и это на каждый релиз. Все всегда актуально.

Сабмодули разбираются до мержа ядра. Все подсистемы проверяются целостно. Кстати благодаря этому смог сделать полную сборку всего из исходников для F-Droid.

Стабильный тег не срезается без прогона на реальном устройстве. Эмулятор не ловит ни вендорные ядра, ни настоящий doze. Всё, что проверено только стендом, честно помечено в релиз-нотах: «полевого прогона не было».

И каждый релиз — с рукописными машинописными (конечно) билингвальными нотами.

Что дальше

Демон только начал жить на роутерах — впереди телеметрия хоста, полевой прогон штрафной механики urltest и дальнейшее сращивание с лаунчером и L×Box. Если у вас есть свежий сервер Xray с REALITY (≥ v26.7.11) — отчёты особенно ценны: своих стендов под все сценарии не хватает.

Как обычно: ядро открыто — https://github.com/Leadaxe/sing-box-lx/. Баги — в issues, лучше с крашдампом или конфигом; звёздочки приветствуются; спеки в SPECS/ читаются как отдельный жанр, если вам интересна эта кухня. Спасибо всем, кто присылал полевые репорты и пользуется этими решениями. Мой форк уже вошёл в десятку самых популярных:

Иллюстрация из оригинала статьи

по теме #router