Android VPN: VpnService ڈسکرپٹر بنام root tun ڈیوائس
Android ایپس خود tun0 نہیں بنا سکتیں: establish() کیا لوٹاتا ہے، Binder کہاں رکتا ہے اور JNI کہاں شروع ہوتا ہے، اور root سے بنا ڈیوائس کب جیتتا ہے۔
دو راستے ایک Android ایپ کے سامنے IP انٹرفیس رکھ سکتے ہیں، اور دونوں ایک ہی قسم کے فائل ڈسکرپٹر پر ختم ہوتے ہیں جن کے مالک بہت مختلف ہیں۔ ایک VpnService اور اس کے builder سے گزرتا ہے، دوسرا root shell اور /dev/net/tun سے۔ اس ڈسکرپٹر پر ہر پڑھائی باہر جانے والا پیکٹ ہے اور ہر لکھائی اندر آنے والا۔ راستوں کو الگ کرنے والی بات یہ ہے کہ پالیسی کس کے پاس ہے، OS اپ گریڈ کون برداشت کرتا ہے، اور روٹنگ ٹیبل میں سے کتنا آپ چھو سکتے ہیں۔
پلیٹ فارم کا راستہ اختیار کریں جب تک آپ اس مخصوص چیز کا نام نہ بتا سکیں جس سے یہ انکار کرتا ہے۔ وہ انکار عام طور پر TAP، آپ کے اپنے ایپ سیٹ سے باہر کیپچر، یا کوئی روٹنگ اصول ہوتا ہے جسے فریم ورک کبھی ظاہر نہیں کرتا۔
پلیٹ فارم کے راستے پر آپ حکموں کی بجائے نیت کا اعلان کرتے ہیں۔ آپ کم از کم ایک پتہ، مطلوبہ روٹس، DNS سرورز اور اختیاری ایپ فہرست دیتے ہیں، پھر Android کی سسٹم سروس اپنی شناخت کے تحت مراعات یافتہ سیٹ اپ کرتی ہے۔ آپ انٹرفیس کا نام پہلے سے کبھی نہیں جانتے، اور اسے بنانے والا ioctl کبھی جاری نہیں کرتے، اور یہی اصل بات ہے۔
IP انٹرفیس حاصل کرنے کے دو طریقے
root راستہ پرانی ترکیب ہے۔ آپ /dev/net/tun کھولتے ہیں، IFF_TUN کے ساتھ TUNSETIFF کال کرتے ہیں، ip link سے انٹرفیس اوپر اٹھاتے ہیں، اور پتے اور روٹس ہاتھ سے شامل کرتے ہیں۔ ہر قدم آپ کو صحیح کرنا ہے، وہ بھی جو فریم ورک خاموشی سے نمٹا دیتا۔ ایک روٹ رہ جائے تو صارف کو مردہ سرور جیسی ہی رپورٹ ملتی ہے۔
ڈی بگنگ اتنی ہی مختلف ہے جتنی سیٹ اپ۔ root راستے پر انٹرفیس یا موجود ہے یا آپ کے ioctl نے ایسی غلطی لوٹائی ہے جسے آپ براہ راست پڑھ سکتے ہیں۔ پلیٹ فارم کے راستے پر انٹرفیس establish() کے کامیاب ہونے کے بعد ہی موجود ہوتا ہے، اس لیے ناکامی ڈیوائس نوڈ کی بجائے استثنا یا null ڈسکرپٹر کے طور پر آتی ہے جسے آپ کرید سکیں۔
establish() واقعی کیا لوٹاتا ہے
Builder.establish() کے تین نتائج ہیں اور انہیں تین مختلف جواب چاہیے۔ ڈسکرپٹر کا مطلب ہے کہ انٹرفیس کنفیگر ہے اور استعمال کے لیے آپ کا ہے، null کا مطلب ہے کہ درخواست گزر نہیں سکی، اور پھینکا گیا استثنا کا مطلب ہے کہ سسٹم سروس نے اسے مسترد کیا۔ null اور کامیابی کو ایک boolean میں ملانا کسی ایپ کا چلتی ہوئی سرنگ بتانے کا سب سے عام طریقہ ہے جو کبھی پیکٹ نہیں ڈھوتی۔ Builder حوالہ پتے کی شرط بتاتا ہے، اور سرور کو قصوروار ٹھہرانے سے پہلے اسے پڑھنا مناسب ہے۔
سمتیں ڈسکرپٹر طے کرتا ہے، آپ کا پروٹوکول نہیں۔ پڑھائی آپ کو باہر جاتے پیکٹ دیتی ہے جو پہلے سے VPN کے لیے چنے گئے ہیں، اور لکھائی اندر آنے والے پیکٹ واپس انٹرفیس میں ڈالتی ہے۔ ان پیکٹوں کو انکرپٹ، تصدیق اور فریم کرنا آپ کی اپنی ٹرانسپورٹ کا کام ہے، کیونکہ پلیٹ فارم پیکٹ کی حد پر رک جاتا ہے۔
Binder ایک قدم ہے، JNI دوسرا محور
builder کی درخواست Binder کے ذریعے سسٹم میں داخل ہوتی ہے، اور اس کے نیچے کہیں پلیٹ فارم ڈیوائس کنفیگر کرنے کے لیے نیٹو کوڈ بلاتا ہے۔ یہ ایک ہی کال میں تہہ شدہ دو مختلف میکانزم ہیں۔ Binder آپ کی ایپ اور سسٹم سروس کے درمیان بین العمل تواصل ہے، جبکہ JNI عمل کے اندر Java سے نیٹو تک پل ہے۔ Android 9 AOSP درخت پڑھنے سے اسٹیک لفظی دکھتا ہے، اور یاد رکھنا چاہیے کہ اندرونی کلاس نام اور فائل راستے ریلیز کے درمیان بدلتے ہیں۔
جو نہیں بدلتا وہ معاہدہ ہے جس پر آپ بھروسہ کر سکتے ہیں: builder، وہ ڈسکرپٹر جو وہ لوٹاتا ہے، اور اس کے گرد سروس کا زندگی چکر۔ کوئی ایپ انٹرفیس حاصل کرنے کے لیے اندرونی سروس لین دین نہ بلائے اور نہ ڈیوائس نوڈ دوبارہ بنائے۔ اگر آپ کا کوڈ AOSP کلاس نام پر منحصر ہے، تو وہ اس ریلیز پر ٹوٹے گا جسے آپ نے آزمایا نہیں۔
TUN IP ڈھوتا ہے، TAP Ethernet
TUN ایک IP انٹرفیس ہے۔ TAP ایک Ethernet انٹرفیس ہے، اور یہی فرق طے کرتا ہے کہ بریجنگ ممکن ہے بھی یا نہیں۔ TUN ڈیوائس کے پاس MAC پتہ نہیں اور آگے بھیجنے کے لیے Ethernet ہیڈر نہیں، اس لیے TUN کلائنٹ روٹس جیسے بھی لکھے ہوں layer-2 بریج میں شامل نہیں ہو سکتا۔
VpnService آپ کو IP قسم دیتا ہے، جو ایپ سطح VPN کو درکار ہے اور جسے وہ خام Ethernet اسٹیک کے بغیر سنبھال سکتا ہے۔ اگر آپ کے ڈیزائن کو بریجنگ چاہیے، تو پلیٹ فارم کا راستہ آپ کو وہاں نہیں لے جائے گا، اور root راستہ تب ہی لے جائے گا جب کرنل اور ڈیوائس کی اجازتیں تعاون کریں۔
root راستہ اب بھی کہاں جیتتا ہے
تین کام لوگوں کو پلیٹ فارم کے راستے سے دور دھکیلتے ہیں۔ layer-2 بریجنگ کو TAP چاہیے۔ آپ کے VPN دائرے سے باہر ایپس کا ٹریفک پکڑنے کے لیے ایسی نظر چاہیے جو فریم ورک نہیں دیتا۔ builder کبھی ظاہر نہ کرنے والی پالیسی روٹنگ، مثلاً ایک منزل کے لیے الگ ٹیبل، وہ اصول مانگتی ہے جو آپ خود نصب کریں۔
اخراجات بعد میں آتے ہیں: کھلا bootloader یا root شدہ امیج، آپ کے قدموں تلے سرکنے والی SELinux پالیسی، اور OTA کے بعد درست برتاؤ چھوڑ دینے والا ڈیوائس۔ root شدہ ترکیب عام ایپ تقسیم سے بھی نہیں بھیجی جا سکتی، اس لیے زیادہ تر ٹیمیں اسے مصنوع کے بجائے داخلی تشخیصی راستہ رکھتی ہیں۔
دونوں میں سے انتخاب
آپ کے پاس موجود کوڈ سے نہیں، آپ کو درکار انٹرفیس سے شروع کریں۔ جواب ایپ محدود روٹس والا TUN ڈیوائس ہو تو پلیٹ فارم کا راستہ چھوٹا ہے اور اپ گریڈ برداشت کرتا ہے۔ جواب میں Ethernet فریم، دوسری ایپس کی کیپچر، یا builder کے مسترد کردہ روٹنگ اصول شامل ہوں تو آپ root علاقے میں ہیں اور اسے آپریشنل خرچ کے طور پر بجٹ کرنا چاہیے۔
زیادہ تر بحثیں طے کرنے والی ایک جانچ: پہلے پلیٹ فارم کا راستہ بنائیں، establish() کا نتیجہ دور دراز سیشن کی حالت سے الگ ریکارڈ کریں، اور ہر سمت میں ایک پیکٹ کی تصدیق کریں۔ اسی کے بعد طے کریں کہ گمشدہ صلاحیت معاون راستہ چھوڑنے کا جواز بنتی ہے یا نہیں۔