Ви запускаєте на телефоні дистрибутив 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, а про те, чи підтримувана реалізація переносить потрібні вам застосунки через задуману межу, не залишаючи на пристрої нічиїх привілейованих змін.

Схожі статті