L×Box: от VPN-клиента до экосистемы управления сетевым трафиком

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Я рассказываю тут про развитие VPN-клиента L×Box, его ядра и десктоп-версии.
Новость месяца: L×Box уже доступен в Google Play

Проект быстро развивается: пока я дописывал раздел про форк, ядро проехало три минорных релиза. Пока описывал фичесет приложения, вышло 27 релизов. Так что все технологичекие фишки тут не смогу описать — только главное и интересное, и поговорим про позиционирование!


Как успех порождает цель

Когда я начинал LxBox, у меня была одна простая цель: сделать Android-клиент для sing-box, который устраивает лично меня, и попутно показать, как я умею вести проекты. Первые две статьи (обзор клиента и разбор per-app профайлера) ровно про это: вот фича, вот как она устроена, вот как проверена.

Потом рынок и спрос стал управлять процессом: в июне я форкнул ядро, потому что XHTTP и AmneziaWG в апстрим не войдут никогда, а Xray-серверы и их конфиги набрали популярность. В августе ядро ушло в роутеры, потому что адаптации под телефон и под OpenWrt оказались одними и теми же. Из общения с аудиторией я понял, что люди привыкают к хорошему мгновенно: дал фишку на роутере, уже хотят на телефоне; сделал на телефоне, хотят в десктопе. Это вообще UX тренд такой — мы научились автоматически переносить положительный опыт и ожидания между разными поверхностями взаимодействия.

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

  • Windows 7. Пользователи с семёрки пришли сами, и оказалось, что у них есть удивительно крутые легаси-проекты, от которых зависит их работа, и управляемая сеть нужна им не меньше, чем остальным. Я был удивлён, слушая, какие сложные системы иногда существуют только на семёрке. А про них все забыли: современные клиенты собираются под современные API. Пришлось помочь.

  • Китай. Пришли китайцы, объяснили мне, что у них вообще принято конфиги в телефоне писать. Сначала не поверил, потом сделал редактор JSON в Android-клиенте. А еще они тут инициировали мне TrustTunnel, так у нас появилась своя реализация.

  • Вайбкодеры — золотая молодежь, разбираться в технологиях нет времени, они хотят кирпичики, из которых сделают всё что угодно и быстро. Что ж — понимаемо, принимаемо. Для них пришлось создать серию ИИ-документации (для ИИ: люди у них документы уже не читают, читают агенты и им рассказывают) по продукту и API, чтобы их агенты могли сами разобраться или по крайней мере баг-репорт написать автономно.

  • Европа и Америка этим нужны не прокси, а корпоративная и домашняя сеть. Tailscale и Fortinet SSL VPN, потому что на работе у них популярны эти два. Сделал полную поддержку обоих: узел Tailscale с выбором exit node на лету и вкладкой, где виден путь до каждого устройства, прямой или через ретранслятор (вообще уникальная фишка); FortiGate через OpenConnect со вторым фактором и входом через SAML в браузере. И то и другое встало в общую маршрутизацию рядом с остальными узлами, а не отдельным режимом. По их же запросу WireGuard-узлы научились включаться и выключаться на лету, без перезапуска туннеля: выключенный узел засыпает, его буферы освобождаются, открытые через него потоки рвутся, а включение будит его сразу.

Рынок конкурентный и на нем L×Box конкурирует не только с другими VPN-клиентами. Он объединяет сценарии, для которых пользователь обычно вынужден устанавливать несколько приложений и разбираться в разных моделях настройки. Иными словами я оказался в нужном месте с нужным решением: у меня клиент, который позволяет держать множество разных соединений одновременно, делать их роутинг по приложениям, доменам и зонам, а настраивается всё через интерфейс.

Уникальность L×Box в том, что это одновременно VPN-клиент и прокси-клиент, и всё живёт в одной маршрутизации (оригинальная идея sing-box, которую никто почему-то не раскрывал полностью). VPN-протоколы: WireGuard и AmneziaWG, OpenVPN, SSL VPN через OpenConnect (FortiGate, Cisco AnyConnect, GlobalProtect, F5, Pulse), Tailscale. Прокси-протоколы: VLESS, VMess, Trojan, Shadowsocks, Hysteria2, TUIC, AnyTLS, NaïveProxy, TrustTunnel, SSH, SOCKS, HTTP. Обычно это два разных мира с двумя разными клиентами: корпоративный VPN в одном, домашний прокси в другом. Здесь корпоративный SSL VPN, домашний VLESS и WireGuard до своего роутера управляются в одном месте, типа: «рабочие домены через SSL VPN, остальное через VLESS, домашняя подсеть через WireGuard».

Работа идет по трем направлениям:

  • sing-box-lx — ядро: глубоко доработанный форк sing-box с AmneziaWG, XHTTP, MASQUE, TrustTunnel, постквантовым VLESS и демоном lxd для роутеров.

  • LxBox — Android-клиент, включая Android TV. Google Play, F-Droid, GitHub.

  • singbox-launcher — десктопный лаунчер на Go, он же интерфейс к роутеру с lxd. Windows от 7 до последней, macOS, Linux.

Про ядро позволю себе похвастаться: в августе я писал, что sing-box-lx входит в десятку самых популярных форков sing-box, а сейчас он на четвёртом месте по звёздам. И его берут как основу не только мои клиенты: на нём работают сторонние клиенты и панели, например готовящийся NekoBox 6.

Прогрессивный JPEG

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

Уровень 1. Поставил, нажал Get WARP, нажал Start. Ни ссылки, ни сервера, ни регистрации. Ключ WireGuard генерируется на телефоне, наружу уходит только публичная часть, и через несколько секунд есть рабочий туннель до Cloudflare. Для многих этого достаточно навсегда. Тут автоматически есть и обфускация и выбор оптимальных параметров и новейший протокол MASQUE c нужным диалектом.

Уровень 2. Вставил подписку или ввёл сервер. Ссылка добавляется из буфера, по QR с камеры или файлом. Можно вбить параметры через форму. Пресеты правил стоят с момента установки: российские сайты и приложения напрямую, Tailscale-сети, трафик без владельца и входящие из туннелей закрыты. Направление по умолчанию одно, с автовыбором самого быстрого узла. Настраивать нечего. Большинство пользователей остаются на этом ±уровне.

Уровень 3. Захотел настроить. Экран Routing, четыре вкладки: Directions, Presets, Rules, Tunnel apps. Направление — набор серверов под задачу: «стриминг», «работа», «домой». Правило — исключение из умолчания: «банк напрямую», «рабочие домены через SSL VPN», «дома по Wi-Fi всё напрямую». Tunnel apps решает, какие приложения вообще заходят в L×Box. Три решения, три вкладки, в этом порядке. Опытным сюда же: узел Tailscale добавляется мастером, который сам создаёт DNS-сервер, правило для .ts.net и маршрут в сеть 100.64.0.0/10, а SSL VPN через OpenConnect — со вторым фактором и входом через SAML в браузере. Корпоративная сеть и домашняя подсеть встают в тот же список Направлений, что и обычные серверы.

Уровень 4. Решил разобраться, куда ходит трафик. Профайлер показывает по каждому приложению, какие домены оно открыло, через какой DNS они разрешились и по какому правилу ушли в какое Направление. Это тема второй статьи, повторять не буду. Добавлю только, что с тех пор у каждого узла появилась вкладка Diagnostics: HTTP-проба через конкретный узел с сырым ответом, даже при выключенном VPN.

Уровень 5. Захотел тюнить подписку или узел. У подписки своя вкладка Filters: правила, которые на каждом обновлении сами чинят и отсеивают узлы. Условие по имени или полю узла (содержит, равно, регулярное выражение), действие Disable или Replace с карманами $1/$2. Типичные ситуации, которые решают через фильтр: провайдер переименовал серверы, чуть сломал конфиг, вставил рекламный узел, сломал отпечаток у половины списка, добавить TLS или Jump (relay/detour) Server. Перед сохранением фильтр прогоняется по узлам, и видно, что он зацепил. Через интерфейс можно заставить работать даже бесплатный Proton (WG + AWG 1.5).

Уровень 6. Захотел править конфиг. Это уровень китайцев и вайбкодеров. У каждого узла вкладка Source: то, что приехало из подписки, можно переписать в JSON ядра, и оно уйдёт ядру дословно, с проверкой на Save, диагностика останется, но перейдёт в режим информирования. Для JSON-полей нативный редактор JSON5. Для агентов — Debug API на 127.0.0.1 с Bearer-токеном, выключен по умолчанию, и справочник, написанный так, чтобы его читал агент, а не человек.

Уровень 7. Захотел понять, как это работает. В ядре пишу ликбезы, устроенные по тому же принципу, от «что это» до «какие байты на проводе»: протоколы семейства Xray, AmneziaWG и TrustTunnel. Над ними справочник lx-полей, под ними спеки. Три уровня документации под три уровня погружения читателя: что есть и как включить, как устроено, почему так решили. А над всем этим лежит общий с лаунчером реестр протоколов и корпус разбора и тестирования: снимки 68 публичных подписок, 73 938 узлов, по каждому из которых видно, что приехало из ссылки, во что превратилось для ядра и какое предупреждение получило по дороге. Это и есть полная диагностика разбора, открытая, воспроизводимая, дорабатываемая, проверяемая.

Кручу этот принцип прогрессивного JPEG на все три продукта. Лаунчер и роутер отличаются от телефона по факту лишь тем, что у роутера нет экрана, и первый уровень там — это файл конфига от телефона.

Как защищал пользователей, которые не читают дальше первого уровня

Большинство пользователей не делают различия между VPN-протоколом и прокси. Для них и то и другое — «VPN». Для ядра разница принципиальная, и из неё растут разные угрозы, о которых никто из нормальных людей не думает. Я обнаружил потенциальные проблемы в знакомых сценариях, но не проводил систематического сравнительного аудита клиентов. Думаю, что многие приложения подвержены тем угрозам, которые я ниже опишу.

У прокси каждое соединение открываете и инициализируете вы: телефон → сервер → сайт. Сервер не может позвонить вам обратно, у него нет такого канала.

Врезка для знатоков: имею ввиду, что сервер не получает автоматически IP-маршрут внутрь клиентского устройства, эквивалентный маршруту через поднятый VPN-туннель. Обратные соединения, UDP и другие особенности отдельных протоколов — это все живет в локальном неймспейсе и в общий роутинг не выходит.

У VPN-протокола поднимается туннель, и он двусторонний по определению: WireGuard, OpenVPN, SSL VPN, Tailscale дают серверу или пиру маршрут внутрь вашего устройства. В sing-box этот туннель обслуживает userspace-стек gVisor (ха, а в новой версии его в upstream не будет, так что модель перестроим еще раз), и он принимает входящее соединение на любой адрес. То есть корпоративный шлюз, узел WireGuard из чужой подписки или пир в Tailscale-сети может сам открыть соединение к вашему телефону, к вашей домашней сети за ним или через вас и пойти дальше.

На корпоративном VPN это нормально и даже нужно: так админ ходит на ваш ноутбук. На узле WireGuard из бесплатной подписки это дыра. Управлять этим вручную сложно даже опытному системному администратору: надо знать, какой из двадцати узлов в списке VPN-протокол, а какой прокси, и у каждого решить отдельно. Обычный пользователь этого не сделает никогда.

Поэтому решение принято мной за него. Пресет Tunnel ingress включён всегда по умолчанию, и у существующих установок он добавляется один раз при обновлении. Входящие из любого клиентского туннеля отклоняются, пока у узла не включен один из трех тумблеров явно: Allow access to this device, Expose local network, Allow as gateway. У узла из подписки тумблеров нет вовсе, он всегда закрыт. У своего узла, например WireGuard до домашнего роутера, их можно открыть осознанно. Tailscale пресет не трогает: там входящие управляются правилами Tailscale и о пользователях они заботятся (хотя тоже вопросики, если «друг» дал вам подключение).

Вторая утечка того же класса, про которую тут уже много всего написано утечки через tun0: Приложение, исключённое из VPN, может само привязать сокет к интерфейсу tun0. Такой пакет минует перехват Android, и ядро видит его без владельца: UID неизвестен, имя пакета пустое. Правила по приложению на него не действуют, потому что сравнивать не с чем, и до версии 2.25.13 он уходил на VPN-сервер. Исключённое приложение узнавало адрес вашего сервера и то, что VPN включён. Пресет Unknown traffic ловит такой трафик правилом с инверсией и отправляет напрямую; строгий вариант reject есть, но по умолчанию не стоит (стоит директ): у системных процессов без атрибуции не должно пропадать сетевое соединение.

Проверяется это на устройстве через Termux, исключённый из VPN:

curl --interface tun0 https://ifconfig.me/ip

Пресет включён — в ответе адрес провайдера. Пресет выключен — адрес VPN-сервера, то есть утечка. Оба пресета появились за последний месяц. Сразу скажу, что не придумал способ не ломать прокси режим. Так что либо прокси режим, либо контроль утечек.

И про то, что уходит с телефона наружу, раз уж речь про утечки. Скрытой телеметрии принципиально — нет, аналитики — нет, никакого деанонимизирования: в APK нет ни одного SDK, который бы это делал, и это проверено перед публикацией на F-Droid. Серверу подписки при обновлении уходят стандартные для панелей заголовки, User-Agent и, если включить, x-hwid. HWID — случайный UUID, сгенерированный при первом запуске, не выведенный ни из IMEI, ни из серийника, ни из чего-либо другого в железе. По умолчанию он не отправляется вовсе; включается, когда панель провайдера без него отказывается отдавать узлы, глобально в App Settings → Subscriptions или у одной подписки в её Fetch identity. У каждой подписки может быть и своя идентичность, свой User-Agent и свой HWID.

Немного о безопасности на роутере: на роутере ядро живёт как демон lxd под root: он поднимает TUN, меняет маршруты, читает логи. Лаунчер ходит к нему по gRPC с mTLS. И тут возникает вопрос, на котором спотыкаются многие панели: если клиент с сертификатом может сказать демону «примени этот конфиг», почему он не может сказать «выполни эту команду»? К несчастью во многих панелях может. А это не правильно, потому что тогда украденный сертификат или скомпрометированный лаунчер равен root-шеллу на роутере. Я провёл границу иначе: демон управляет сетью, и запускает только заранее разрешенные пресеты. Админ при установке перечисляет в daemon.json именованные команды: типа "update": "/usr/bin/sing-box lxd update". Клиент видит список и запускает команду по имени. Передать что-то своё он не может: ни аргумент, ни путь, ни версию. Хочется две вариации — будут две команды, update и update-rc. Это модель sudoers с NOPASSWD: тот, у кого есть root на хосте, перечисляет, что разрешено сетевому клиенту. Варианты «загрузи скрипт и выполни» отсутствуют

Как я веду проект

Это спекдрайвен: каждая фича и каждый нетривиальный баг — спецификация. В приложении счёт задач перевалил за 660, фич в новом формате 31. В ядре отдельный Spec Kit: SPEC → PLAN → TASKS → IMPLEMENTATION_REPORT, с августа по октябрь спеки с 095 по 134. Все цифры в этой статье взяты из отчётов реализации, и там же записано, чего не мерили. Отчёт по режиму авто-группы failover так и говорит: устройство и живые узлы не гонялись, энергоэффект не измерен. Это не скромность, это дисциплина: без строки «не проверено» следующий баг ищется не там.

Значительная часть работы делается в паре с AI-ассистентами по этим спецификациям. Спеку пишу я, ревью делаю я, на устройстве проверяет он и пользователи. Все замеры в статьях снимаю с телефона я. Дисциплина «сначала спека, потом код» во многом и выросла из опыта управления проектами. Контролирую форматы данных, вход выход, контракт, алгоритмы, блоксхемы, логику, приоритеты, обещания. Проблема: читая спеки стал говорить сам как ии, прям реально пугает.

Бывают приколы с тем, что спека фиксирует предположение, вот пример. Когда я прививал AmneziaWG к wireguard-go, в спеке графта я записал как инвариант: «запас в заголовке пакета форк не использует, константу обнуляем». Для WireGuard это было верно (ну я так думал). Спека прошла ревью, код прошёл тесты, и инвариант жил в проекте пока я не стал реализовывать Tailscale! А Tailscale, собирается из того же wireguard-go и на прямом UDP-пути требует этот запас (вот это поворот!). Трафик молчал, DERP работал, неделю я это искал.

Где взять и чего не ждать

  • sing-box-lx — ядро, GPL-3.0. Спеки, changelog по каждому тегу, справочник lx-полей и три ликбеза лежат в репозитории. Десктопные бинари, libbox.aar для Android и инсталлятор для OpenWrt — в релизах. Текущая версия, не имеет дрейфа от upstream/stable, что уникально для такого рода форков.

  • singbox-launcher — Windows от 7, macOS, Linux, и он же интерфейс к роутеру.

Чего пока нет и не знаю как сделать (жду подсказок от вас):

  • режим прокси и контроль утечек из раздела выше несовместимы: либо одно, либо другое (не придумал как и то и то);

  • приложения внутри Samsung Knox-папки правилам по приложению не видны, без root это не решается;

Известные ограничения:

  • deny-list приложений вместе с системным «Block connections without VPN» даёт полный блок для приложений из списка: netd отдаёт DNS-сокет под uid приложения, это поведение Android; выход — per-app выключить и завести правило package_name → direct;

  • режим failover не выбирает лучший узел, он просто держит работающее соедиенение, зато не засирает проверками все;

Если у вас есть сеть, где что-то из этого пригодилось — расскажите, если что-то сломалось — issues буду рад решить ваши вопросы!.

Похоже, что следующая задача — выйти за пределы клиентских приложений. Когда на одном устройстве сходятся корпоративный VPN, домашняя инфраструктура и внешние прокси, возникает следующий уровень: централизованное управление конфигурациями, узлами и политиками для целой команды или организации.

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

Источник: https://habr.com/ru/articles/1095724/


Интересные статьи

Интересные статьи

Современные компании всё чаще сталкиваются с необходимостью интеграции IP-телефонии и CRM-систем для улучшения управления клиентскими коммуникациями. Такая интеграция позволяет автоматизировать ключев...
За последние несколько недель сразу несколько производителей анонсировали и/или запустили продажи новых мини-ПК: от пассивного MeLE Quieter 4C до флагманского GMK EVO-X2 с дискретной графикой. Одн...
После очередного обновления коробочного портала Битрикс 24 в марте 2023г, в бизнес процессах, перестала работать модификация типов при присвоении значения строковым переменным.Например, при присвоении...
Торговые санкции США в отношении Китая становятся все жестче, но, похоже, Поднебесная все же находит пути решения проблемы. Более того, при поддержке государства компании продолжают развиваться, р...
Этот пост будет из серии, об инструментах безопасности, которые доступны в Битриксе сразу «из коробки». Перечислю их все, скажу какой инструмент в какой редакции Битрикса доступен, кратко и не очень р...