惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

P
Proofpoint News Feed
V2EX - 技术
V2EX - 技术
S
Secure Thoughts
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
L
LINUX DO - 最新话题
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Hacker News: Ask HN
Hacker News: Ask HN
T
Troy Hunt's Blog
Forbes - Security
Forbes - Security
Application and Cybersecurity Blog
Application and Cybersecurity Blog
P
Proofpoint News Feed
Know Your Adversary
Know Your Adversary
Schneier on Security
Schneier on Security
H
Heimdal Security Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Simon Willison's Weblog
Simon Willison's Weblog
V
Vulnerabilities – Threatpost
月光博客
月光博客
罗磊的独立博客
Webroot Blog
Webroot Blog
博客园 - 【当耐特】
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
The Cloudflare Blog
爱范儿
爱范儿
Last Week in AI
Last Week in AI
博客园 - 聂微东
博客园 - 叶小钗
美团技术团队
A
Arctic Wolf
P
Palo Alto Networks Blog
T
Tailwind CSS Blog
Cyberwarzone
Cyberwarzone
雷峰网
雷峰网
Apple Machine Learning Research
Apple Machine Learning Research
人人都是产品经理
人人都是产品经理
宝玉的分享
宝玉的分享
H
Hacker News: Front Page
大猫的无限游戏
大猫的无限游戏
S
SegmentFault 最新的问题
Jina AI
Jina AI
C
Cyber Attacks, Cyber Crime and Cyber Security
The Last Watchdog
The Last Watchdog
IT之家
IT之家
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
酷 壳 – CoolShell
酷 壳 – CoolShell
阮一峰的网络日志
阮一峰的网络日志
J
Java Code Geeks
B
Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
P
Privacy & Cybersecurity Law Blog

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
LxBox: переносим опыт singbox-launcher в Android
developer · 2026-04-25 · via Все публикации подряд на Хабре

Уровень сложностиПростой

Время на прочтение11 мин

Охват и читатели210

Обзор

Привет. Полгода назад я выложил singbox-launcher — десктопный GUI для управления ядром sing-box. По фидбеку стало понятно: идея зашла, людям удобно собирать и отлаживать конфиги на ноутбуке, а потом переносить их на роутеры и другие сетевые устройства. Подробнее о десктопной версии я писал на Хабре.

Пару слов для тех, кто не в контексте. Есть небольшой класс кроссплатформенных сетевых ядер, которые умеют гибкую маршрутизацию трафика и поддерживают современный набор протоколов: WireGuard, VLESS, SOCKS5, Shadowsocks, Hysteria2, TUIC и так далее. Sing-box в этом списке — не самый раскрученный, но для меня он оказался наиболее интересным: быстрая эволюция, внимание к деталям, чистый код, живое общение мейнтейнеров с пользователями, классно организованный по логике конфиг.

Довольно быстро стали приходить запросы на Android-порт. Первое время казалось, что это будет прямое переиспользование десктопного кода. На практике сценарии потребления на мобильных оказались сильно другими: другой UX, другой lifecycle, Doze и background-лимиты, OEM-специфика, ограниченный экран, другие ожидания от автозапуска и обновлений. В итоге пришлось переписать практически всё с нуля.

Результат этой работы — LxBox, и сегодня я хочу рассказать, чем он отличается от существующих Android-клиентов и как устроен изнутри.

и всё, что называют «подпиской» или «конфигом»

Первое, что раздражает в существующих клиентах — каждому нужен «свой» формат. У кого-то только v2rayN base64, у кого-то — только собственный хитрый JSON. LxBox принимает всё, с чем приходится иметь дело на практике:

Формат

Пример входа

Подписка по URL

https://provider.example/sub?token=…

v2rayN base64

base64-список vless://…\nvmess://…

Plain text

построчный список URI

Direct URI

vless://…, vmess://…, trojan://…, ss://…, hy2://…, tuic://…, ssh://…, socks://…, wireguard://…

WireGuard INI

стандартный .conf из wg-quick

Xray JSON Array

полноценный xray-конфиг с outbounds, dialerProxy, REALITY

Sing-box JSON outbound

сырой outbound прямо из документации sing-box

Clash/Clash-Meta подписки

читаются как subscription URL

Всё, что вы скопировали из чата, файла, QR-кода или спеки — LxBox попытается распознать. Формат детектится автоматически: «умный paste» анализирует тело, показывает превью того, что оно собирается сделать, и только потом добавляет.

Что мы делаем с HTTP-заголовками подписки

Кроме самого тела, правильный клиент обязан парсить HTTP-хедеры (de facto стандарт ещё с v2rayN 2018):

  • subscription-userinfo: upload=…; download=…; total=…; expire=… — текущая квота и срок;

  • profile-title (опционально base64-encoded UTF-8) — человеческое имя подписки;

  • profile-update-interval: 24 — подсказка, как часто провайдер рекомендует обновляться;

  • support-url, profile-web-page-url — ссылки на поддержку и сайт;

  • content-disposition: attachment; filename="…" (RFC 5987) — fallback для имени.

Подписка отображается строкой вида:

124 nodes · 🔄 24h · 🕐 3h ago · (2 fails)

Где 🔄 24h — интервал обновления (из хедера или выбранный вручную: 1/3/6/12/24/48/72/168 ч), 🕐 3h ago — давность последнего успеха, в скобках — число неудач подряд.

Поддерживаемые протоколы

Протокол

URI

Транспорты

VLESS

vless://

TCP, WS, gRPC, H2, HTTPUpgrade, REALITY

VMess

vmess:// (v2rayN base64)

TCP, WS, gRPC, H2, HTTPUpgrade

Trojan

trojan://

TCP, WS, gRPC

Shadowsocks

ss:// (SIP002 + legacy + SS2022)

TCP, UDP, SIP003 плагины

Hysteria2

hy2://, hysteria2://

QUIC, Salamander obfs, port-hopping

TUIC v5

tuic://

QUIC, BBR/CUBIC/NewReno, 0-RTT

SSH

ssh://

TCP, host key / password / private key

SOCKS5

socks://, socks5://

TCP, auth

WireGuard

wireguard://, INI

UDP, multi-peer

Подробнее со всеми параметрами каждого URI и соответствием sing-box outbound'ам — в docs/PROTOCOLS.md репо.

2. Подписки, которые не спамят провайдеру и не падают

Что отличает LxBox о других решений в этом вопросе это бережное обращение с сетью и то, что rebuild конфига никогда не ходит в сеть. Любая перегенерация sing-box JSON — это чистая локальная сборка из уже загруженных нод. Я видел клиенты, где каждое открытие настроек = HTTP-запрос по подписке и если сети нет, то и конфига нет. У нас не так, если уже смогли хоть раз считать — будем пользоваться этим.

Детали — в spec 027 subscription auto update.

3. Статистика и наблюдаемость на нормальном уровне

Это моя любимая часть. В типовом клиенте вы видите две цифры — upload/download. В LxBox я сильно расширил функционал.

Экран Statistics

  • Сводка: общий upload, общий download, число активных соединений.

  • Трафик сгруппирован по outbound'ам (vpn-1, auto-proxy-out, direct-out, конкретные ноды). Каждая группа — раскрывающаяся карточка.

  • Для нод с detour (см. ниже) в шапке карточки рендерится цепочка ступеньками:

🇱🇹 Литва-bypass                   ↑ 102.0 KB
   ↳ via ⚙ socks 45.142.73.159     ↓ 299.7 KB
   4 connections                         ⌄

Вот как это выглядит на живом устройстве — вкладка Overview: сводка, трафик по outbound'ам (здесь Нидерланды и direct-out), группировка по routing-правилам и Top apps:

Экран Statistics — Overview

там же экран Connections:

  • Все активные соединения, сортировка по времени.

  • Для каждого: хост:порт, протокол (TCP/UDP), применённое правило маршрутизации, цепочка прокси, длительность, upload/download, имя приложения/процесса.

  • Можно закрыть отдельное соединение крестиком (DELETE /connections/{id}).

  • «Close all» в AppBar — обрубить всё разом.

  • Auto-refresh каждые 2 секунды.

Когда что-то «не так» (сайт не грузится, приложение ходит мимо правила, трафик утекает в direct) — обычно сразу видно, где именно.

Дополнительно из полезного:

  • Встроенный speed test на 10 серверах в разных городах (Cloudflare, Hostkey × 5, Selectel, Tele2, OVH, ThinkBroadband), настраиваемое число параллельных потоков (1/4/10), история сессий.

  • Mass-ping — 20 параллельных пингов по всем нодам с цветовой раскраской по латенси.

  • Heartbeat туннеля — каждые 20 секунд опрашиваем Clash API, два подряд фейла = считаем туннель мёртвым. Ловит перехват другим VPN-приложением или тихую смерть сервиса. и все что выше названо пингом — это HTTP запросы а не imap так что все будет четко работать

в общем вам надо это попробовать и поймете почему это круто.

4. Неочевидные настройки

Android-мир жестокий: Doze, App Standby, background-лимиты, OEM-специфика (Xiaomi, Samsung, Oppo, Huawei — у всех свои тоглы). Тут реализовано очень бережное обращение с батарейкой. Много, очень много тестирования.

Что мы умеем:

Tunnel sleep mode — три режима, на выбор

Настройка Settings → Background → Tunnel sleep mode:

  • never (дефолт) — туннель активен всегда. Стабильные push-уведомления и SIP/VoIP. Цена — +1–3% батареи за ночь.

  • lazy — pause только при глубоком Doze (это дефолт у других решений и часто у пользователей ломались long-lived TCP и push').

  • always — pause на каждое выключение экрана. Максимум экономии, но push будут отваливаться.

Еще полезного:

  • При старте приложение проверяет isIgnoringBatteryOptimizations. Если не whitelisted — показывает диалог с переходом в системные настройки (rate-limited: не чаще раза в сутки).

  • Отдельная плитка App info (OEM power settings) открывает системный Settings.ACTION_APPLICATION_DETAILS_SETTINGS + перед этим показывает инструкцию: «ищите в следующем экране тоглы Autostart / Background activity / Battery saver exceptions». У Xiaomi/MIUI, Samsung, Oppo/ColorOS и Huawei они называются по-разному и спрятаны в разных местах — без этой подсказки обычный пользователь их не находит.

  • Auto-start on boot — Стандартный RECEIVE_BOOT_COMPLETED + BootReceiver. Если пользователь так настроил — VPN поднимается сам после перезагрузки. — Keep VPN on exit: должен ли VPN гаситься при swipe'е приложения из recents или держаться как независимый foreground-service. Реализовано через onTaskRemoved + структурированный serviceScope. Поддерживает сценарий «Flutter-процесс умер, сервис живой»: когда пользователь возвращается, новый UI восстанавливает состояние туннеля через pull-sync (getVpnStatus в init, не только броадкасты, которые могут быть потеряны в Doze).

5. Несколько VPN-каналов одновременно, а не один туннель

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

Во вкладке Routing → Channels (на коллаже выше — третий скрин) видно:

  • VPN ① (selector: vpn-1) — основной канал. По умолчанию туда направляется весь трафик, не попавший под правила (route.final).

  • VPN ② (selector: vpn-2) — второй канал, например, для сервисов, которые должны видеть конкретную страну.

  • VPN ③ (selector: vpn-3) — третий.

  • Include Auto (urltest: ✨auto) — автоматический селектор, который сам выбирает самую быструю ноду по Clash URLTest'у и сам перетекает между нодами по мере изменения латенси.

Каждый канал — это отдельный selector outbound в sing-box, в который можно положить любой набор нод из любой подписки. Один и тот же сервер может быть в нескольких каналах одновременно — это не копия, а ссылка на outbound, «дорого» от этого не становится.

Живой сценарий, которым сам пользуюсь:

  • Канал ① — основная подписка, быстрые европейские ноды. Туда уходит весь трафик по умолчанию.

  • Канал ② — мой домашний WireGuard. Туда я отправляю банковские приложения, чтобы они всегда видели один и тот же «домашний» IP.

  • Канал ③ — специальные региональные ноды (японские, американские — под конкретные сервисы, у которых геолокация завязана на IP).

Правило в Routing → Rules (четвёртый скрин на коллаже) указывает какой канал использовать — или direct (в обход туннеля), или reject (заблокировать)

Любое правило одним тапом на dropdown справа перенастраивается на нужный канал

Важно, что все активные каналы держат параллельные соединения. Когда одно приложение ходит через ①, другое — через ②, а третье — напрямую, это происходит одновременно, без переподключения туннеля. Эффект «умного VPN», где каждое приложение едет по своему маршруту, а не «один общий провод на всех».

В большинстве Android-клиентов такой конструкции либо вовсе нет (один глобальный прокси), либо она собирается руками в сыром sing-box JSON. В LxBox это first-class поверхность настройки.

6. Detour: собственный «первый хоп» для ненадёжных сетей

Объясняю максимально просто.

Представьте кафе с капризным Wi-Fi или провайдера, у которого сегодня что-то с роутингом до вашего обычного сервера в условной Германии. Связь до него то работает, то нет, туннель падает.

Detour-сервер — это промежуточный сервер, через который ваш трафик едет до основного. Классический сценарий:

Домашний роутер с WireGuard → весь трафик LxBox сначала прыгает на него, потом уходит на любой VLESS/Trojan/Hysteria.

Плюсы:

  • Первый хоп — всегда «к себе», он стабилен.

  • Дальше уже работает качественный канал между двумя серверами (не обязательно вашим мобильным интернетом).

  • Если провайдер глючит именно до конкретного зарубежного IP — ваш домашний/рабочий роутер ходит до него гораздо более стабильно.

В LxBox это выделено как отдельный продуманый сценарий:

  • Любую ноду можно пометить как detour (переключатель Mark as detour server в настройках ноды, появляется префикс ).

  • Override detour на уровне подписки — все ноды этой подписки поедут через выбранный detour. Один тогл — вся подписка перемаршрутизирована.

  • Register / Use / Register-in-Auto — тонкая настройка, как именно показывать detour-ы в списке нод и в auto-urltest.

  • Работает со всеми протоколами: ваш WireGuard-detour + VLESS-выходной узел, или SSH-detour + Shadowsocks — как захотите.

Для подписок, которые сами приходят с dialerProxy (Xray JSON-подписки с цепочками) — он распознаётся автоматически, внутренние серверы получают префикс и корректно регистрируются как detour-кандидаты.

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

7. Как это устроено внутри — 3-слойный pipeline

Это раздел «для гиков», но без него сложно понять, почему LxBox ведёт себя именно так.

UI / Controller
  │   paste / URL / QR / file → SubscriptionSource
  ▼
parseFromSource(source)                         — слой 1: парсинг
  │  HTTP fetch + body_decoder + typed parser
  │  returns: List<NodeSpec>, meta, rawBody, headers
  ▼
ServerList (sealed)                             — слой 2: контейнер
  │  SubscriptionServers | UserServer
  │  .build(ctx: EmitContext):
  │    ├─ applies tagPrefix + allocateTag
  │    ├─ per-node emit(vars) → SingboxEntry
  │    ├─ applies detour policy (register/use/override)
  │    └─ registers в selector / auto-proxy-out groups
  ▼
buildConfig(lists, settings)                    — слой 3: сборка
  │  template (assets/wizard_template.json) + post-steps:
  │   1. server_list_build     outbounds/endpoints из ServerList
  │   2. applyPresetBundles    expansion CustomRule(kind: preset) → merge
  │   3. applyCustomRules      inline + local-SRS правила
  │   4. flush registry        → config.route.{rule_set, rules}
  │   5. applyCustomDns        dns.servers/rules из template + extras
  │   6. validator             dangling refs, empty urltest, etc.
  ▼
BuildResult { config, configJson, validation, emitWarnings }
  ▼
HomeController.saveParsedConfig(config)
  ▼
native VpnService (libbox)

Ключевые свойства этой архитектуры:

  • NodeSpec — sealed class на 9 вариантов. Один NodeSpec → 1–2 SingboxEntry (WireGuard едет в endpoints, остальные — в outbounds). Любой switch по типу — без default, компилятор ловит забытую ветку.

  • Round-trip инвариант: parseUri(spec.toUri()) ≈ spec. Протестировано на всех 9 протоколах — можно туда-сюда без потерь.

  • Immutability по умолчанию. Mutable — только ServerList.nodes (перезаписывается на refresh) и NodeSpec.warnings (добавляются warning'и).

  • EmitContext.allocateTag(baseTag) — глобальная уникальность тегов между всеми подписками. Коллизии → суффиксы -1, -2. Сервисные теги шаблона (direct-out, dns-out, block-out) преднаполнены в taken-set, пользовательские с ними не конфликтуют.

  • Warnings bubble up: parse-time → NodeSpec.warnings, emit-time → добавляется в emit (пример: XHTTP fallback — sing-box его не умеет, мы даунгрейдим до HTTPUpgrade и оранжевым баннером сообщаем «с этим узлом, скорее всего, не соединится»).

  • Валидатор возвращает типизированный ValidationResult { fatal[], warnings[] }: dangling refs, пустой urltest, невалидный selector default. Подробности — в UI, «почему конфиг не собирается» никогда не остаётся загадкой.

Wizard-template (assets/wizard_template.json) — единый источник баз: дефолтные DNS-серверы, preset-группы (VPN①/②/③ + @auto), каталог правил маршрутизации, vars. Пользовательский override лежит в lxbox_settings.json. Правило: если нужен новый default — добавляй в template, не хардкодь в Dart.

Полная схема дерева, потоков данных и native-слоя — в docs/ARCHITECTURE.md.

8. Отладка и Debug API

Эта часть чисто для тех, кто любит копаться.

У LxBox есть встроенный HTTP-сервер на 127.0.0.1:9269 — выключен по дефолту, включается тоглом App Settings → Developer → Debug API. Токен генерится при первом включении, показывается в UI с кнопкой Copy, нигде в файлы не пишется (единственный канал — ваш буфер обмена).

Через adb forward tcp:9269 tcp:9269 всё становится доступно с ноутбука.

Что умеет:

  • Чтение состояния: GET /state (HomeState, tunnel, nodes, traffic), /state/subs, /state/rules, /state/storage (с маскированием чувствительных полей), /state/clash, /state/vpn, /device (версия Android, ABI, battery-opt, network type).

  • Clash API proxy/clash/proxies, /clash/group/<tag>/delay, /clash/connections и т.д. Секрет подмешивается автоматически.

  • ActionsPOST /action/ping-all, /ping-node, /run-urltest, /switch-node, /start-vpn, /stop-vpn, /rebuild-config, /refresh-subs, /download-srs, /toast (показать Android-toast — sanity-check «моё ли это устройство на adb»).

  • CRUD на доменные ресурсы: /rules/* (create/update/delete/reorder), /subs/* (add/patch/delete/refresh), /settings/* (scoped writes на route_final, excluded_nodes, vars, DNS).

  • PUT /config — прямой override saved sing-box JSON, минуя сборку. Для A/B тестов руками, без пересборки APK.

  • GET /help?format=text|jsonсамодокументируемая карта API. Без auth (как /ping). Markdown для LLM-агентов, JSON для авто-тулинга. Любой MCP-wrapper или скрипт стартует с одного запроса и знает всё, что есть.

Безопасность:

  • Bind строго 127.0.0.1 (не LAN).

  • Host header check (anti DNS-rebinding) — запрос с Host: evil.com режется 403.

  • Bearer token, Host-check срабатывает до auth.

  • Write-эндпоинты имеют явный allow-list ключей (вы не заблокируете сами себе доступ через API).

Звучит как overengineering для VPN-клиента — но это то, что превращает отладку сложного кейса из «пересоберу APK, перезалью, погляжу» в «один curl».

Полная спека — spec 031 debug api. В разработке — обёртка этого API в MCP-сервер (spec 035 mcp server), чтобы LLM-агент мог напрямую дёргать actions без промежуточного REST.

9. Spec-driven разработка — как это устроено в репозитории

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

Где это живёт:

docs/
  spec/
    features/
      001 mobile stack/spec.md
      002 mvp scope/spec.md
      ...
      026 parser v2/spec.md         ← landmark-рефакторинг v1.3.0
      027 subscription auto update/spec.md
      030 custom routing rules/spec.md
      031 debug api/spec.md
      036 update check/spec.md
    tasks/
      001-reconnect-sink-leak.md
      002-blocking-stopvpn-intent-reset.md
      ...                            ← журнал рабочих циклов
    processes/
      night-work/                    ← autonomous-сессии (AI-агент ночью)
  ARCHITECTURE.md                    ← 3-слойный pipeline, потоки данных
  DEVELOPMENT_GUIDE.md               ← принципы, тесты, процесс релиза
  PROTOCOLS.md                       ← URI-форматы всех 9 протоколов
  releases/
    v1.5.0.md                        ← per-version notes, EN + RU

Если хотите покопаться — начните с docs/spec/README.md, а дальше по интересу: 026 parser v2 для архитектуры, 027 subscription auto update для «как не спамить провайдеру», 031 debug api для «как выдернуть любое состояние наружу». Каждая спека — самодостаточный документ.

Попробовать

Репо: https://github.com/Leadaxe/LxBox — там APK в Releases, документация (EN + RU), все спеки, ARCHITECTURE.md, PROTOCOLS.md.

Issues и PR приветствуются. Больше всего ценны кейсы, где поведение разошлось с ожиданием — они двигают проект в правильную сторону сильнее любой «фичи».