UID قواعد کے ساتھ ایک Linux ایپ کو VPN سے جوڑنا
UID قاعدہ صرف مقامی ساکٹ دیکھتا ہے، اور معمول کی loopback استثنا سرنگ کو مار دیتی ہے۔ پہلے اکاؤنٹ کو راستہ دیں، پھر ہر مرحلے کو فلٹر اور جانچیں۔
لینکس پر ایک پروگرام کو VPN سے جوڑنا بنیادی طور پر روٹنگ کا مسئلہ ہے، اور فائر وال قاعدہ صرف یہ طے کرتا ہے کہ راستہ منتخب ہونے کے بعد کیا ہوتا ہے۔ اگر آپ سرنگ کے پاس ڈیفالٹ راستہ آنے سے پہلے OUTPUT میں پروگرام کا UID ملائیں، تو قاعدہ وہی ٹریفک گرا دیتا ہے جسے آپ بچانا چاہتے تھے۔ یہی قاعدہ پروگرام کے DNS سوالات کا جواب دینے والے resolver عمل کو بھی نہیں دیکھتا۔ ترتیب درست کریں، اور ایک بغیر استحقاق اکاؤنٹ قابلِ بھروسا منقسم سرنگ چننے والا بن جاتا ہے۔
فیصلے سے پہلے اکاؤنٹ کو راستہ دیں
مالک کی مطابقت ایک سوال کا جواب دیتی ہے: کیا اس UID سے تعلق رکھنے والے مقامی ساکٹ نے پیکٹ بنایا؟ یہ انٹرفیس نہیں چنتا، اور مرکزی جدول جو ٹریفک پہلے ہی طبعی NIC سے بھیج رہا ہے اسے ہلا نہیں سکتا۔ اسی لیے مطابق راستے کے بغیر UID قاعدہ پروگرام کو موڑنے کے بجائے روکتا ہے۔
اکاؤنٹ کو پہلے اس کی اپنی جدول سے گزاریں، پھر فائر وال کو نتیجہ تصدیق کرنے دیں۔ یہ ایسے ہوسٹ پر کام کرتا ہے جس کا iproute2 uidrange سمجھتا ہے، جسے ip rule help ایک سطر میں بتاتا ہے۔ جدول 100 سرنگ کے ذریعے ڈیفالٹ راستہ رکھتا ہے، اور قاعدہ صرف UID 1000 کو اس جدول میں بھیجتا ہے۔ باقی سب مرکزی جدول پر رہتا ہے اور طبعی رابطہ استعمال کرتا رہتا ہے۔
ip rule add uidrange 1000-1000 table 100 ip route add default dev tun0 table 100
دوسری سرنگ درکار دوسرے اکاؤنٹ کو جدول 101 اور اپنا قاعدہ ملتا ہے، کیونکہ دو پروفائل ایک ہی جدول میں ڈیفالٹ راستے کے مالک بیک وقت نہیں ہو سکتے۔ NetworkManager پروفائل نظام گیر ہیں، اس لیے یہ حصہ ہاتھ سے ہی رہتا ہے، اور ری بوٹ پر قواعد مٹ جاتے ہیں جب تک کوئی انہیں بحال نہ کرے۔ جدولوں کو سرنگ کی تعریف کے ساتھ بوٹ اسکرپٹ میں لکھیں، تاکہ دوبارہ جڑنا کسی اکاؤنٹ کو غلط راستے پر نہ چھوڑے۔
loopback استثنا سرنگ کو کیوں مار دیتی ہے
قاعدے کی زیادہ تر نقل شدہ شکلیں ہر اس پیکٹ کو گرا دیتی ہیں جو loopback سے باہر نہ جائے۔ سرنگ loopback نہیں ہے، اس لیے وہ شکل سرنگ کی ٹریفک بھی گرا دیتی ہے، اور نتیجہ فائر وال کی غلطی کے بجائے مردہ VPN جیسا لگتا ہے۔
جب OUTPUT چلتا ہے تو کرنل پہلے ہی اخراجی انٹرفیس چن چکا ہوتا ہے، اس لیے -o پیکٹ ہیڈر کے بجائے راستے کے جواب سے موازنہ کیا جاتا ہے۔ مالک کی مطابقت صرف OUTPUT اور POSTROUTING میں دیکھی جاتی ہے، اور آگے بھیجے گئے پیکٹوں میں ایسا ساکٹ نہیں ہوتا جسے یہ پڑھ سکے۔ اس امتزاج کا مطلب ہے کہ استثنا کو سرنگ کا انٹرفیس نام دینا ہوگا اور اس مطابقت کی نفی کرنی ہوگی، نہ کہ loopback کی نفی۔
loopback اب بھی DROP کے اوپر اپنا ACCEPT مستحق ہے، کیونکہ پروگرام کا پہلا DNS پیکٹ lo کے ذریعے مقامی stub تک جاتا ہے۔ دونوں قواعد اسی ترتیب میں رکھیں، اور اکاؤنٹ stub تک پہنچتا ہے، پھر سرنگ تک، اور کہیں اور نہیں۔
iptables -I OUTPUT 1 -o lo -m owner --uid-owner vpnapp -j ACCEPT iptables -A OUTPUT -m owner --uid-owner vpnapp ! -o tun0 -j DROP
IPv6 الگ قواعد کا مجموعہ ہے، اور صرف v4 کے لیے بنایا جوڑا ip6tables کو اچھوتا چھوڑ دیتا ہے۔ AAAA ریکارڈز کو ترجیح دینے والا پروگرام پھر DROP تک کبھی پہنچے بغیر طبعی رابطے سے باہر چلا جائے گا۔ دونوں قواعد ip6tables میں جھلکائیں، یا جب سرنگ کوئی v6 پتہ نہ لے جائے تو ہوسٹ پر IPv6 بند کریں۔ ہاتھ سے شامل کیے گئے قواعد بھی ری بوٹ پر مٹ جاتے ہیں، اس لیے انہیں netfilter-persistent save سے محفوظ کریں یا وہی منطق بوٹ یونٹ کے لوڈ کردہ nftables جدول کے طور پر دوبارہ بنائیں۔
DNS جوابات دوسرے عمل سے آتے ہیں
پروگرام کی 127.0.0.53 کی طرف درخواست loopback ACCEPT سے گزرتی ہے، اور وہیں UID مطابقت رک جاتی ہے۔ stub resolver اپنے سروس اکاؤنٹ سے اوپر بھیجتا ہے، اس لیے vpnapp سے جڑا قاعدہ دوسری درخواست کبھی نہیں دیکھتا۔ اگر resolver رابطے کے لیے LAN سرور چنے تو جوابات طبعی NIC سے واپس آتے ہیں جبکہ پروگرام کے اپنے پیکٹ سرنگ میں رہتے ہیں۔ نظر آنے والا نتیجہ ٹوٹے ناموں والی چلتی سرنگ ہے، یا ایسے نام جن کا جواب آپ نے نہ چنا ہو ایسا سرور دیتا ہے۔
ناموں کا حل سرنگ کے رابطے پر درست کریں، ایپ پر نہیں۔ سرنگ پروفائل کو DNS سرور اور روٹنگ ڈومین دیں، پھر resolvectl query اور resolvectl status tun0 سے تصدیق کریں کہ resolver اہم ناموں کے لیے اسے استعمال کرتا ہے۔ نیٹ ورک نام کی جگہ کے اندر مسئلہ غائب ہو جاتا ہے، کیونکہ جگہ کا resolver صرف سرنگ جانتا ہے۔
قاعدہ خود اکاؤنٹ سے جانچیں
کرنل سے پوچھیں کہ UID کو کون سا راستہ ملتا ہے، پھر اس اکاؤنٹ کے طور پر درخواست کریں اور اخراجی پتہ اپنے اکاؤنٹ کے پتے سے موازنہ کریں۔ اگر دونوں ایک ہی پتہ بتائیں تو قاعدہ آپ کے جانچے گئے ٹریفک کے علاوہ کسی اور چیز سے میل کھاتا ہے۔ نیچے پہلا حکم پیکٹ بھیجے بغیر راستے کی تلاش دکھاتا ہے، جو روٹنگ کی غلطی کو فائر وال کی غلطی سے الگ کرتا ہے۔
ip route get 1.1.1.1 uid 1000 sudo -u vpnapp curl -s https://ifconfig.co
کاؤنٹر دکھاتے ہیں کہ قاعدہ کبھی چلا یا نہیں۔ iptables -vnL OUTPUT چلائیں، ہر قاعدے کے پاس پیکٹ گنتی پڑھیں، اور حقیقی ٹریفک کے بعد DROP کے پاس صفر کو مطابقت کی غلطی مانیں۔
آگے بھیجی گئی ٹریفک اس ڈیزائن سے باہر ہے۔ پل کے پیچھے کنٹینر یا VM کے پاس vpnapp کی ملکیت والا مقامی ساکٹ نہیں ہوتا، اس لیے مالک کی مطابقت کبھی نہیں چلتی اور وہ پیکٹ FORWARD پالیسی پر چلتے ہیں۔ اگر وہ بوجھ ڈھانپنا ہو تو اسے الگ جانچیں اور پل یا کنٹینر کے پتے سے جڑی پالیسی لکھیں۔ ڈیزائن تب ٹکتا ہے جب جدول، انٹرفیس استثنا، resolver اور v6 قواعد سب ایک ہی سمت اشارہ کریں؛ ان میں سے کوئی ایک چھوڑ دیں اور اکاؤنٹ یا لیک ہوتا ہے یا کنیکٹیویٹی کھو دیتا ہے۔