آپ کی ایپ VpnService.prepare کو کال کرتی ہے، null وصول کرتی ہے، ایک سرنگ بناتی ہے، اور ڈسکرپٹر درست دکھائی دیتا ہے، مگر سرور تک کچھ نہیں پہنچتا۔ یا prepare ایک Intent واپس کرتا ہے، صارف اسے منظور کرتا ہے، اور establish پھر بھی ناکام ہوتا ہے۔ دونوں نتائج عام طور پر ایک ہی بات کہتے ہیں: کوئی دوسری ایپ پہلے سے اس صارف کا VPN انٹرفیس رکھتی ہے، اور آپ کی protect کالیں ایسے ساکٹ نشان زد کر رہی ہیں جو آپ کی سرنگ استعمال نہیں کر سکتی۔ نیچے دی گئی جانچ ترتیب سے مکمل کریں اور پہلی ناکام جانچ پر رکیں، کیونکہ بعد کا مرحلہ پہلے والے کو ٹھیک نہیں کر سکتا۔

protect کو چھونے سے پہلے VPN سلاٹ کی جانچ کریں

اینڈرائیڈ ہر صارف کو بالکل ایک فعال 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 نہیں ہے۔ یہ اس عمل کے لیے اخراج منتخب کرتا ہے، جو آپ کی ترسیل کے لیے مفید ہے اور بیک وقت دو سرنگیں چلانے کے لیے بے کار۔

کوڈ کا راستہ نہیں، صارف کا ڈیوائس ٹھیک کریں

کوئی API ایسا نہیں جو دو ایپس کو VPN سلاٹ بانٹنے دے، اس لیے اصلاح ڈیوائس کی حالت سے متعلق ہے۔ صارف کو دو واضح راستے دیں: دوسری ایپ کا کنکشن منقطع کریں یا اس کی ہمہ وقت فعال سیٹنگ مٹائیں تاکہ آپ کا prepare قبضہ کر سکے، یا اس ایپ کی فی ایپ سیٹنگز کھول کر اپنی ایپ کو اس کی سرنگ سے باہر رکھیں۔ اخراج باقی سب کے لیے فلٹر جاری رکھتا ہے اور آپ کی ایپ کو عام کنکشن استعمال کرنے دیتا ہے، جو اکثر وہی نتیجہ ہوتا ہے جو صارف واقعی چاہتا ہے۔

دونوں راستے اپنی معاونت دستاویز میں لکھیں، کیونکہ صارفین شاذ و نادر ہی جانتے ہیں کہ کون سی ایپ VPN کی مالک ہے۔ ان سے کہیں کہ سیٹنگز سے فعال VPN کا نام اور اپنے لاگ سے prepare، establish اور protect کے نتائج بھیجیں، اور آپ ایک منٹ میں بتا سکتے ہیں کہ کون سا مرحلہ ناکام ہوا۔ پھر حقیقی ٹریفک سے تصدیق کریں: نام کی تلاش، TCP کنکشن اور سرنگ کے ذریعے ایک درخواست، صرف منسلک آئیکن نہیں۔ درست ڈسکرپٹر اور سبز اشارہ زیادہ سے زیادہ ملکیت ثابت کرتے ہیں، یہ کبھی نہیں کہ ترسیل روٹنگ اصولوں سے بچ گئی۔

اگر چاروں جانچ پاس ہو جائیں اور ٹریفک پھر بھی مرے، تو ملکیت اب آپ کی مسئلہ نہیں ہے۔ روٹنگ اور سرور کی رسائی کی طرف بڑھیں، اور وہی اسناد ایسے ڈیوائس سے جانچیں جس میں کوئی VPN ایپ نصب نہ ہو۔

متعلقہ مضامین