Android VpnService बारेका चार अनुमानले मलाई एकचोटि हप्ताको ठूलो भाग खर्च गराए, र तीमध्ये एउटै पनि नेटवर्क प्रोटोकलबारे थिएन। एपले जोडिएको छ भन्यो, साँचोको आइकन स्थिति पट्टीमा बस्यो, र ट्राफिक अझै सामान्य रुटबाटै बाहिर जाँदै थियो। म सुरुङ मेरै हो भन्ने मान्दै रहें जबसम्म म यसलाई रोक्दिनँ, मैले थपेका रुट नै मैले पाउने रुट हुन्, र stopSelf बोलाउँदा इन्टरफेस पनि सँगै तल झर्छ। सेवा ठ्याक्कै कागजातमा भएझैं व्यवहार गर्दै थियो। टुटेको भाग मेरो मानसिक मोडेल थियो।

मिथ 1: सुरुङ तपाईंले रोक्नुभएसम्म उभिरहन्छ

Android एक पटकमा एउटै VPN इन्टरफेस राख्छ। दोस्रो स्थापना गर्नुहोस् र प्लेटफर्मले यसलाई कतारमा राख्दैन, तपाईंको निष्क्रिय गर्छ र तपाईंको सेवामा onRevoke() बोलाउँछ। यदि तपाईंको कोड बटन थिच्दा मात्र सबै भत्काउँछ भने, कब्जाले पछाडि एउटा डेस्क्रिप्टर र एउटा रिडर थ्रेड छोड्छ, र अर्को सुरुवातले दुवैलाई उत्तराधिकारमा पाउँछ।

VpnService सन्दर्भ स्पष्ट भन्छ कि एपसँग पहिले नै सहमति छ भने prepare() null फर्काउँछ, र प्रयोगकर्ताले अझै स्वीकृति दिनुपर्ने भए Intent फर्काउँछ। त्यो सहमति तपाईंले मनसाय startActivityForResult() मार्फत पुर्‍याए मात्र आउँछ। यो हस्तान्तरण छोड्नुहोस् र establish() null फर्काउँछ, जसलाई अनुमति समस्या नभई शान्त असफलता भनेर पढिन्छ।

Always-on VPN ले तपाईंले नियन्त्रण नगर्ने मालिक थप्छ। प्रणालीले बुटपछि वा क्र्यासपछि सुरुङ फर्काउन सक्छ, र यसले प्रयोगकर्ताले हातले सुरु गरेको VPN एपलाई पछि पार्छ। onRevoke() लाई तपाईंको सामान्य बन्दले जत्तिकै स्रोत बन्द गर्ने गरी बनाउनुहोस्, र यसलाई कुनाको केस नभई मुख्य रोक्ने बाटो मान्नुहोस्। प्रयोगकर्ताहरू VPN एप बदल्छन्; तपाईंको कोडले त्यो सहनुपर्छ।

मिथ 2: addRoute ले ठ्याक्कै तपाईंले सूचीबद्ध गरेको कुरा समात्छ

कुन प्याकेट तपाईंको डेस्क्रिप्टरसम्म पुग्छन् भन्ने रुटले निर्धारण गर्छ, र दायराको गल्तीले केही ट्राफिक सुरुङबाट जाने र केही नजाने त्यो रिस उठाउने अवस्था बनाउँछ। addRoute("0.0.0.0", 0) ले सम्पूर्ण IPv4 लिन्छ, अर्थात् अब हरेक प्याकेट तपाईंकहाँ आउँछ र त्यसलाई अगाडि पठाउन वा फ्याँक्नुपर्छ। एउटै होस्टका लागि /32 ले लगभग केही पनि लिँदैन, र बाँकी सबै तपाईंको VPN कहिल्यै स्थापना नभएझैं व्यवहार गर्छ।

परिवारहरू अलग-अलग गनिन्छन्। केवल IPv4 भएको रुटले IPv6 लाई अन्तर्निहित नेटवर्कमा छोड्छ, त्यसैले दोहोरो स्ट्याक होस्ट सुरुङभित्र पूर्ण रूपमा जोडिएको देखिँदै पनि बाहिर नाम समाधान गर्न र जोडिन सक्छ।

DNS ले पनि त्यही तर्क पछ्याउँछ। addDnsServer() सँग थपिएका सर्भर सुरुङको रिजोल्भर प्रयोग गर्ने एपकहाँ जान्छन्, जबकि आफ्नै इन्क्रिप्टेड DNS इन्डपोइन्ट वा होस्टनाममा सेट गरिएको Private DNS भएको एपले तिनलाई पूर्ण रूपमा बेवास्ता गर्छ। जब नामहरू एउटा एपका लागि असफल हुन्छन् र अर्कोका लागि काम गर्छन्, एउटै रुट छुनुअघि रिजोल्भरको बाटो जाँच्नुहोस्।

मिथ 3: एपअनुसारका नियम दुवैतिर घुमाउन सकिने स्विच हुन्

addDisallowedApplication() र addAllowedApplication() दुई फिल्टर नभई दुई मोड हुन्। बिल्डरले प्रति सुरुङ एउटै मोडेल स्वीकार्छ, त्यसैले तीन प्याकेजबाहेक सबै चाहने एपले निषिद्ध सूची प्रयोग गर्छ र अनुमति दिइएको सूची खाली छोड्छ। दुवै परस्पर अनन्य छन्, र मानिसहरूले यो रनटाइममा थाहा पाउँछन् जब सेटिङ स्क्रिनले पहिले नै दुवै टगल देखाइसकेको हुन्छ।

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

कार्य प्रोफाइलले दर्शकलाई फेरि बाँड्छ। प्रोफाइलभित्र सुरु गरिएको सुरुङले त्यो प्रोफाइल र त्यसका एप समेट्छ, जबकि व्यक्तिगत पक्षले आफ्नै जडान राख्छ। यो एकचोटि लिइने दायराको निर्णय हो, र यसको ठाउँ सपोर्ट टिकटमा नभई इन्टरफेसमा छ।

मिथ 4: stopSelf ले सुरुङ अन्त्य गर्छ

गर्दैन। इन्टरफेस establish() ले फर्काउने डेस्क्रिप्टरभित्र बस्छ, र त्यो डेस्क्रिप्टर खुला रहँदा सेवा वस्तु मर्न सक्छ। पहिले ParcelFileDescriptor बन्द गर्नुहोस्, सन्दर्भ छोड्नुहोस्, रिडर र राइटर थ्रेड जोड्नुहोस् वा अवरोध गर्नुहोस्, त्यसपछि stopForeground(true) र stopSelf() त्यही क्रममा बोलाउनुहोस्।

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

उल्टो गल्ती पनि उत्तिकै सामान्य छ: रिडर थ्रेड पढ्ने बीचमा हुँदा डेस्क्रिप्टर बन्द गर्नु, र त्यसपछि त्यो थ्रेडलाई कसैले कोड नलेखेको अपवाद सम्हाल्न छोड्नु। सटडाउन क्रम एकै ठाउँमा राख्नुहोस् र प्रयोगकर्ताको कार्य र onRevoke() दुवैले त्यसमा बोलाउन्।

सुरुङ मरेजस्तो देखिँदा के जाँच्ने

सुरुङ माथि आउनुअघि लामो आयुका सकेट protect() ले सुरक्षित गर्नुहोस्। त्यो बिना सुरुङको आफ्नै यातायात फेरि सुरुङभित्र रुट हुन्छ र जडान सर्भर खराबीसँग ठ्याक्कै मिल्ने तरिकाले अड्किन्छ। टाढाको नेटवर्कपछि मात्र रहेको ठेगानाविरुद्ध परीक्षण गर्नुहोस्, क्यास वा अन्तर्निहित बाटोबाट जवाफ दिने सार्वजनिक साइटविरुद्ध होइन।

establish() को नतिजा, रुट, बहिष्कृत प्याकेज र बन्द गर्ने कारण लग गर्नुहोस्। ती चार लाइनले प्याकेट क्याप्चरबिना सहमतिको समस्यालाई दायराको समस्या र जीवनचक्रको समस्याबाट छुट्याउँछन्।

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