chroot і VPN на Android: чаму тунель працуе, а праграмы яго ігнаруюць
chroot змяняе разбор шляхоў, а не ядро, сеткавую прастору імён або рэгістрацыю VPN у Android. Адсюль дзве вынікі, і абодва здзіўляюць людзей.
Вы атрымліваеце дыстрыбутыў Linux, які працуе ў chroot на тэлефоне, ставіце ўнутры кліент VPN, і shell паведамляе, што тунель усталяваны. Потым вы пераходзіце ў браўзер, і трафік выходзіць праз мабільныя даныя, нібы нічога не адбылося. Або наадварот: усе праграмы на тэлефоне губляюць злучэнне, бо кліент дадаў маршрут па змаўчанні ў тую прастору імён, якую Android фактычна выкарыстоўвае. Гэтыя два сімптомы паходзяць з аднаго адсутнага кавалка, і ні адзін з іх не з’яўляецца памылкай кліента VPN.
Shell кажа, што злучана, праграмы не згодныя
Першы вынік сустракаецца часцей. Тунель у прасторы карыстальніка, адкрыты з chroot, можа завяршыць рукапацісканне, надрукаваць сваю статыстыку і несці трафік, які спараджае той жа shell, а праграмы Android працягваюць карыстацца сеткай тэлефона па змаўчанні. Нішто іх не перахоплівае, бо нішто не паведаміла Android, што VPN існуе.
Другі вынік небяспечны. Калі chroot дзеліць сеткавую прастору імён Android, а гэта адбываецца па змаўчанні, працэс з дастатковымі прывілеямі можа дадаць маршруты і інтэрфейс TUN, якія ўплываюць на ўвесь тэлефон. Тады тунель працуе для кожнай праграмы, уключаючы тыя, якія вы не збіраліся маршрутызаваць, і злучэнне тэлефона цяпер залежыць ад дэмана без кіравання жыццёвым цыклам, без індыкатара злучэння і без палітыкі пастаяннага ўключэння.
Які з двух вынікаў вы атрымалі, можна вызначыць адной камандай. Параўнайце ip route унутры chroot з той жа камандай з shell Android звонку. Ідэнтычны вывад азначае, што chroot знаходзіцца ў прасторы імён хаста: любое сеткавае змяненне, якое ён робіць, дзейнічае на ўвесь тэлефон. Вывад, які адрозніваецца, азначае, што запускальнік стварыў для яго асобную прастору імён, і яго тунель па канструкцыі нябачны для Android.
Што chroot змяніў, а што не
| Object | Effect of a chroot |
|---|---|
| Pathname resolution | Changed: lookups start at the new root |
| Kernel and drivers | Unchanged: the phone's kernel, its TUN driver, its limits |
| Network namespace | Unchanged unless the launcher creates one |
| Android VPN registration | Unchanged: 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-shell, можа атрымаць адмову ў прыладзе, якую бачыць. Адключэнне прымусу, каб запусціць стары інсталятар, — гэта рашэнне для ўсяго тэлефона з наступствамі далёка за межамі тунеля, і гэта не выпраўленне састарэлага бінарніка.
Чаму праграмы Android ігнаруюць ваш тунель
Падтрыманая мадэль Android — гэта праграма VPN, якая рэгіструецца праз службу VPN платформы, адзін раз просіць згоды ў карыстальніка і атрымлівае дэскрыптар файла для свайго тунеля. Затым платформа накіроўвае трафік у гэты дэскрыптар і прымяняе абсяг праграм, абраны карыстальнікам або адміністратарам, таму адзін і той жа механізм можа быць па кожнай праграме, па профілі і спалучацца з наладамі пастаяннага ўключэння і блакавання без VPN. Кіраўніцтва па распрацоўцы VPN для Android апісвае гэтае рукапацісканне, і галоўнае — што гэта рэгістрацыя, а не трук з маршрутызацыяй.
Дэман унутры chroot ніколі не рэгіструецца. Няма дыялога згоды, няма значка ключа ў радку стану, няма спісу ўключэння або выключэння па праграмах і няма ўдзелу ў палітыцы пастаяннага ўключэння. Таму праграмы працягваюць карыстацца сеткай па змаўчанні, а тунель нясе толькі тое, што адпраўляе сам shell.
Зваротны шлях таксама не дапамагае. Заштурхоўванне маршрутаў у прастору імён хаста перахоплівае ўсё, уключаючы трафік, які платформа разлічвала пакінуць лакальным, і робіць гэта без кантролю па праграмах і без магчымасці для карыстальніка ўбачыць або адклікаць гэта. Няма прамежкавай налады, дзе дэман у chroot накіроўвае трафік толькі адной праграмы.
Бінарная сумяшчальнасць — асобная сцяна
Нават калі сеткавы бок цікавы, у выкананага файла свае патрабаванні: архітэктура працэсара, дынамічны загрузчык, бібліятэка C і магчымасці ядра, якіх ён чакае. Android выкарыстоўвае bionic, а не glibc, і стары бінарнік, сабраны для настольнага дыстрыбутыва, можа патрабаваць бібліятэк, якіх больш няма на прыладзе.
Спасылка з імя файла бібліятэкі на больш новую версію не стварае сумяшчальнасці ABI, а заархіваваная крыптаграфічная бібліятэка з пакета дзесяцігадовай даўніны не з’яўляецца абслугоўваным кампанентам. Калі план на гэтым трымаецца, план — запусціць код без падтрымкі з сеткавымі прывілеямі на тэлефоне.
Дакажыце гэта ў кантэксце Android і прыбярыце пасля сябе
Праверце тое, што вам сапраўды важна, з таго боку, які мае значэнне: адкрыйце пэўную праграму, дасягніце пэўнай прыватнай мэты, пацвердзіце, які рэзалвер адказаў, затым адключыце тунель і пацвердзіце апісаныя паводзіны. Вынік з тэрмінала ўнутры chroot — гэта доказ пра кантэкст выканання гэтага тэрмінала і нічога больш.
Калі вы змянілі маршруты хаста падчас эксперыменту, вярніце іх і запішыце, што змянілі. Затым праверце, ці настроены на тэлефоне VPN пастаяннага ўключэння, бо стары эксперымент, які пакінуў правіла, праз месяцы можа выглядаць як збой платформы.
Для рэальнай патрэбы ў аддаленым доступе выкарыстоўвайце падтрымліваны кліент службы або зацверджаную схему шлюза. Вартае пытанне не ў тым, ці можна прымусіць працаваць інсталятар з root, а ў тым, ці перанясе падтрымліваемая рэалізацыя патрэбныя вам праграмы праз задуманую мяжу, не пакідаючы на прыладзе бясхозных прывілеяваных змен.