OpenVPN жардамчы бинари Android 10'до иштебейт: уруксат берилген жок
Android 10 колдонмо өз кампасына жазган жардамчы файлды аткаруудан баш тартат. logcat окуңуз, жардамчыны жергиликтүү китепкана катары жеткириңиз жана bundle курулуштарын оңдоңуз.
Колдонмо Android 9'до иштеп, Android 10'го жаңыртылгандан кийин ошол эле телефондо өлөт. Профилиңизге тийбеген, сертификаттар ошонун эле өзү, ал эми кулоо кандайдыр бир аутентификация трафигинен мурун келет. logcat адегенде нөлдүк көрсөткүчтү көрсөтөт, ал эми андан бир нече сап жогору турат Cannot run program ...: error=13, Permission denied. Бул билдирүү файлды аткаруу жөнүндө, конфигурацияңызды окуу жөнүндө эмес.
13-ката иш жүзүндө эмнени четке кагат
Android 10, API деңгээли 29, колдонмолордун өздөрүнүн маалымат каталогуна жазган файлдарын аткаруусун токтотту. Эреже адегенде жазылуучу, анан аткарылуучу кампаны көздөйт, жана дал ушундай нерсени assets ичинен көчүрүүчү иштеткич жаратат. ics-openvpn өзөгүнүн эски курулуштары биринчи иштетүүдө APK'дан аткарылуучу openvpn файлын чыгарып, аны ProcessBuilder аркылуу баштайт. Чыгаруу дагы эле ийгиликтүү; четке кагылганы аткаруу. API 29'го багытталган колдонмо бул эрэжени эскирээк чыгарылыш менен келген түзмөктө иштегенде да мураска алат, ошондуктан жаңыртуу эч ким тийбеген курулушту бузушу мүмкүн.
Четке кагууда бир папка атына таандык эч нерсе жок. Колдонмо өз маалымат каталогунун астында жараткан файл жолго карабастан аткарылбай турган деп эсептелет, ошондуктан getFilesDir(), getCacheDir() жана ыңгайлаштырылган кошумча каталог баары бирдей ийгиликсиз болот.
Жардамчынын кулоосун профиль маселесинен ажыратыңыз
Процесстин башталышынын айланасындагы логду окуңуз, жогорудан айландырбаңыз. Изделе турган кол тамга — error=13 сабы, ал эми анын үстүндөгү стек изи адатта ProcessBuilder-ин чакырган иштеткич ыкмасын атайт:
adb logcat -d | grep -n -i -E "cannot run program|permission denied|startOpenVPN"Эгер жардамчы эч качан башталбаса, OpenVPN лог чыгарылышын такыр көрбөйсүз: шифр сүйлөшүүсү да, жиберилген маршруттар да, DNS конфигурациясы да жок. Эгер ошол саптар пайда болуп, ийгиликсиздик кийин келсе, бинар иштеген жана маселе профилде, серверде же маршруттоо катмарында. Ошол бир айырма .ovpn файлдарын оңдоого кетердей көп убакытты үнөмдөйт, алар эч качан күнөөлүү болгон эмес. Ал ошондой эле төмөнкү эки оңдоонун кайсынысы сизге чындап керек экенин айтат.
Сынап жаткан түзмөктүн API деңгээлин да текшериңиз, куруу конфигурацияңыздагыны эмес. API 28'деги эмулятор образы эч нерсени кайра жаратпайт, анткени чектөө 29'дон өйдө гана тиет. Ошол эле учурда куруу файлыңыздагы максаттуу SDK'ны текшериңиз: дал аны көтөрүү ушул эрэжени ичке тартат.
adb shell getprop ro.build.version.sdkЭмнеге бинарды башка жерге көчүрүү жардам бербейт
Айкын айланма жол, жардамчыны башка жазылуучу каталогго жазуу, түпнуска ийгиликсиз болгон ошол эле себептен ийгиликсиз болот. Android дагы эле колдонмонун жергиликтүү китепканалар каталогуна орнотулган жалпы китепканаларды аткарууга уруксат берет, анткени аларды орноткуч таңуулайт, аткаруу убагында жазылбайт. Ошол каталог — иштеткич көрсөтүүгө тийиш болгон жалгыз жер. Аткаруу убагында өзүңүз чыгарган нерсенин баары, кандай атасаңыз да, четке кагылган категорияда калат.
Тышкы кампа андан жаман: ал noexec менен бекитилген, ал эми ал жерге коюлган жардамчыны эч бир колдонмо баштай албайт. Колдонмо маалыматтарын тазалоо да эски жүрүм-турумду кайтарбайт, анткени кийинки иштетүү ошол эле аткарылбай турган көчүрмөнү кайра жаратат.
Иштеткичти таңууланган китепканага багыттаңыз
Жардамчынын атын жалпы китепкана атына өзгөртүп, аны колдогон ар бир ABI үчүн jniLibs астында жеткириңиз, анан иштеткич API 28'ден тартып орнотулган китепкананын жолун кайтарсын:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
return new File(context.getApplicationInfo().nativeLibraryDir,
"libovpnexec.so").getPath();
}Бул жолдо чыныгы файл болушу үчүн китепкана орнотуу убагында чыгарылышы керек, ошондуктан android:extractNativeLibs="true" маанисин <application> элементине коюңуз. Эгер manifest бириктиргичи башка маани алып келсе, анын жанына tools:replace="android:extractNativeLibs" кошуңуз. application элементинин шилтемеси бул атрибут эмнени башкарарын документтейт.
Иштеткичти кол менен патчтаганда кайталанган жергиликтүү өзгөрмөдөн сак болуңуз. Эски булактар ошол эле ыкмада кийин nativeAPI деп жарыялайт, ал эми экинчи жарыялоо аткаруу эмес, компиляция катасы, ошондуктан куруу тез ийгиликсиз болот жана катаны байкоо оңой. Gradle блогундагы ABI тизмесин кошкон папкаларыңыз менен шайкеш кармаңыз.
Чыгарылыш артефактын сыноо курулушуна дал келтириңиз
Дебаг APK туннелди көтөрө алат, ал эми чыгарылыш bundle дагы эле кулайт, анткени bundle жергиликтүү китепканаларды башка формада таңуулап, аларды архивден кысылган түрдө бере алады. Эгер bundle'дан чыккан курулуштар гана ийгиликсиз болсо, муну gradle.properties файлына кошуп, кайра куруңуз:
android.bundle.enableUncompressedNativeLibs=falseАнан орнотулган пакет күткөн ABI'ди билдирерин ырастаңыз, экесин тең жеткирсеңиз, текшерүүнү 32 биттик жана 64 биттик түзмөктө кайталаңыз. Пакет менеджери тандаган ABI'ин атайт, ошондуктан 32 битке кайткан түзмөк кулоо отчётунда эмес, ушул жерде көрүнөт:
adb shell dumpsys package com.example.openvpn | grep -i primaryCpuAbiБир ABI үчүн жок китепкана баштапкы уруксат катасын ошол түзмөктө гана кайра жаратат, ошондуктан бир ийгиликтүү сыноо телефону далил эмес. Manifest желегин, китепкананын атын жана bundle параметрин бирге жеткириңиз; бирөөнү өзгөртүп, калганын унутуп калсаңыз, ошол эле кулоого кайтасыз. Туруктуу чечим — патчты түбөлүк көтөрүү эмес, колдоого алынган өзөк чыгарылышына өтүү.