Android VpnService मा स्प्लिट टनेलिङ: वास्तवमा के रुट गर्न सकिन्छ
VpnService ले builder ले आफ्नो डिस्क्रिप्टरमा पठाएका प्याकेट मात्र पठाउँछ। स्प्लिट टनेलिङलाई दोष दिनुअघि प्रिफिक्स, प्रोक्सी प्रमाणीकरण, DNS र एप सूची जाँच गर्नुहोस्।
VpnService एपमा स्प्लिट टनेलिङ केही निश्चित ठाउँमा बिग्रन्छ, र प्रत्येकको समाधान फरक छ। क्लाइन्टले असफल भएको एउटा मात्र गन्तव्य देखाउँछ, त्यसैले पहिलो काम तपाईं कुन सीमामा ठोकिनुभएको छ भनी पत्ता लगाउनु हो: builder ले पाएका रुटहरू, प्रमाणित गर्न नसकिने प्रोक्सी, मात्र घोषणा गरिएको resolver, वा प्लेटफर्मले प्रत्येक प्रयोगकर्ताका लागि लागू गर्ने एप सूची। त्यसैले मैले चार चरणको जाँच राखेको छु। यो तलको क्रममा चल्छ र पहिलो असफलतामा रोकिन्छ।
builder ले प्लेटफर्मलाई के दियो भनी पुष्टि गर्नुहोस्
VpnService.Builder घोषणाहरूको सूची हो। establish() ले भर्चुअल इन्टरफेसका लागि ParcelFileDescriptor फर्काउँछ, र प्लेटफर्मले त्यो डिस्क्रिप्टरमा addAddress र addRoute का प्रिफिक्ससँग मिल्ने ट्राफिक मात्र पठाउँछ; addDnsServer ले क्लाइन्टलाई कुन resolver सोध्ने बताउँछ। तपाईंले थपेका सबै प्रिफिक्सबाहिरको गन्तव्य इन्टरफेसले जे वाचा गरे पनि तपाईंको एपमा कहिल्यै पुग्दैन। यही एउटा तथ्यले कोड बदल्नुअघि नै बिग्रिएको स्प्लिट टनेलिङका अधिकांश रिपोर्ट व्याख्या गर्छ।
तपाईंको builder ले बनाएका ठेगाना, रुट र DNS सूची लग गर्नुहोस्, त्यसपछि असफल हुने गन्तव्यसँग तुलना गर्नुहोस्। व्यवस्थापन होस्टका लागि हराएको /32 बिग्रिएको टनेलभन्दा धेरै सामान्य हुन्छ। सूची ठीक छ भने अगाडि बढ्नुहोस्; गलत छ भने बाँकी जाँच-सूची व्यर्थ श्रम हो।
excludeRoute API 33 देखि मात्र छ
गन्तव्य-आधारित बहिष्करण सबैभन्दा धेरै सहयोग थ्रेड बन्ने अनुरोध हो। builder.excludeRoute(IpPrefix) API 33 मा आयो; त्यसअघि एकमात्र समर्थित अनुमान बहिष्कृत प्रिफिक्सबाहेक सबैका लागि रुट थप्नु हो, अर्थात् पूरक प्रिफिक्स तपाईं आफैले गणना गर्नुपर्छ। दुई कल ऐनाका प्रतिबिम्ब होइनन्: एउटा इन्टरफेसको रुट सेटबाट घटाउँछ, अर्को सेट शून्यबाट बनाउँछ, र पुरानो यन्त्रले नचिनेको कल फ्याँक्छ वा चुपचाप बेवास्ता गर्छ। Build.VERSION.SDK_INT अनुसार शाखा बनाउनुहोस् र दुवै बाटो वास्तविक हार्डवेयरमा परीक्षण गर्नुहोस्।
पूरक गणना गर्दा प्रिफिक्सको पङ्क्तिबद्धतामा ध्यान दिनुहोस्। /16 रुटभित्र /24 बहिष्करणका लागि बाँकी भागलाई साँच्चै वर्णन गर्ने आवरण प्रिफिक्स चाहिन्छ, एउटा विकृत /8 होइन। अन्तिम सूची लग गर्नुहोस् र बहिष्कृत होस्ट अझै टनेलबाहिरको बाटोबाट समाधान हुन्छ भनी पुष्टि गर्नुहोस्।
प्रोक्सी प्रमाणहरू व्यक्त गर्न सकिँदैन
setHttpProxy(ProxyInfo) ले इन्टरफेसलाई HTTP वा SOCKS प्रोक्सीतिर फर्काउँछ, र PAC URL ले प्रत्येक गन्तव्यका लागि दुईबीच छान्न सक्छ। ProxyInfo वा PAC ढाँचा कुनैले पनि प्रयोगकर्ता नाम र पासवर्ड बोक्दैन, त्यसैले प्रमाणीकरण चाहिने प्रोक्सी प्लेटफर्म API बाहिर रहन्छ। यो चाहिने एपहरू सामान्यतया userspace स्ट्याक, tun2socks वा त्यस्तै इन्जिन राख्छन् र 407 चुनौतीको जवाफ आफै दिन्छन्।
यो छनोटका परिणाम छन्। userspace स्ट्याकले तपाईंले त्यसतर्फ रुट गरेको ट्राफिक मात्र देख्छ, त्यसैले यो एउटै डिस्क्रिप्टर सीमाभित्र बस्नुपर्छ, र आफ्नै uplink सकेटका लागि त्यही protect() आवश्यकता पाउँछ। protect() छोड्नुभयो भने टनेलले आफ्नै ट्रान्सपोर्ट समात्छ, जुन पहिलो प्याकेटपछि अड्किने ह्यान्डशेकका रूपमा देखिन्छ। प्रमाण माग्ने प्रोक्सीविरुद्ध परीक्षण गर्नुहोस्, किनकि खुला प्रोक्सी प्लेटफर्मको बाटोबाट जान्छ र केही पनि प्रमाणित गर्दैन।
प्रति-एप सूची र DNS पनि घोषणा हुन्
Builder मा addAllowedApplication र addDisallowedApplication दुवै छन्, र ती परस्पर विरोधी छन्: दुवै कल गर्दा अपवाद फ्याँकिन्छ। जे भए पनि सूची इन्टरफेस सेटअपमा प्रत्येक प्रयोगकर्ताका लागि लागू हुन्छ, त्यसैले कार्य प्रोफाइलको एप तपाईंको टनेलले होइन, कार्य प्रोफाइलको टनेलले नियन्त्रण गर्छ। कुनै API ले नदिने कुरा अर्को एपको निर्णयमाथिको नियन्त्रण हो: बाहिरबाट प्याकेट तपाईंको टनेलमा धकेल्न सकिँदैन, र पहिले नै सक्रिय VPN बन्द वा पुनः कन्फिगर गर्न सकिँदैन।
DNS ले पनि त्यही ढाँचा पछ्याउँछ। addDnsServer ले resolver ठेगाना घोषणा गर्छ; यसले तपाईंको एपलाई प्रश्नको जवाफ दिन दिँदैन। आफै नाम समाधान गर्न चाहनुहुन्छ भने resolver चलाउनुहोस् र त्यसको ठेगाना टनेलमा रुट गर्नुहोस्। स्थिर होस्टनाममा DoT वा DoH प्रयोग गर्ने एपहरूले तपाईंले घोषणा गरेको ठेगाना छल्न सक्छन्, त्यसैले प्रश्नको बाटो पनि अवरोध नगरेसम्म नाम समाधानलाई उत्तम प्रयास मान्नुहोस्।
Manifest, always-on र चार चरणको परीक्षण
योग्यता manifest मा घोषणा गरिन्छ: BIND_VPN_SERVICE, android.net.VpnService intent फिल्टर, र टनेल पृष्ठभूमिमा टिक्नुपर्ने भए foreground सेवा। Always-on VPN ले थप रूपमा सफा onRevoke माग्छ, किनकि प्रयोगकर्ताले सेटिङ बदल्दा वा अर्को एपले नियन्त्रण लिँदा प्रणालीले यसलाई कल गर्छ।
जाँचहरू क्रममा चलाउनुहोस् र पहिलो असफलतामा रोकिनुहोस्। पहिलो, builder लाई दिइएका ठेगाना, रुट र DNS सूची निकाल्नुहोस्। दोस्रो, establish() ले डिस्क्रिप्टर फर्काएको र ट्रान्सपोर्ट सकेट सुरक्षित छ भनी पुष्टि गर्नुहोस्। तेस्रो, समावेश गरिएको प्रिफिक्सभित्र एउटा र बहिष्कृत प्रिफिक्सभित्र एउटा गन्तव्य माग्नुहोस्। चौथो, तपाईंको resolver ले मात्र समाधान गर्न सक्ने होस्टनाम सोधेर कुन resolver ले साँच्चै जवाफ दियो जाँच्नुहोस्।
पूरा भएको ह्यान्डशेकले पछिल्ला कुनै पनि चरण प्रमाणित गर्दैन। प्रत्येक जाँचले एउटा तह अलग गर्छ, त्यसैले दोस्रो चरणको सफलताले चौथोबारे केही भन्दैन।
VpnService.Builder सन्दर्भ ले builder को सम्पूर्ण सतह सूचीबद्ध गर्छ। यसभन्दा बाहिर चाहिने जे पनि अर्को API, अर्को एप वा तपाईंको आफ्नै userspace स्ट्याक हो, र त्यो स्प्लिट-टनेल बग नभई डिजाइन निर्णय हो।