Башка VPN мурун эле активдүү болгондо VpnService коргоосу ишке ашпайт
Android ар бир колдонуучуга бир VPN интерфейсин уруксат кылат. prepare, establish, protect жана ээлик текшерүүлөрүн тартиби менен аткарып, анан жокко чыгарууну же колдонмо боюнча четтетүүнү тандаңыз.
Колдонмоңуз VpnService.prepare чакырат, null алат, туннель курат, дескриптор жарактуу көрүнөт, бирок серверге эч нерсе жетпейт. Же prepare Intent кайтарат, колдонуучу аны жактырат, бирок establish дагы эле ишке ашпайт. Эки жыйынтык тең адатта бир нерсени билдирет: башка колдонмо бул колдонуучунун VPN интерфейсин мурунтан ээлеп алган, ал эми сиздин protect чакырууларыңыз туннелиңиз колдоно албаган сокеттерди белгилеп жатат. Төмөнкү текшерүүлөрдү тартиби менен аткарып, биринчи ишке ашпаган жерде токтогула, анткени кийинки кадам мурункусун оңдой албайт.
protect тийүүдөн мурун VPN ордун текшериңиз
Android ар бир колдонуучуга так бир активдүү VPN интерфейсин берет. Бул платформанын эрежеси, колдонмоңуз сурай алган уруксат эмес, ошондуктан экөө тең туннель болууну каалаган эки клиент бирге жашай албайт.
Башка колдонмо үчүн коюлган дайыма күйүк турган VPN эң кыйын учур, анткени система ал колдонмону туташтырылган бойдон кармап, басып алуудан баш тартат. AdGuard сыяктуу трафик фильтри, корпоративдик клиент же керектөөчү VPN колдонуучу анын орнотулганын унутуп калганда орунду ээлеп тура алат. Колдонуучудан параметрлерди ачып, VPN астында көрсөтүлгөн жазууну окуусун сураныңыз; ал жердеги ат — сиз атаандашып жаткан ээси. Ошол жазуу ажыратылмайынча же дайыма күйүк жөндөө өчүрүлмөйүнчө, сиздин VpnService интерфейс боло албайт.
Кадам 1: prepare эмнени кайтараарын окуңуз
VpnService.prepare бир суроого жооп берет: бул колдонмо VPN боло алабы? Макулдук мурунтан болсо null кайтарат, ал эми колдонуучу аны дагы макулдашы керек болсо Intent кайтарат, аны startActivityForResult менен иштетүү керек. null кайтаруусун улантууга уруксат деп кабыл алыңыз, establish ийгиликтүү болот деген далил катары эмес.
Intent intent = VpnService.prepare(context);
if (intent != null) {
startActivityForResult(intent, REQUEST_VPN);
}Эгер Intent жолу кайтып, колдонуучу баш тартса, prepare кийинки аракетте дагы Intent кайтара берет. Циклде кайра аракет кылуунун ордуна жыйынтык кодун жазып кой, анткени баш тартылган макулдук — колдонуучунун чечими, өткөөл ката эмес.
Кадам 2: интерфейс сиздин колдонмого таандык экенин ырастаңыз
establish ден кийин алынган ParcelFileDescriptor — сиздин ээлик далилиңиз, аны ар кандай сокет ишинин алдында текшерүү пайдалуу. null же мурунтан жабылган дескриптор интерфейс эч качан түзүлбөгөнүн билдирет, эч кандай өзгөчөлүк чыкпаса да. Builder'дин интерфейс атын системанын активдүү VPN үчүн билдирген аты менен салыштырыңыз, сыноо түзмөгүндө dumpsys колдонуп. Эгер алар айырмаланса, сиз курган туннель трафикти ташып жаткан туннель эмес.
adb shell dumpsys connectivityУшул эле шайкешсиздик туташкан белгини өлүк трафик менен түшүндүрөт. Система башка колдонмонун туннелин көрсөтөт, ал эми сиздин код өзүнө таандык эмес интерфейстин дескрипторин кармап турат.
Кадам 3: protect ты connect тен мурун чакырыңыз
Интерфейс пайда болгондон кийин колдонмоңуз ачкан сокеттер демейки боюнча туннелге багытталат. Сырткы транспорт бул эрежени аткара албайт, антпесе капсулага па кет интерфейске кайтып келмек, ошондуктан VpnService protect сокетти VPN ди айланып өтүп, астындагы тармакты колдонуу үчүн белгилейт. Чакыруу boolean кайтарат, аны этибарга албоо — соо көрүнгөн, бирок эч нерсе ташыбаган сокетке жетүүнүн жолу.
protect ти connect же bind ден мурун чакырыңыз, эч качан кийин эмес. Коргоо сокет туташканга же байланганга чейин ордунда болушу керек, анткени туташкан сокет өз маршрутун мурунтан тандап койгон жана кийинки protect аны ишенимдүү жылдырбайт. Эгер protect false кайтарса, токтоп, ээликти кайра текшериңиз: ал интерфейс сиздин колдонмого таандык болбогондо ишке ашпайт, бул дал башка VPN калтырган абал. false кайтаруу — Кадам 1 ге кайтуу белгиси, ошол эле сокетти кайра сынап көрүү эмес.
DatagramSocket socket = new DatagramSocket();
if (!vpnService.protect(socket)) {
return;
}
socket.connect(serverAddress, serverPort);Кадам 4: сокет ыңгайсыз болгондо процессти байланыштырыңыз
Айрым транспорттор бир сокет эмес: китепкана бир нечесин ача алат, же жардамчы процесстеги ар бир туташуу бир эле чыгууну колдонушун каалайсыз. ConnectivityManager.bindProcessToNetwork процессти тандалган тармакка байланыштырат, ал эми эски setProcessDefaultNetwork эскиргенге чейин ушундай эле иштейт. Астындагы туташууну NET_CAPABILITY_NOT_VPN менен сураңыз, байлоо туннелдин астындагы тармакты тандасын, туннелдин өзүн эмес.
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
.build();Процессти байлоо экинчи VPN эмес. Ал ошол процесс үчүн чыгууну тандайт, бул сиздин транспортуңузга пайдалуу жана бир убакта эки туннелди жүргүзүүгө пайдасыз.
Колдонуучунун түзмөгүн оңдоңуз, коддун жолун эмес
Эки колдонмого VPN ордун бөлүшүүгө уруксат берген API жок, ошондуктан оңдоо түзмөктүн абалына таандык. Колдонуучуга эки так жол сунуштаңыз: башка колдонмонун туташуусун үзүңүз же дайыма күйүк жөндөөсүн өчүрүңүз, ошондо prepare кабыл алат, же ошол колдонмонун колдонмо боюнча жөндөөлөрүн ачып, өз колдонмоңузду анын туннелинен чыгарыңыз. Четтетүү фильтрди калган бардык нерсе үчүн иштеп турат жана колдонмоңузга кадимки туташууну колдонууга мүмкүндүк берет, бул көбүнчө колдонуучу чындап каалаган жыйынтык.
Эки жолду тең колдоо документтериңизге жазыңыз, анткени колдонуучулар кайсы колдонмо VPN ге ээ экенин сейрек билишет. Алардан параметрлерден активдүү VPN атын жана журналдарыңыздан prepare, establish жана protect жыйынтыктарын жөнөтүүнү сураныңыз, бир мүнөттүн ичинде кайсы кадам ишке ашпаганын айта аласыз. Андан кийин реалдуу трафик менен текшериңиз: ат издөө, TCP туташуу жана туннель аркылуу бир сурам, жөн гана туташкан белги эмес. Жарактуу дескриптор жана жашыл көрсөткүч эң мыкты учурда ээликти далилдейт, транспорттун маршруттоо эрежелеринен өткөнүн эч качан эмес.
Эгер төрт текшерүүнүн баары өтсө да трафик өлүп жатса, ээлик мындан ары сиздин көйгөйүңүз эмес. Маршруттоо жана сервердин жеткиликтүүлүгүнө өтүңүз, ошол эле эсептик маалыматтарды VPN колдонмосу орнотулбаган түзмөктөн текшериңиз.