Android дээр VPN холбогдсон эсэхийг кодоор хэрхэн шалгах
Android-д VPN холбогдсон эсэхийг буцаадаг getter байхгүй. Сүлжээний боломжуудыг асууж, тээврийн өөрчлөлтийг ажиглаж, аппын зөвшөөрөл, төхөөрөмжийн төлөв, серверийн нотолгоог тус тусад нь бариарай.
Android-оос VPN холбогдсон эсэхийг асууж болохгүй. VpnService холбогдсон төлөвийг буцаадаг getter гаргадаггүй бөгөөд статус мөрөнд байгаа түлхүүрийн дүрсийг систем зурдаг, таны апп уншиж чадах зүйл биш. Таны хийж чадах зүйл бол холболтын стект илүү нарийн асуулт тавих: энэ аппын урсгал аль сүлжээг ашиглаж байна, тэр сүлжээ VPN тээврийг зөөж байна уу. Энэхүү гарын авлага хуурамч эерэг үр дүнгээс зайлсхийх дарааллаар шалгалтуудыг гүйцэтгэнэ: төхөөрөмж дээрх shell командаас апп дотор үлдээсэн callback хүртэл.
Аппын кодонд хүрэхээс өмнө төхөөрөмжийг shell-ээс шалгана уу
Эхлээд суурь төлөвийг авна уу. adb shell dumpsys connectivity системийн мэддэг бүх сүлжээг хэвлэдэг бөгөөд блок бүр өөрийн тээврүүдийг жагсаадаг тул VPN сүлжээ тэр жагсаалтад VPN-тэй хамт гарч ирнэ. Бусдаас өмнө анхдагч сүлжээний блокыг уншаад, дараа нь ижил тээврийг зөөж буй бусад сүлжээг хайна уу.
Хоёр гаралт өөр өөр асуултад хариулдаг. VPN сүлжээ байгаа эсэх нь таны апп үүнийг ашиглаж байгаа эсэхтэй ижил биш бөгөөд ажлын профайл эсвэл хоёр дахь хэрэглэгчтэй төхөөрөмж дээр таны процесс интернеттэй шууд ярьж байх үед хоёул нэгэн зэрэг үнэн байж болно. Сокетууд юу хийдгийг идэвхтэй сүлжээний мөр шийддэг.
Аппын ашиглаж буй сүлжээг асууна уу
Кодонд боломжийн тест дөрвөн мөр байна. Манифестод ACCESS_NETWORK_STATE хүсээд, дараа нь идэвхтэй сүлжээний боломжуудыг VPN тээвэртэй харьцуулна уу:
ConnectivityManager cm = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
Network active = cm.getActiveNetwork();
NetworkCapabilities caps = cm.getNetworkCapabilities(active);
boolean vpnInUse = caps != null
&& caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
Хариулт санаатайгаар нарийн: аппын анхдагч сүлжээ яг одоо VPN мөн үү. Аль VPN, энэ таных уу, туннель нөгөө үзүүрт хүрч байна уу гэдгийг энэ юу ч хэлэхгүй. true-ыг „урсгал ямар нэг туннелээр гарч байна“ гэж үзэж, өөрийн бүртгэлээ тусдаа бариарай. Гурван зүйлийг чимээгүйгээр нэгэн зэрэг илэрхийлдэг boolean нь хэрэглэгч VPN-ээр аялж байхад тохиргооны дэлгэц VPN-ыг унтарсан гэж мэдээлэх шалтгаан юм.
Харин ямар нэг VPN сүлжээ байгаа эсэхийг мэдэх шаардлагатай бол cm.getAllNetworks()-ыг давтаж, боломжийн багц бүрийг шалгана уу. Хоёр хариулт нь бусад аппд хамаарах боловч таны аппд хамаарахгүй апп-тус бүрийн VPN ажиллаж буй төхөөрөмж дээр салдаг бөгөөд тэр салалт нь „апп тодорхой асаалттай VPN-ыг харж чадахгүй“ гэсэн алдааны мэдээллийн ихэнхийн эх сурвалж юм.
Polling биш өөрчлөлтийг ажиглана уу
Таймер polling нь энэ асуултад тохиромжгүй хэлбэр, учир нь төлөвийн өөрчлөлтүүд үйл явдал хэлбэрээр ирдэг. VPN тээвэрт тохирох хүсэлтийг бүртгэж, тохирох сүлжээ гарч ирэх, алга болох эсвэл өөрчлөгдөх үед фреймворк өөрөө мэдэгдэх болтугай:
NetworkRequest request = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_VPN)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
.build();
cm.registerNetworkCallback(request, callback);
VPN сүлжээ хэзээ ч NET_CAPABILITY_NOT_VPN-ыг зөөдөггүй тул тодорхой хасах нь санааг баримтжуулна. Үүнгүйгээр ч хүсэлт тохирно, гэхдээ дараагийн уншигч үүнийг өөрөө олж мэдэх ёстой.
Бүртгэл нь ажиглалт шаардлагатай хүрээнд хамаарна, ихэвчлэн дэлгэц эсвэл урд талын үйлчилгээ. onStop эсвэл onDestroy дотор бүртгэлээ цуцалж, аль хэдийн алга болсон activity-д callback-ыг үлдээж болохгүй. Харагдах компонентгүй апп нь байнгын ажиглагчид муу хост бөгөөд мартсан callback-ууд нь тохиргооны өөрчлөлтийн дараа унадаг.
Гурван асуултыг тусад нь бариарай
Энэ салбарын төөрөгдлийн ихэнх нь гурван өөр шалгалтыг нэг гэж үзэхээс үүдэлтэй. Тэд өөр API ашигладаг бөгөөд нэг нь үнэн байхад бусад нь худал байж болно.
| Question | How you answer it | What a yes means |
|---|---|---|
| Did the user grant VPN consent to my app? | VpnService.prepare() returns null | Consent exists; the tunnel may still be down |
| Is the device sending default traffic through a VPN? | TRANSPORT_VPN on the active network | Something is tunneling, not necessarily your app |
| Did this request arrive through the VPN? | Source address seen by the server | Proof for that connection, nothing wider |
Гурав дахь мөр нь хүмүүс клиент дээр хариулахыг оролддог боловч тэнд хариулж болохгүй мөр юм. VPN клиентүүдэд өөрийн хаягийн санг өгч, сервер дээр эх хаягийг уншина уу; хэрэглэгч сессийн дунд туннель сольсон ч үлддэг цорын ганц нотолгоо энэ юм.
Хуурамч эерэг үр дүнг үгүйсгэх шалгалтын дараалал
Одоо ч эргэлдэж буй хуучин жишээ код getNetworkInfo(ConnectivityManager.TYPE_VPN)-ыг дууддаг. Тэр дуудлага хуучирсан бөгөөд хэд хэдэн хувилбарт VPN холбогдсон байсан ч null буцаадаг байсан тул хуулсан хэсгүүд ажиллаж буй төхөөрөмж дээр эвдэрсэн мэт харагддаг. Боломжийн шалгалтууд тэр урхийг зайлсхийж, Android 5.0-оос хойш ижил ажилладаг. Хэрэв үүнийг дууддаг кодын санг арчилж байгаа бол fallback-д ороож биш, дуудлагыг өөрөө соль, учир нь буруу хариултыг эхэнд нь бий болгосон нь яг тэр fallback байсан.
Нэг товчлол анхааруулга хүртэх ёстой. Гадаад үйлчилгээний мэдээлдэг нийтийн хаягийг VPN-ийн гарах хаягтай харьцуулах нь замын тухай ямар нэг зүйлийг нотолдог ч шалгалт бүрт гуравдагч талын хүсэлт нэмж, тэр үйлчилгээ ажиллаж байхыг шаардаж, кэшлэгдэх эсвэл блоклогдох боломжтой. Үүнийг гарын диагностик болгон бариарай, апп доторх төлөвийн шалгалт болгон хэзээ ч бүү ашигла.
Шалгалтуудыг энэ дарааллаар гүйцэтгэж, хэрэглэгчийн мэдээлэлтэй зөрчилдөх эхнийх дээр зогсоно уу: shell дэх тээврийн жагсаалт, идэвхтэй сүлжээний боломжууд, туннелийг асаах, унтраах үеийн callback үйл явдлууд, дараа нь сервер талын эх хаяг. Дөрөв нь ч тохирч байтал апп буруу ажиллаж байвал алдаа нь Android-ийн сүлжээний харагдацад биш, таны өөрийн төлөвийн машин дотор байна.