Вы запускаете на телефоне дистрибутив Linux под chroot, ставите в нём VPN-клиент, и оболочка сообщает, что туннель поднят. Потом вы открываете браузер, и трафик уходит через мобильные данные, будто ничего не произошло. Или наоборот: каждое приложение на телефоне теряет связь, потому что клиент добавил маршрут по умолчанию в то пространство имён, которое Android действительно использует. Оба симптома происходят из одного недостающего элемента, и ни один не является ошибкой VPN-клиента.

Оболочка говорит, что подключено, приложения не согласны

Первый исход — обычный. Туннель в пользовательском пространстве, открытый из chroot, может завершить рукопожатие, вывести статистику и передавать трафик, который создаёт та же оболочка, тогда как приложения Android продолжают пользоваться сетью телефона по умолчанию. Ничто их не перехватывает, потому что никто не сообщил Android о существовании VPN.

Второй исход — опасный. Если chroot делит сетевое пространство имён Android, что он делает по умолчанию, процесс с достаточными привилегиями может добавить маршруты и интерфейс TUN, влияющие на весь телефон. Тогда туннель работает для каждого приложения, включая те, которые вы не собирались маршрутизировать, и связь телефона теперь зависит от демона без управления жизненным циклом, без индикатора подключения и без политики постоянного включения.

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

Что chroot изменил, а что нет

ObjectEffect of a chroot
Pathname resolutionChanged: lookups start at the new root
Kernel and driversUnchanged: the phone's kernel, its TUN driver, its limits
Network namespaceUnchanged unless the launcher creates one
Android VPN registrationUnchanged: no app consented, no VPN is selected

Системный вызов chroot делает одну вещь: он меняет каталог, используемый для разрешения имён путей. Страница man прямо говорит, что это не граница безопасности, и ничего не сообщает об интерфейсах, маршрутах или состоянии VPN. Всё, чего люди ждут от контейнера Linux — частный сетевой стек, отфильтрованная файловая система, ограничения ресурсов — происходит из других механизмов, которые загрузчик мог применять, а мог и нет.

Поэтому утверждения, что chroot изолирует VPN, обычно отвечают не на тот вопрос. Уместный вопрос — в каком пространстве имён работает процесс и в каком домене SELinux он ограничен, и оба являются свойствами того, как он был запущен, а не слова chroot.

TUN нужны три вещи, и узел устройства — только одна

Традиционному туннелю в пользовательском пространстве нужны устройство TUN, которое он может открыть, поддержка этого устройства в ядре и разрешение настраивать интерфейс и маршруты. Это отдельные требования, и создание имени пути в /dev само по себе не выполняет ни одного из них:

ls -l /dev/net/tun
ip tuntap add dev tun0 mode tun

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

dmesg | grep avc
logcat -d | grep "avc: denied"

Root это не решает. SELinux ограничивает процессы, работающие от uid 0, точно так же, как остальные, поэтому chroot, запущенный из root-оболочки, всё равно может получить отказ к устройству, которое видит. Отключение принудительного режима, чтобы заработал старый установщик, — это решение для всего телефона с последствиями далеко за пределами туннеля, и оно не является исправлением устаревшего двоичного файла.

Почему приложения Android игнорируют ваш туннель

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

Демон внутри chroot никогда не регистрируется. Нет диалога согласия, нет значка ключа в строке состояния, нет списка включения или исключения для приложений и нет участия в политике постоянного включения. Поэтому приложения продолжают пользоваться сетью по умолчанию, а туннель передаёт только то, что отправляет сама оболочка.

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

Двоичная совместимость — отдельная стена

Даже когда сетевая сторона интересна, у исполняемого файла свои требования: архитектура процессора, динамический загрузчик, библиотека C и те возможности ядра, на которые он рассчитывает. Android использует bionic, а не glibc, и старый двоичный файл, собранный для настольного дистрибутива, может требовать библиотек, которых на устройстве больше нет.

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

Докажите это в контексте Android и приберите за собой

Проверяйте то, что вам действительно важно, с той стороны, которая имеет значение: откройте конкретное приложение, достигните конкретного приватного адреса, убедитесь, какой резолвер ответил, затем отключите туннель и подтвердите задокументированное поведение. Результат из терминала внутри chroot — свидетельство только о контексте выполнения этого терминала и ни о чём больше.

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

Для реальной потребности в удалённом доступе используйте поддерживаемый клиент сервиса или одобренный проект шлюза. Стоит спрашивать не о том, можно ли заставить работать установщик с root, а о том, переносит ли поддерживаемая реализация нужные вам приложения через задуманную границу, не оставляя на устройстве ничьих привилегированных изменений.

Похожие статьи