VpnService protect() या ऐप को छोड़ना: राउटिंग क्या ठीक करता है
टनल ले जाने वाले सॉकेट को सुरक्षित करें, या पूरे ऐप को बाहर रखें: वे तीन शर्तें जो तय करती हैं कि आपके Android VPN को कितना दायरा चाहिए।
टनल के अपने पैकेट टनल से बाहर रखने के दो तरीके हैं: ट्रांसपोर्ट सॉकेट को सुरक्षित करें, या पूरे ऐप को VPN से बाहर निकालें। ये अलग-अलग समस्याएँ हल करते हैं, और जोड़ना आसान होने के कारण बड़े दायरे को चुनना ही वह रास्ता है जिससे ऐप्स बिना ध्यान दिए लोकल नेटवर्क तक पहुँच और बँटा हुआ DNS खो देते हैं। जो टनल से बाहर रहना चाहिए उससे शुरू करें, फिर वह सबसे छोटा दायरा चुनें जो उसे हासिल करता है।
protect() टनल से क्या हटाता है
VpnService.protect() प्रति-सॉकेट कॉल है। आप उसे वह सॉकेट या डिस्क्रिप्टर देते हैं जो टनल ले जाता है, और Android उस सॉकेट को चिह्नित करता है ताकि उसका ट्रैफ़िक VPN इंटरफ़ेस के बजाय नीचे के नेटवर्क का उपयोग करे। बाकी सब कुछ जो ऐप भेजता है वह सामान्य VPN मार्ग का ही पालन करता है।
यही संकरा दायरा मुद्दा है। संरक्षित सॉकेट यह नहीं बदलता कि आपका HTTP क्लाइंट नाम कैसे हल करता है, आपकी एनालिटिक्स कॉल कौन-सा इंटरफ़ेस इस्तेमाल करती हैं, या बाद में खुले दूसरे कनेक्शन का क्या होता है।
दायरा तय करने वाली तीन शर्तें
पहली शर्त यह है कि क्या केवल टनल के ट्रांसपोर्ट को बाहर निकलना है। अगर ऐप का बाकी ट्रैफ़िक अब भी VPN से गुज़रना चाहिए, तो सॉकेट सुरक्षा सही दायरा है। दूसरी शर्त यह है कि क्या सॉकेट बनाना आपके नियंत्रण में है। जो लाइब्रेरी भीतर गहरे में अपना सॉकेट खोलती है, वह आपकोprotect() कॉल करने की जगह नहीं देती, जब तक कि वह कोई हुक न दे या पहले से बना सॉकेट न ले। तीसरी शर्त यह है कि क्या ऐप को सीधे लोकल नेटवर्क या captive portal तक पहुँचना है, जो टनल को जीवित रखने से अलग आवश्यकता है।
ऐप कोaddDisallowedApplication() से छोड़ना मोटा औज़ार है। यह ऐप के हर कनेक्शन को VPN से हटा देता है, उन सहित जिन्हें आप जाँचना चाहते थे, और कुछ डिवाइसों पर यह लोकल खोज का व्यवहार भी बदल देता है।
तीसरा विकल्प है ट्रांसपोर्ट को चुने हुए नेटवर्क से बाँधना:bindProcessToNetwork() या सॉकेट-स्तर के नेटवर्क हैंडल से। यह तब उपयोगी है जब डिवाइस में एक साथ Wi-Fi और मोबाइल हो और आप चाहें कि टनल किसी खास अपलिंक से जाए।
ट्रांसपोर्ट बनते समय ही इसे कॉल करें
कॉल करेंprotect() उसी ब्लॉक में जो ट्रांसपोर्ट बनाता है,connect() याsend() से पहले। अगर कॉल false लौटाए, तो सॉकेट बंद करें और सेटअप विफल करें; जारी रखने पर आपके पास ऐसा ट्रांसपोर्ट रह जाता है जिसके पैकेट आपके अपने इंटरफ़ेस में फिर से आ सकते हैं।
आकार इतना छोटा है कि एक ही जगह रखा जा सके:
DatagramSocket transport = new DatagramSocket();
if (!protect(transport)) {
transport.close();
throw new IOException("transport not protected");
}
transport.connect(serverAddress);यहाँ तीन ब्यौरे काटते हैं। पहला,बुलियन ही वह अकेला संकेत है जो आपको मिलता है, इसलिए विफलता को इतने संदर्भ के साथ दर्ज करें कि रद्द की गई सहमति और अस्वीकृत कॉल में फ़र्क़ पड़ सके। दूसरा,protect() सॉकेट को कवर करता है, डिस्क्रिप्टर संख्या को नहीं: अगर आप सॉकेट बंद करें और बाद में वही पूर्णांक किसी दूसरे सॉकेट के लिए दोबारा इस्तेमाल करें, तो नया सॉकेट संरक्षित नहीं है। तीसरा, जब कोई नेटिव लाइब्रेरी ट्रांसपोर्ट खोलती है, तो नेटिव कोड के जुड़ने से पहले डिस्क्रिप्टर सुरक्षित करें, वरना मार्ग पहले ही चुना जा चुका हो सकता है।VpnService संदर्भ यह जाँचने की जगह है कि आपका लक्षित API स्तर वास्तव में कौन-से ओवरलोड देता है।
सिर्फ़ सुखद मार्ग नहीं, अवरुद्ध मार्ग भी जाँचें
टनल चालू रखकर सत्यापित करें, क्योंकि यही अकेली अवस्था है जिसमें दोनों मार्ग अलग हो सकते हैं। संरक्षित ट्रांसपोर्ट से एक अनुरोध भेजें और protect() कभी कॉल न करने वाले कोड मार्ग से दूसरा, फिर तुलना करें कि दूर का सिरा क्या देखता है: संरक्षित कनेक्शन को नीचे के नेटवर्क के साथ स्रोत बनकर आना चाहिए, जबकि असुरक्षित कनेक्शन टनल का अपना पता दिखाता है और टनल के बाइट काउंटर हिलाता है। डिवाइस पर ss याnetstat रेडियो से कुछ निकलने से पहले वही बँटवारा दिखाते हैं।
रद्दीकरण अलग से जाँचें, क्योंकि सहमति बदलने पर इंटरफ़ेस बिना आपके सॉकेट कोड को छुए ढह जाता है। VPN सहमति रद्द करें या सेवा रोकें, ट्रांसपोर्ट फिर से बनाएँ, और पुष्टि करें किprotect() अब भी true लौटाता है और सहमति दोबारा मिलते ही ट्रांसपोर्ट फिर जुड़ जाता है।
अगर संरक्षित अनुरोध फिर भी टनल का पीछा करे, तो सुरक्षा कॉल संभवतः सॉकेट के राउट हो चुकने के बाद हो रही है। इसे पहले खिसकाएँ और फिर जाँचें।
फ़ैसला ट्रांसपोर्ट सेटअप के पास लिखा रखें: कौन-से सॉकेट संरक्षित हैं, कौन-सा ऐप ट्रैफ़िक छोड़ा गया है, और सुरक्षा विफल होने पर ऐप क्या करता है। यही पंक्ति आगे के रीफ़ैक्टर को एक परीक्षण विफल होने के कारण छूट को पूरे ऐप तक बढ़ाने से रोकती है। यह अगले व्यक्ति को मैनिफ़ेस्ट को उलटे इंजीनियरिंग के बिना मंशा जाँचने का तरीक़ा भी देती है।