Android VPN टनेलबाट सबनेट कसरी बहिष्कृत गर्ने
VpnService ले मार्ग बहिष्कृत गर्न सक्दैन, त्यसैले तपाईं पूरक थप्नुहुन्छ: /8 का लागि आठ उत्पन्न प्रिफिक्सहरू, साथै बाँकी समात्ने IPv6, DNS र खोज जाँचहरू.
Android को VpnService मा कुनै बहिष्करण मार्ग छैन, र API पढ्ने कुनै पनि मात्राले एउटा उत्पन्न गर्दैन। Builder.addRoute() टनेलमा सधैं गन्तव्यहरू मात्र थप्छ, त्यसैले LAN खण्डलाई स्थानीय राख्नुको अर्थ त्यो खण्ड कहिल्यै मार्ग सूचीमा नपर्नु हो। यसको सट्टा तपाईं खण्डको पूरक थप्नुहुन्छ, जो साधारण प्रिफिक्सको रूपमा व्यक्त गरिन्छ। काम गणित हो, र यो केही अनुमानयोग्य ठाउँहरूमा असफल हुन्छ।
तलका जाँचहरू क्रममा गर्नुहोस्। प्रत्येकले अघिल्लो टिक्यो भनी मान्छ, त्यसैले तलका लक्षणहरू प्याच गर्नुको सट्टा पहिलो असफलतामा रोक्नुहोस्।
टनेलले के दाबी गर्छ त्यहीबाट सुरु गर्नुहोस्
0.0.0.0/0 लाई addRoute() मा पठाउँदा Android लाई प्रत्येक IPv4 गन्तव्य टनेलको हो भनी बताउँछ। त्यसैले धेरै क्लाइन्टहरू विभाजित टनेलिङमा अक्षम देखिन्छन्: तिनीहरू पूरै ठेगाना ठाउँ दाबी गर्छन् र त्यसपछि त्यसबाट घटाउने प्रयास गर्छन्। बिल्डरमा केही पनि घटाउँदैन। तपाईंले स्थानीय राख्न चाहेको नेटवर्कको लागि अझ विशिष्ट मार्गले मानिसहरूले अपेक्षा गरेको विपरीत गर्छ, किनभने सबैभन्दा लामो मिल्ने प्रिफिक्स जित्छ र त्यो नेटवर्क टनेलभित्र पर्छ।
मार्ग सूची नै सम्पूर्ण नीति हो। यसको पछाडि प्रत्येक गन्तव्यको भिटो छैन, र Builder सन्दर्भ ले त्यस्तो एक प्रदान गर्ने कुनै विधि सूचीबद्ध गर्दैन।
प्रिफिक्स गणितबाट पूरक उत्पन्न गर्नुहोस्
बहिष्कृत प्रिफिक्सको पूरक ठेगाना रूखको जरासम्मको बाटोमा यसका दाजुभाईहरूको समूह हो। 1 देखि बहिष्कृत लम्बाइसम्म प्रत्येक लम्बाइको लागि, तपाईंको प्रिफिक्स समेट्ने त्यो लम्बाइको ब्लक लिनुहोस्, प्रिफिक्सको ठीक तलको बिट पल्टाउनुहोस् र नतिजा दिनुहोस्। तपाईंले यसलाई चलाउनुअघि यो अमूर्त सुनिन्छ।
10.0.0.0/8 बहिष्कृत गर्दा आठ मार्ग प्राप्त हुन्छन्: 128.0.0.0/1, 64.0.0.0/2, 32.0.0.0/3, 16.0.0.0/4, 0.0.0.0/5, 12.0.0.0/6, 8.0.0.0/7, 11.0.0.0/8। तीमध्ये कुनैले पनि 10.0.0.0/8 समेट्दैन, र सँगै तिनीहरू बाँकी सबै ढाक्छन्।
आठ लाइनहरूले कुनै पनि प्रिफिक्सको लागि त्यो सूची उत्पन्न गर्छन्:
import ipaddress
def complement(addr, length):
base = int(ipaddress.IPv4Address(addr))
out = []
for k in range(1, length + 1):
block = base & (0xFFFFFFFF << (32 - k))
sibling = block ^ (1 << (32 - k))
out.append(f"{ipaddress.IPv4Address(sibling)}/{k}")
return out
print(complement("10.0.0.0", 8))
मार्गको संख्या प्रिफिक्स लम्बाइ बराबर हुन्छ, र त्यही ध्यान दिनुपर्ने संख्या हो। एउटा /21 बहिष्करणले 21 मार्ग खर्च गर्छ र पढ्न योग्य रहन्छ। दस बहिष्करणले केही सय खर्च गर्न सक्छ, जसको अर्थ सामान्यतया जेनेरेटर होइन, नेटवर्क डिजाइन बदल्नुपर्छ भन्ने हो।
ठेगाना परिवार र टनेलको दायरा जाँच्नुहोस्
IPv4 मार्गहरूले IPv6 का लागि केही गर्दैनन्। यदि टनेलले IPv6 ठेगाना दाबी गर्छ भने, IPv6 LAN प्रिफिक्सलाई आफ्नै पूरक चाहिन्छ, जो 128 बिटमा उही गणितबाट उत्पन्न हुन्छ। कागजमा बहिष्करण काम गर्ने तर स्थानीय उपकरण पुग्न नसक्ने रहनुको सामान्य कारण यही हो: होस्टमा IPv6 मार्फत पुगियो, र IPv4 मात्र काटियो। गणित गलत छ भनी निष्कर्ष निकाल्नुअघि दुवै परिवार जाँच्नुहोस्।
दायरा जाँचको अर्को आधा हो। Android ले नेटवर्क र एप अनुसार राउटिङ ट्र्याक गर्छ, त्यसैले एउटै प्रिफिक्स एउटा एपका लागि टनेलबाट र अर्कोका लागि सिधै जान सक्छ, VPN कसरी घोषणा गरियो त्यसमा निर्भर गर्दै।
DNS र प्रत्येक एपका नियम ठीक ठाउँमा राख्नुहोस्
मार्ग बहिष्करणले रिजोल्भर बदल्दैन। स्थानीय होस्टनाम अझै टनेलको DNS सर्भरबाट उत्तर पाउन सक्छ, जबकि यसको ठेगाना स्थानीय रूपमा राउट हुन्छ, र असंगति LAN पुग्न नसक्ने कुरामा समाधान हुने नामको रूपमा देखिन्छ। रिजोल्भर नीति जानाजानी सेट गर्नुहोस्, खोज डोमेन वा विभाजित DNS नियमसँग। मार्गहरूले तपाईंको लागि यो निर्णय गरे भनी नमान्नुहोस्।
addDisallowedApplication() एउटा एपलाई टनेलबाहिर राख्छ; भित्र रहने एपहरूका लागि गन्तव्य बाहिर राख्दैन। protect() तपाईंले खोल्नुभएको सकेटलाई टनेल छल्न दिन्छ, र यसरी टनेलले आफ्नै यातायात समात्नबाट बच्छ। दुवैले पूरकलाई प्रतिस्थापन गर्दैनन्।
आफ्नै सूचीले होइन, खोजले प्रमाणित गर्नुहोस्
टनेल उठेपछि, तपाईंले बनाएको सूची फेरि पढ्नुको सट्टा ठेगाना वास्तवमा कहाँ जान्छ भनी उपकरणलाई सोध्नुहोस्। iproute2 सहित आउने बिल्डमा, adb shell ip route get 10.1.2.3 ले कर्नेलले छानेको इन्टरफेसको नाम बताउँछ। सार्वजनिक ठेगानाका लागि उही आदेश चलाउनुहोस् र यसले टनेलको नाम बताउँछ भनी पुष्टि गर्नुहोस्।
अझै दुई जाँचले चक्र बन्द गर्छन्। पहिले स्थानीय नाम समाधान गर्नुहोस्, त्यसपछि समाधान भएको ठेगानामा adb shell ip route get चलाउनुहोस् र टनेल नभएको इन्टरफेस माग्नुहोस्, किनभने सफल adb shell ping -c 1 host.lan ले पहुँच प्रमाणित गर्छ, मार्ग होइन। टनेलले एक दाबी गरेमा IPv6 मा ठेगाना-परिवार परीक्षण दोहोर्याउनुहोस्। तपाईंले पठाउने API स्तरमा परीक्षण गर्नुहोस्, किनभने VPN नेटवर्कहरू राउटिङ तालिकासामु कसरी पर्दाफास हुन्छन् त्यो संस्करणहरूबीच बदलिएको छ। कागजमा सही देखिने मार्ग सूची र गलत इन्टरफेस छान्ने खोज फरक बग हुन्, र प्रयोगकर्तासम्म दोस्रो मात्र पुग्छ।
बहिष्करण सूची बढ्दै गएमा, मार्ग उत्पन्न गर्न रोक्नुहोस् र टाढाको नेटवर्क पुनः क्रमाङ्कन गर्नुहोस् वा यसको सट्टा टनेल साँघुरो बनाउनुहोस्। जेनेरेटर अनुपस्थित API को लागि उपाय हो, डिजाइन उपकरण होइन।