Чаму ваша праграма для Android не можа дадаць сістэмны профіль VPN
VpnService будуе тунель, які належыць вашай праграме; ён не можа дадаваць або змяняць запісы PPTP, L2TP ці IPsec тэлефона. Прайдзіце мяжу і выберыце правільны шлях.
Вы націскаеце радок VPN у Наладах, бачыце профіль, усталяваны кімсьці іншым, і пачынаеце шукаць выклік, які дадае яго. Такога выкліку няма. Праграма можа адкрыць свой уласны тунель праз VpnService, але запісы ў гэтым спісе належаць платформе і таму кліенту, які іх стварыў. Дакладнае веданне таго, дзе праходзіць мяжа, зберажэ вам тыдзень пагоні за схаванымі класамі.
Пачніце з таго, што паказвае экран Налад
Спіс VPN — гэта рэестр профіляў, якія ўсталявалі сістэма або кліент пастаўшчыка: PPTP, L2TP/IPsec, IKEv2, а таксама ўсе радкі, што праштурхнула праграма OEM або MDM. Кожны радок нясе адрас сервера, уліковыя даныя і рэалізацыю пратакола, якая жыве па-за вашым працэсам. Калі карыстальнік націскае там «Падключыцца», тунель узнімае кліент платформы, а не ваш код. Менавіта таму радок перажывае перазагрузку і таму выдаленне вашай праграмы ніколі яго не прыбірае.
З боку карыстальніка спіс выглядае як паверхня API, месца, дзе даданне VPN павінна быць на адлегласці аднаго намеру. Гэта не так. Адзіныя публічныя пункты ўваходу, якія датычаць яго, — гэта навігацыйныя намеры, а ўсё, што піша ў яго, належыць платформе або прывілеяванаму кампаненту.
Практычная выснова: калі тэкст падтрымкі кажа карыстальнікам дадаць профіль у Наладах, ваша праграма ўвогуле не ўдзельнічае ў гэтым працэсе.
Што VpnService фактычна вам дае
VpnService і VpnService.Builder апісваюць адзін тунель, які належыць вашай праграме. Вы дадаяце адрасы, маршруты, DNS-серверы і MTU, абмяжоўваеце трафік праз addAllowedApplication() або addDisallowedApplication(), а затым establish() вяртае ParcelFileDescriptor для інтэрфейсу TUN. З гэтага моманту праграма чытае IP-пакеты і піша адказы, а значыць, пратакол — ваш для рэалізацыі або ўбудовы: OpenVPN, WireGuard, уласны транспарт.
Нішто ў гэтай паслядоўнасці не гаворыць на PPTP, L2TP/IPsec ці IKEv2. У Builder няма перамыкача, які кажа выкарыстоўваць сістэмны кліент L2TP, і няма зваротнага выкліку, які дазволіў бы кіраваць профілем, што ўжо належыць платформе. Гэта і ёсць сапраўдная мяжа, і гэта мяжа праектавання, а не прабел у дазволах.
Такім чынам, праграма цалкам можа быць VPN-кліентам на Android. Яна проста не можа быць менеджарам для кліентаў, што пастаўляюцца з тэлефонам.
Дыялог згоды — гэта не ўпрыгожванне
Паколькі ваш тунель можа перахопліваць трафік іншых праграм, сістэма патрабуе, каб карыстальнік яўна ўхваліў гэта. prepare() вяртае Intent, які вы абавязаны запусціць, ухвала прывязана да вашага пакета, а пакуль тунель актыўны, у радку стану гарыць пастаянны індыкатар. Другі VPN, які ўзнімаецца, дэактывуе першы, бо Android трымае адзін актыўны VPN адначасова.
Правіла аднаго актыўнага збівае людзей у тэставанні. Вы ўзнімаеце свой тунель, пакуль падключаны карпаратыўны кліент, і робіце выснову, што ваш код зламаны, хаця платформа проста пераключылася ад іншага кліента. Ухвалы можна адклікаць пазней, і prepare() можа вярнуць null на прыладах, дзе няма актыўнасці згоды, таму establish() па-ранейшаму абавязаны апрацоўваць збой.
Схаваныя API і намеры налад
Старыя адказы паказваюць на класы com.android.internal і інтэрфейсы AIDL, якія выкарыстоўвае ўбудаваны кліент. Іх няма ў SDK, яны змяняюцца паміж выпускамі без папярэджання, і крамы праграм лічаць такі доступ рызыкай. Атрыманне root таксама не робіць іх стабільнымі, бо root і доступ да схаваных API — гэта незвязаныя праблемы.
Падтрыманая навігацыйная падмога — Settings.ACTION_VPN_SETTINGS, чыё значэнне android.net.vpn.SETTINGS. Разрашыце яго перад запускам, бо некаторыя зборкі OEM не пастаўляюць гэтую актыўнасць; пераходзьце да пісьмовых крокаў, калі разрашэнне не ўдалося. Ён вядзе карыстальніка да экрана і нічога не наладжвае.
Шляхі ўласніка прылады і MDM — гэта выключэнне, якое звычайна маюць на ўвазе. DevicePolicyManager можа прызначыць пакет пастаяннага VPN, а кіраваныя канфігурацыі могуць папярэдне загрузіць налады для кліента, які іх падтрымлівае, але гэта ўсё яшчэ не публічны SDK, які стварае профіль PPTP.
Прайдзіце рашэнне з боку карыстальніка
Калі вашаму прадукту трэба пераносіць трафік, плануйце VpnService плюс сапраўдны стэк пратаколаў і закладвайце час на працэс згоды і правіла аднаго VPN. Калі мэта — падключыцца да існуючага карпаратыўнага профілю, ваша праца — гэта кіраўніцтва: глыбокая спасылка на экран налад, дакументаванне палёў, і няхай кліент платформы будуе тунель. Калі праграме трэба дасягнуць толькі прыватнай канчатковай кропкі, ёй увогуле не патрэбны ўласны тунель.
Запішыце гэтае рашэнне да таго, як пісаць код, бо тры шляхі пасля першага спрынту амаль нічога не маюць супольнага.
Апошняя праверка перад пачаткам: у патрабаванні сказана, што падключаецца наша праграма ці што падключаецца прылада? Першае — гэта VpnService, другое — профіль, які вы не можаце стварыць. Правільна сфармуляваць гэты сказ танней за любы рэфактарынг.