Docker VPN کنٹینر کے ذریعے میزبان ٹریفک کو کیسے روٹ کریں
VPN کنٹینر نیٹ ورک نیم اسپیس ہے، پراکسی نہیں۔ مشترکہ netns، حقیقی SOCKS سننے والا یا روٹ شدہ گیٹ وے منتخب کریں، پھر اخراج کا راستہ جانچیں۔
آپ کا ٹنل کنٹینر کام کر رہا ہے، docker compose exec vpn curl -s https://ifconfig.me فراہم کنندہ کے پتے کے ساتھ جواب دیتا ہے، پھر بھی آپ کے ڈیسک ٹاپ کا براؤزر آپ کے ISP سے ہی باہر جاتا ہے۔ یہ فرق متوقع ہے۔ VPN کلائنٹ چلانے والا کنٹینر نیٹ ورک نیم اسپیس، راستے اور ٹنل انٹرفیس رکھتا ہے، اور ایسی کوئی چیز نہیں جو HTTP یا SOCKS بولے؛ اس پر پورٹ شائع کرنا ایسا سننے والا نہیں بنا سکتا جو کبھی تھا ہی نہیں۔
کلائنٹ کہاں چلتا ہے یہ ڈیزائن طے کرتا ہے۔ پڑوسی کنٹینر ٹنل کے نیم اسپیس میں جا سکتا ہے، ڈیسک ٹاپ ایپلی کیشن نہیں جا سکتی، اور راؤٹر کو پراکسی فیلڈ نہیں راستے چاہیے۔ نقشہ غلط ہوا تو علامت وہی ہے: کنکشن مسترد، یا چپکے سے پرانے راستے پر جانے والی ٹریفک۔
ترتیب کو کلائنٹ کے چلنے کی جگہ سے ہم آہنگ کریں
Compose میں ترمیم سے پہلے ایک سوال پوچھیں: کیا کلائنٹ کو VPN کنٹینر کے نیٹ ورک نیم اسپیس کے اندر شروع کیا جا سکتا ہے؟ جو پہلے سے Linux کنٹینر کے طور پر چل رہا ہے وہ کر سکتا ہے۔ آپ کی میز پر موجود براؤزر، IDE یا CLI نہیں کر سکتا، کیونکہ اس کی پراکسی سیٹنگ پروٹوکول سروس کی توقع کرتی ہے، نیم اسپیس کی نہیں۔
| Client | Arrangement | What must already exist |
|---|---|---|
| Another Compose service | Shares the vpn namespace via network_mode: service:vpn | A working tunnel and correct start order |
| Host browser, IDE or CLI | Proxy listener inside the namespace, published to host loopback | A configured SOCKS or HTTP proxy and its access rules |
| Router, VM or phone | The container as a layer-3 gateway | Forwarding, NAT and a return route |
یہ تینوں ملتے نہیں۔ کنٹینر کے برج پتے کی طرف اشارہ کرنے والی HTTP پراکسی فیلڈ وہاں پراکسی نہ سنے تو کہیں نہیں پہنچتی، اور پراکسی سننے والا راؤٹر کی ٹریفک روٹ نہیں کرتا۔ پہلے فیصلہ کریں، پھر مناسب حصے کی پیروی کریں۔
ٹنل نیم اسپیس پڑوسی کنٹینر کے ساتھ شیئر کریں
یہ سب سے سستا آپشن ہے کیونکہ اس میں کوئی پراکسی پروٹوکول شامل نہیں۔ ایپ vpn سروس کے نیم اسپیس میں شامل ہوتی ہے اور اس کے انٹرفیس، راستے اور پورٹ کی جگہ ورثے میں پاتی ہے:
services:
vpn:
image: your-vpn-client
cap_add:
- NET_ADMIN
healthcheck:
test: ["CMD-SHELL", "ip link show tun0 >/dev/null"]
interval: 10s
retries: 5
app:
image: your-app
network_mode: service:vpn
depends_on:
vpn:
condition: service_healthyنیم اسپیس کسی دوسری سروس کا ہونے سے تین پابندیاں آتی ہیں۔ ایپ کو اپنی networks کلید نہیں ملتی، کیونکہ جڑنے کے لیے اس کے پاس نیم اسپیس نہیں۔ پورٹ کی اشاعت vpn پر ہے، کیونکہ نیم اسپیس وہیں رہتا ہے۔ اور vpn کو دوبارہ بنانا اس نیم اسپیس کو تباہ کرتا ہے جس میں ایپ شامل ہوئی تھی، اس لیے docker compose up -d --force-recreate vpn آپ کو app بھی دوبارہ بنانے دیتا ہے؛ سادہ ری اسٹارٹ ہمیشہ کافی نہیں ہوتا۔ Compose سروس حوالہ اس ترتیب اور اس کی پورٹ اشاعت کی پابندی کا احاطہ کرتا ہے۔
یہ مت سمجھیں کہ حل کرنے والا ساتھ آتا ہے۔ /etc/resolv.conf ہر کنٹینر کی فائل ہے، نیٹ ورک نیم اسپیس کا حصہ نہیں، اس لیے ایپ کے پیکٹ ٹنل سے باہر جاتے ہوئے بھی وہ میزبان کے حل کرنے والے سے پوچھ سکتی ہے۔ اسے کنٹینر کے اندر سے پڑھیں اور جب نجی نام ٹنل سے حل کرنے ہوں تو ایپ پر dns: مقرر کریں۔
docker compose exec app ip route
docker compose exec app cat /etc/resolv.conf
docker compose exec app curl -s https://ifconfig.meاگر راستوں کی فہرست میں ٹنل انٹرفیس ہے اور پتہ فراہم کنندہ کا ہے، تو ایپ ٹنل کے اندر ہے۔ اگر انٹرفیس نہیں ہے، تو vpn کے پاس ٹنل آنے سے پہلے app شروع ہو چکی تھی، اس لیے vpn کے صحت مند ہونے کی اطلاع پر app دوبارہ بنائیں۔
میزبان کلائنٹس کے لیے نیم اسپیس میں حقیقی پراکسی سننے والا رکھیں
ڈیسک ٹاپ براؤزر نیم اسپیس میں شامل نہیں ہو سکتا، اس لیے ٹنل کو سروس کے طور پر کھولنا پڑے گا۔ vpn نیم اسپیس کے اندر حقیقی SOCKS یا HTTP پراکسی چلائیں اور صرف اس کا پورٹ شائع کریں:
services:
vpn:
ports:
- "127.0.0.1:1080:1080"
proxy:
image: your-proxy
network_mode: service:vpn
command: ["--socks", "0.0.0.0:1080"]میزبان کی طرف کا پتہ اس نقشے کا اہم نصف ہے۔ بائیں طرف کا 127.0.0.1:1080 سننے والے کو آپ کے LAN سے باہر رکھتا ہے؛ ننگا "1080:1080" آپ کی مشین تک پہنچ سکنے والے ہر آلے کے لیے کھلی پراکسی شائع کرتا ہے۔
کنٹینر کی طرف کا اپنا جال ہے۔ شائع شدہ پورٹ کنٹینر کے برج پتے پر پہنچائے جاتے ہیں، اس کے loopback پر نہیں، اس لیے نیم اسپیس کے اندر --socks 127.0.0.1:1080 سے شروع کی گئی پراکسی پڑوسیوں کے کنکشن قبول کرتی ہے اور شائع شدہ پورٹ سے آنے والا سب کچھ مسترد کرتی ہے۔ اسے 0.0.0.0 سے باندھیں اور تنہائی کے لیے میزبان کی طرف کے loopback بندھن پر بھروسہ کریں۔ یہی قاعدہ پراکسی کنفگ فائل میں سننے کے پتے پر بھی لاگو ہوتا ہے۔
پھر طے کریں کہ نام کہاں حل ہوتے ہیں۔ curl میں --socks5 میزبان نام مقامی طور پر حل کرتا ہے اور --socks5-hostname نام پراکسی کو بھیجتا ہے؛ براؤزر وہی سوئچ دوسرے لیبل کے تحت دکھاتے ہیں۔ مقامی حل صفحہ کے ٹنل سے لوڈ ہونے پر بھی استفسار لیک کرتا ہے۔
کنٹینر کو گیٹ وے صرف واپسی کے راستے کے ساتھ سمجھیں
راؤٹر، VM اور فون HTTP پراکسی فیلڈ استعمال نہیں کریں گے، اور کچھ ایپلی کیشنز پراکسی متغیرات کو مکمل نظرانداز کرتی ہیں۔ ان کی ٹریفک روٹ کرنے کا مطلب لیئر 3 ہے: کنٹینر پیکٹ آگے بھیجتا ہے اور ٹنل انٹرفیس پر پتے ترجمہ کرتا ہے۔
sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADEدو چیزیں آسانی سے رہ جاتی ہیں۔ کلائنٹ کو ایسا راستہ چاہیے جو اس کے ڈیفالٹ گیٹ وے کو اس میزبان کی طرف بھیجے، اور جوابات کو واپسی کا راستہ ملنا چاہیے، یا اوپر والے راؤٹر پر مستقل راستے سے یا کلائنٹ کی طرف والے انٹرفیس پر NAT سے۔ ان میں سے ایک بھی نہ ہو تو ٹنل درخواست باہر لے جاتا ہے اور جواب غائب ہو جاتا ہے۔
اس کا اثر دائرہ بھی سب سے وسیع ہے۔ پورے LAN کے لیے گیٹ وے بنے میزبان ہر غلط ترتیب شدہ کلائنٹ کو آپ کے VPN اکاؤنٹ سے بھیجتا ہے، اور ٹنل گرنے پر kill switch کے مطابق یا تو LAN اندھیرے میں چلا جاتا ہے یا ISP پر واپس گرتا ہے۔
اخراج کا راستہ جانچیں، پھر ترتیب سے واپس پلٹیں
اسی ترتیب میں جانچیں اور پہلی ناکامی پر رکیں: نیم اسپیس کے اندر اخراج کا پتہ، میزبان سے پراکسی کے ذریعے اخراج کا پتہ، پھر نجی میزبان کے لیے نام کا حل۔
docker compose exec vpn curl -s https://ifconfig.me
curl -s -x socks5h://127.0.0.1:1080 https://ifconfig.me
curl -s -x socks5h://127.0.0.1:1080 http://internal.example/healthپہلے دو پتے فراہم کنندہ سے میل کھانے چاہئیں، اور تیسرا نام کی غلطی سے ناکام ہونے کے بجائے پراکسی سے حل ہونا چاہیے۔ پہلی سطر کا میل کھانا اور دوسری کا ناکام ہونا بتاتا ہے کہ سننے والا یا شائع شدہ پورٹ غلط ہے، ٹنل نہیں۔
واپس پلٹنا سیٹ اپ کا الٹ ہے۔ پراکسی ماحول متغیرات کو shell پروفائل اور کسی بھی systemd یونٹ سے ہٹائیں، پھر اسٹیک نیچے اتاریں تاکہ مشترکہ نیم اسپیس اپنے مالک کے ساتھ غائب ہو جائے۔ پراکسی سروس ہٹانے سے پہلے شائع شدہ پورٹ ہٹائیں، ورنہ میزبان پر ایسا loopback سننے والا رہ جاتا ہے جسے کوئی نہیں پڑھتا۔
آگے بڑھنے سے پہلے چار باتیں یقینی بنائیں: جس کلائنٹ کی آپ کو فکر ہے وہ واقعی ٹنل تک پہنچتا ہے، پورٹ صرف نیم اسپیس کا مالک شائع کرتا ہے، نجی نام وہیں حل ہوتے ہیں جہاں آپ نے چاہا تھا، اور loopback نہ ہونے والے میزبان پتے پر کچھ نہیں سنتا۔ ان میں سے ہر ایک پیداوار میں خاموشی سے ناکام ہوتا ہے، اور ہر ایک اوپر دی گئی ایک سطری جانچ ہے۔