तुमचे अ‍ॅप VpnService.prepare कॉल करते, null मिळवते, टनेल बांधते, आणि डिस्क्रिप्टर वैध दिसतो, तरीही सर्व्हरपर्यंत काहीही पोहोचत नाही। किंवा prepare Intent परत देतो, वापरकर्ता ते मंजूर करतो, आणि establish तरीही अयशस्वी होते। दोन्ही निकालांचा अर्थ सहसा एकच असतो: दुसरे अ‍ॅप या वापरकर्त्याचा VPN इंटरफेस आधीच धारण करते, आणि तुमचे protect कॉल अशा सॉकेटला चिन्हांकित करत आहेत जे तुमचे टनेल वापरू शकत नाही। खालील तपासण्या क्रमाने पूर्ण करा आणि पहिल्या अयशस्वी तपासणीवर थांबा, कारण नंतरची पायरी आधीची दुरुस्त करू शकत नाही।

protect ला स्पर्श करण्यापूर्वी VPN स्लॉट तपासा

Android प्रत्येक वापरकर्त्याला नेमक एक सक्रिय VPN इंटरफेस देतो। हा प्लॅटफॉर्मचा नियम आहे, तुमचे अ‍ॅप मागू शकणारी परवानगी नाही, म्हणून दोन्ही टनेल होऊ इच्छिणारे दोन क्लायंट एकत्र राहू शकत नाहीत।

दुसऱ्या अ‍ॅपसाठी सेट केलेला नेहमी-चालू VPN ही सर्वात कठीण परिस्थिती आहे, कारण सिस्टम ते अ‍ॅप जोडलेले ठेवते आणि ताबा घेण्यास नकार देते। AdGuard सारखा ट्रॅफिक फिल्टर, कॉर्पोरेट क्लायंट किंवा ग्राहक VPN स्लॉट धरून ठेवू शकतो, वापरकर्ता ते इन्स्टॉल आहे हे विसरलेला असताना। वापरकर्त्याला सेटिंग्ज उघडून VPN खाली सूचीबद्ध नोंद वाचायला सांगा; तिथले नाव हेच तुम्ही स्पर्धा करत असलेला मालक आहे। ती नोंद डिस्कनेक्ट होईपर्यंत किंवा नेहमी-चालू सेटिंग पुसली जाईपर्यंत, तुमचे VpnService इंटरफेस होऊ शकत नाही।

पायरी 1: prepare काय परत देतो ते वाचा

VpnService.prepare एका प्रश्नाचे उत्तर देते: हे अ‍ॅप VPN होऊ शकते का? संमती आधीच असल्यास ते null परत देते, आणि वापरकर्त्याला अजून मंजूरी द्यायची असल्यास Intent देते, जे तुम्ही startActivityForResult ने सुरू केले पाहिजे। null परत मिळणे हे पुढे जाण्याची परवानगी माना, establish यशस्वी होईल याचा पुरावा नाही।

Intent intent = VpnService.prepare(context);
if (intent != null) {
    startActivityForResult(intent, REQUEST_VPN);
}

Intent मार्ग परत आला आणि वापरकर्त्याने नकार दिला, तर पुढच्या प्रयत्नात prepare पुन्हा Intent परत देत राहील। लूपमध्ये पुन्हा प्रयत्न करण्याऐवजी निकाल कोड लॉग करा, कारण नाकारलेली संमती हा वापरकर्त्याचा निर्णय आहे, तात्पुरती त्रुटी नाही।

पायरी 2: इंटरफेस तुमच्या अ‍ॅपचा आहे याची खात्री करा

establish नंतर मिळणारा ParcelFileDescriptor हा तुमच्या मालकीचा पुरावा आहे, आणि कोणत्याही सॉकेट कामापूर्वी तो तपासणे योग्य आहे। null किंवा आधीच बंद असलेला डिस्क्रिप्टर म्हणजे इंटरफेस कधीही तयार झाला नाही, अपवाद दिसला नसला तरी। builder चे इंटरफेस नाव सिस्टम सक्रिय VPN साठी जे नाव सांगते त्याशी तुलना करा, चाचणी उपकरणावर dumpsys वापरून। जर ती वेगळी असतील, तर तुम्ही बांधलेले टनेल ट्रॅफिक वाहून नेणारे टनेल नाही।

adb shell dumpsys connectivity

तीच विसंगती जोडलेल्या चिन्हासोबत मृत ट्रॅफिकचे स्पष्टीकरण देते। सिस्टम दुसऱ्या अ‍ॅपचे टनेल दाखवते, तर तुमचा कोड आपल्या मालकीचा नसलेल्या इंटरफेसचा डिस्क्रिप्टर धरून ठेवतो।

पायरी 3: connect आधी protect कॉल करा

इंटरफेस तयार झाल्यावर, तुमचे अ‍ॅप उघडणारे सॉकेट डीफॉल्टने टनेलमध्ये मार्गित होतात। बाह्य ट्रान्सपोर्ट हा नियम पाळू शकत नाही, अन्यथा एन्क‍ॅप्स्युलेटेड पॅकेट इंटरफेसमध्ये परत येईल, म्हणून VpnService protect सॉकेटला VPN बायपास करून खालचे नेटवर्क वापरण्यासाठी चिन्हांकित करते। कॉल boolean परत देतो, आणि त्याकडे दुर्लक्ष करणे हाच निरोगी दिसणाऱ्या पण काहीही न वाहणाऱ्या सॉकेटपर्यंत पोहोचण्याचा मार्ग आहे।

connect किंवा bind आधी protect कॉल करा, कधीही नंतर नाही। सॉकेट जोडण्यापूर्वी किंवा बांधण्यापूर्वी संरक्षण जागेवर असले पाहिजे, कारण जोडलेल्या सॉकेटने आपला मार्ग आधीच निवडला आहे आणि नंतरचे protect त्याला विश्वासार्हपणे हलवत नाही। protect false परत देत असेल, तर थांबा आणि मालकी पुन्हा तपासा: इंटरफेस तुमच्या अ‍ॅपचा नसताना ते अयशस्वी होते, आणि तीच अवस्था दुसरे VPN मागे सोडते। false ची वापसी ही पायरी 1 वर परत जाण्याची खूण आहे, तोच सॉकेट पुन्हा प्रयत्न करण्याची नाही।

DatagramSocket socket = new DatagramSocket();
if (!vpnService.protect(socket)) {
    return;
}
socket.connect(serverAddress, serverPort);

पायरी 4: सॉकेट अवघड असेल तेव्हा प्रक्रिया बांधा

काही ट्रान्सपोर्ट एक सॉकेट नसतात: लायब्ररी अनेक उघडू शकते, किंवा सहाय्यक प्रक्रियेतील प्रत्येक कनेक्शनने समान एक्झिट वापरावी असे तुम्हाला वाटू शकते। ConnectivityManager.bindProcessToNetwork प्रक्रियेला निवडलेल्या नेटवर्कशी बांधते, आणि जुने setProcessDefaultNetwork अप्रचलित होण्यापूर्वी तेच काम करत होते। खालचे कनेक्शन NET_CAPABILITY_NOT_VPN सह मागा, जेणेकरून बांधणी तुमच्या टनेलखालील नेटवर्क निवडेल, टनेल स्वतः नाही।

NetworkRequest request = new NetworkRequest.Builder()
    .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
    .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
    .build();

प्रक्रिया बांधणे हे दुसरे VPN नाही। ते त्या प्रक्रियेसाठी एक्झिट निवडते, जे तुमच्या ट्रान्सपोर्टसाठी उपयुक्त आहे आणि एकाच वेळी दोन टनेल चालवण्यासाठी निरुपयोगी।

कोडचा मार्ग नव्हे, वापरकर्त्याचे उपकरण दुरुस्त करा

दोन अ‍ॅपना VPN स्लॉट सामायिक करू देणारे API नाही, म्हणून दुरुस्ती उपकरणाच्या स्थितीत आहे। वापरकर्त्याला दोन ठोस मार्ग द्या: दुसरे अ‍ॅप डिस्कनेक्ट करा किंवा त्याचे नेहमी-चालू पुसून टाका जेणेकरून तुमचे prepare ताबा घेऊ शकेल, किंवा त्या अ‍ॅपच्या प्रति-अ‍ॅप सेटिंग्ज उघडून तुमचे अ‍ॅप त्याच्या टनेलमधून वगळा। वगळणे उर्वरित सर्वांसाठी फिल्टर चालू ठेवते आणि तुमच्या अ‍ॅपला सामान्य कनेक्शन वापरू देते, जे बहुतेक वेळा वापरकर्त्याला प्रत्यक्षात हवे असलेले निकाल असते।

दोन्ही मार्ग तुमच्या सहाय्य दस्तऐवजात लिहा, कारण वापरकर्त्यांना कोणते अ‍ॅप VPN चे मालक आहे हे क्वचितच माहीत असते। सेटिंग्जमधून सक्रिय VPN नाव आणि तुमच्या लॉगमधून prepare, establish आणि protect चे निकाल पाठवायला सांगा, आणि एका मिनिटात कोणती पायरी अयशस्वी झाली ते सांगू शकता। नंतर प्रत्यक्ष ट्रॅफिकने पडताळा: नाव शोध, TCP कनेक्शन आणि टनेलमधून एक विनंती, केवळ जोडलेले चिन्ह नाही। वैध डिस्क्रिप्टर आणि हिरवा निर्देशक जास्तीत जास्त मालकी सिद्ध करतात, ट्रान्सपोर्ट मार्गनियमातून बचावला हे कधीही नाही।

चारही तपासण्या उत्तीर्ण झाल्या आणि ट्रॅफिक तरीही मरत असेल, तर मालकी आता तुमची समस्या नाही। मार्गनिर्देशन आणि सर्व्हरच्या उपलब्धतेकडे जा, आणि VPN अ‍ॅप इन्स्टॉल नसलेल्या उपकरणावरून तीच क्रेडेन्शियल्स तपासा।

संबंधित लेख