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 लाई “ट्राफिक कुनै सुरुङबाट बाहिर जान्छ” भनेर बुझ्नुहोस् र आफ्नो हिसाब अलग राख्नुहोस्। तीनवटा कुरा चुपचाप एकैसाथ जनाउने बुलियन भनेकै प्रयोगकर्ता VPN मार्फत ब्राउज गर्दै गर्दा सेटिङ स्क्रिनले VPN बन्द भनेर देखाउनुको कारण हो।

यसको उल्टो, कुनै पनि VPN नेटवर्क अवस्थित छ कि छैन जान्नुछ भने cm.getAllNetworks() मा दोहोर्याएर हरेक क्षमता समूह जाँच्नुहोस्। दुई उत्तर अन्य एपहरू समेट्ने तर तपाईंकालाई नसमेट्ने एप-विशेष VPN चलिरहेको यन्त्रमा फरक पर्छन्, र त्यही फरक स्पष्ट रूपमा खुला VPN एपले देख्दैन भन्ने अधिकांश बग रिपोर्टको स्रोत हो।

पोलिङको सट्टा परिवर्तनहरू नियाल्नुहोस्

टाइमरमा पोलिङ गर्नु यो प्रश्नका लागि गलत ढाँचा हो, किनकि स्थिति परिवर्तनहरू घटनाका रूपमा आउँछन्। 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 मा दर्ता रद्द गर्नुहोस्, र पहिले नै गइसकेको गतिविधिमा callback झुन्ड्याएर नराख्नुहोस्। देखिने कम्पोनेन्ट नभएको एप स्थायी अवलोकनकर्ताका लागि खराब आयोजक हो, र बिर्सिएका callback नै कन्फिगरेसन परिवर्तनपछि क्र्यास हुने हुन्।

तीन प्रश्न अलग राख्नुहोस्

यस क्षेत्रको धेरैजसो भ्रम तीन फरक जाँचलाई एउटै ठान्नबाट आउँछ। तिनीहरू फरक API प्रयोग गर्छन्, र एउटा सत्य हुँदा अरू असत्य हुन सक्छन्।

QuestionHow you answer itWhat a yes means
Did the user grant VPN consent to my app?VpnService.prepare() returns nullConsent exists; the tunnel may still be down
Is the device sending default traffic through a VPN?TRANSPORT_VPN on the active networkSomething is tunneling, not necessarily your app
Did this request arrive through the VPN?Source address seen by the serverProof for that connection, nothing wider

तेस्रो पङ्क्ति मानिसहरूले क्लाइन्टमा उत्तर दिन खोज्ने हो, र त्यहाँ उत्तर दिन सकिँदैन। VPN क्लाइन्टहरूलाई आफ्नै ठेगाना पूल दिनुहोस् र सर्भरमा स्रोत ठेगाना पढ्नुहोस्; सत्रको बीचमा प्रयोगकर्ताले सुरुङ फेरे पनि टिक्ने एउटै प्रमाण त्यही हो।

गलत सकारात्मक नतिजा हटाउने प्रमाणीकरण क्रम

अझै प्रचलनमा रहेको पुरानो नमुना कोडले getNetworkInfo(ConnectivityManager.TYPE_VPN) कल गर्छ। त्यो कल अप्रचलित छ, र धेरै संस्करणमा VPN जोडिएको हुँदा पनि null फर्काउँथ्यो, त्यसैले धेरै प्रतिलिपि गरिएका टुक्राहरू काम गर्ने यन्त्रमा बिग्रिएका देखिन्छन्। क्षमता जाँचहरूले त्यो जाल टार्छन् र Android 5.0 देखि उही व्यवहार गर्छन्। अझै त्यो कल गर्ने कोडबेस राख्नुहुन्छ भने फलब्याकमा बेरेर नराखी कल आफैं बदल्नुहोस्, किनकि गलत उत्तर पहिले उत्पन्न गर्ने त्यही फलब्याक हो।

एउटा छोटो बाटोले चेतावनी पाउनुपर्छ। बाह्य सेवाले रिपोर्ट गर्ने सार्वजनिक ठेगानालाई VPN को निर्गमन ठेगानासँग तुलना गर्नुले मार्गबारे केही प्रमाणित गर्छ, तर प्रत्येक जाँचमा तेस्रो पक्षको अनुरोध थप्छ, त्यो सेवा चलिरहनुमा निर्भर हुन्छ, र क्यास वा अवरुद्ध हुन सक्छ। यसलाई हातले गरिने निदानका रूपमा राख्नुहोस्, एपभित्रको स्थिति जाँचका रूपमा कहिल्यै नराख्नुहोस्।

यो क्रममा जाँचहरू चलाउनुहोस् र प्रयोगकर्ताको रिपोर्टसँग नमिल्ने पहिलोमा रोक्नुहोस्: shell को ट्रान्सपोर्ट सूची, सक्रिय नेटवर्क क्षमता, सुरुङ खोल्दा र बन्द गर्दाको callback घटना, त्यसपछि सर्भर-पक्षको स्रोत ठेगाना। चारै मिले पनि एपले गलत व्यवहार गर्छ भने बग Android को नेटवर्क दृष्टिकोणमा होइन, तपाईंको आफ्नै स्थिति यन्त्रमा छ।

सम्बन्धित लेखहरू