VpnService ایپ میں اسپلٹ ٹنلنگ چند مخصوص جگہوں پر ٹوٹتی ہے اور ہر ایک کا علاج الگ ہے۔ کلائنٹ صرف ایک ناکام منزل دکھاتا ہے، اس لیے پہلا کام یہ جاننا ہے کہ آپ کس حد سے ٹکراتے ہیں: وہ راستے جو builder کو ملے، وہ پراکسی جس کی تصدیق نہیں کر سکتے، وہ resolver جس کا صرف اعلان کیا، یا وہ ایپ فہرست جو پلیٹ فارم ہر صارف پر لاگو کرتا ہے۔ اسی لیے میں چار مرحلوں کی جانچ رکھتا ہوں۔ یہ نیچے دیے ترتیب سے چلتی ہے اور پہلی ناکامی پر رک جاتی ہے۔

تصدیق کریں کہ builder نے پلیٹ فارم کو کیا دیا

VpnService.Builder اعلانات کی فہرست ہے۔ establish() مجازی انٹرفیس کے لیے ParcelFileDescriptor واپس کرتا ہے، اور پلیٹ فارم اس ڈسکرپٹر میں صرف وہی ٹریفک بھیجتا ہے جو addAddress اور addRoute کے سابقوں سے میل کھاتی ہے؛ addDnsServer کلائنٹس کو بتاتا ہے کہ کون سا resolver پوچھیں۔ آپ کے شامل کردہ تمام سابقوں سے باہر کی منزل انٹرفیس کچھ بھی وعدہ کرے، آپ کی ایپ تک کبھی نہیں پہنچتی۔ یہی ایک حقیقت کوڈ بدلنے سے پہلے ہی ٹوٹی اسپلٹ ٹنلنگ کی زیادہ تر شکایات کی وضاحت کرتی ہے۔

اپنے builder نے جو پتہ، راستہ اور DNS فہرستیں ترتیب دیں انہیں لاگ کریں، پھر انہیں ناکام منزلوں سے موازنہ کریں۔ انتظامی میزبان کے لیے غائب /32 ٹوٹی ٹنل سے کہیں زیادہ عام ہے۔ فہرست درست ہو تو آگے بڑھیں؛ غلط ہو تو باقی چیک لسٹ بیکار محنت ہے۔

excludeRoute صرف API 33 سے موجود ہے

منزل کی بنیاد پر اخراج وہ درخواست ہے جو سب سے زیادہ معاونت کے دھاگے میں بدلتی ہے۔ builder.excludeRoute(IpPrefix) API 33 میں آیا؛ اس سے پہلے واحد supported طریقہ یہ ہے کہ خارج کردہ سابقے کے سوا ہر چیز کے لیے راستے شامل کیے جائیں، یعنی تکمیلی سابقے آپ خود شمار کریں۔ دونوں کالز آئینے کی تصویریں نہیں: ایک انٹرفیس کے راستہ سیٹ سے گھٹاتی ہے، دوسری سیٹ صفر سے بناتی ہے، اور پرانا آلہ نامعلوم کال پھینک دیتا ہے یا خاموشی سے نظرانداز کرتا ہے۔ 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 اسٹیک ہے، اور یہ اسپلٹ ٹنل کی خرابی نہیں بلکہ ڈیزائن کا فیصلہ ہے۔

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