Docker میں wg-easy سے WireGuard ویب UI چلائیں
Docker Compose میں wg-easy کے ساتھ WireGuard چلائیں: ports، NET_ADMIN، ضروری sysctls اور فونز کے لیے QR code onboarding کی مکمل ترتیب جانیں۔
آپ کیا بنا رہے ہیں
wg-easy ایک ویب انٹرفیس کے ساتھ WireGuard ہے، جو ایک Docker container کے طور پر چلتا ہے۔ یہ آپ کے لیے WireGuard interface کا انتظام کرتا ہے اور clients بنانے کے لیے browser UI فراہم کرتا ہے۔ آپ کے بنائے ہوئے ہر client کو ایک config file اور QR code ملتا ہے، اس لیے فون screen کی طرف camera کر کے VPN سے منسلک ہو جاتا ہے۔
Tunnel خود عام WireGuard ہے۔ kernel module packets منتقل کرتا ہے، اس لیے throughput دستی طور پر بنائے گئے setup جیسا ہی رہتا ہے۔ آپ کو client lifecycle کا انتظام ملتا ہے: SSH کے ذریعے config file میں ترمیم کیے بغیر peers شامل کرنا، غیر فعال کرنا اور حذف کرنا۔ اس کے بدلے آپ config پر براہ راست control چھوڑ دیتے ہیں۔ اس موضوع کے لیے VPS پر دستی WireGuard setup دیکھیں۔
آپ کو public IPv4 address والا KVM VPS، Compose plugin کے ساتھ Docker Engine، اور root access درکار ہے۔ ایسی container virtualisation جو host kernel کا اشتراک کرتی ہے، جیسے OpenVZ یا LXC، عموماً WireGuard module لوڈ نہیں کر سکتی۔ اس کے نتیجے میں container interface شروع کرنے میں ناکام ہو جاتا ہے۔
Version 15 نے ترتیبات کو environment سے منتقل کر دیا
آپ کو ملنے والی زیادہ تر رہنما دستاویزات wg-easy 14 کے لیے لکھی گئی تھیں۔ ان میں WG_HOST کو اپنے server address پر اور PASSWORD_HASH کو administrator password کے bcrypt hash پر set کیا جاتا تھا، اور دونوں کو environment variables کے طور پر استعمال کیا جاتا تھا۔ Version 15 ایک ازسرنو تحریر ہے۔ سرکاری migration notes میں واضح طور پر بتایا گیا ہے کہ v15، v14 والے environment variables استعمال نہیں کرتا، اور ان میں سے زیادہ تر ترتیبات web UI کے admin panel میں منتقل کر دی گئی ہیں۔
اس لیے WG_HOST اور PASSWORD_HASH اب کوئی اثر نہیں ڈالتے۔ اگر آپ پرانی compose file copy کریں، تو container start ہو جاتا ہے، ان سطروں کو نظرانداز کرتا ہے، اور پھر browser میں admin account بنانے کا مطالبہ کرتا ہے۔ یہ کوئی bug نہیں ہے۔ یہی نیا setup flow ہے۔
July 2026 تک pin کرنے کے لیے major tag 15 ہے۔ latest استعمال کرنے کے بجائے major version pin کریں، کیونکہ major upgrade disk پر موجود config format تبدیل کرتا ہے اور صاف طور پر rollback نہیں ہوتا۔
Compose فائل
stack کے لیے ایک directory بنائیں اور اس میں official compose فائل لکھیں۔ یہ upstream فائل ہے اور اس میں کوئی تبدیلی نہیں کی گئی۔
sudo mkdir -p /etc/docker/containers/wg-easy
sudo curl -o /etc/docker/containers/wg-easy/docker-compose.yml \
https://raw.githubusercontent.com/wg-easy/wg-easy/master/docker-compose.ymlاس کے contents اس طرح نظر آتے ہیں:
volumes:
etc_wireguard:
services:
wg-easy:
image: ghcr.io/wg-easy/wg-easy:15
container_name: wg-easy
networks:
wg:
ipv4_address: 10.42.42.42
ipv6_address: fdcc:ad94:bacf:61a3::2a
volumes:
- etc_wireguard:/etc/wireguard
- /lib/modules:/lib/modules:ro
ports:
- "51820:51820/udp"
- "51821:51821/tcp"
restart: unless-stopped
cap_add:
- NET_ADMIN
- SYS_MODULE
sysctls:
- net.ipv4.ip_forward=1
- net.ipv4.conf.all.src_valid_mark=1
- net.ipv6.conf.all.disable_ipv6=0
- net.ipv6.conf.all.forwarding=1
- net.ipv6.conf.default.forwarding=1
networks:
wg:
driver: bridge
enable_ipv6: true
ipam:
driver: default
config:
- subnet: 10.42.42.0/24
- subnet: fdcc:ad94:bacf:61a3::/64etc_wireguard ایک named volume ہے جس میں server key اور آپ کے بنائے گئے تمام clients محفوظ ہوتے ہیں۔ اس volume کا backup لیں، ورنہ rebuild کے بعد تمام peers ضائع ہو جائیں گے۔ اگر آپ ان files کو host filesystem پر دیکھنا چاہتے ہیں تو اسے bind mount سے تبدیل کریں، اور ایسا کرنے سے پہلے bind mounts اور named volumes کے درمیان فرق پڑھیں، کیونکہ permissions مختلف طریقے سے لاگو ہوتی ہیں۔
اسے NET_ADMIN، SYS_MODULE اور sysctls کی ضرورت کیوں ہے
کنٹینر کو بطور ڈیفالٹ نیٹ ورک stack کو تبدیل کرنے کی اجازت نہیں ہوتی، اور ان میں سے ہر لائن ایک مخصوص رکاوٹ دور کرتی ہے۔
NET_ADMIN کنٹینر کو wg0 interface بنانے، اسے address تفویض کرنے اور routes لکھنے کی اجازت دیتا ہے۔ اس کے بغیر کنٹینر شروع ہونے کے بعد interface کو فعال کرتے وقت بند ہو جاتا ہے، کیونکہ ip link add wg0 type wireguard، Operation not permitted واپس کرتا ہے۔
SYS_MODULE اور read-only /lib/modules mount مل کر کنٹینر کو WireGuard kernel module لوڈ کرنے دیتے ہیں، اگر host نے اسے پہلے سے لوڈ نہ کیا ہو۔ یہ module image کے اندر نہیں بلکہ host kernel میں موجود ہوتا ہے، اسی لیے host directory کو visible بنانا ضروری ہے۔ جدید kernel میں یہ module عموماً built in ہوتا ہے، اور آپ host پر sudo modprobe wireguard && echo ok کے ذریعے اس کی تصدیق کر سکتے ہیں۔
net.ipv4.ip_forward=1 kernel کو ایسے packets forward کرنے دیتا ہے جن کا address خود اس box کا نہیں ہوتا۔ اس کے بغیر client connect ہو جاتا ہے، handshake کامیاب ہو جاتا ہے، لیکن internet کے لیے ہر packet drop ہو جاتا ہے، اس لیے VPN connected دکھائی دینے کے باوجود ping 1.1.1.1 timeout ہو جاتا ہے۔
net.ipv4.conf.all.src_valid_mark=1 وہ setting ہے جو لوگوں کو حیران کرتی ہے۔ WireGuard اپنے outgoing packets کو mark کرتا ہے تاکہ وہ واپس tunnel میں route نہ ہوں۔ Strict reverse path filtering ایسے packet کو دیکھ کر drop کر دیتی ہے جس کا source address متوقع route سے مطابقت نہیں رکھتا۔ یہ sysctl kernel کو marked packets قبول کرنے کی ہدایت دیتا ہے، اور اسی سے full tunnel خود اپنے traffic کو متاثر کرنے سے محفوظ رہتا ہے۔
اسے شروع کریں اور ایڈمن اکاؤنٹ بنائیں
cd /etc/docker/containers/wg-easy
sudo docker compose up -d
sudo docker compose logs -fdocker compose up اور docker compose down استعمال کریں، start اور stop نہیں۔ Upstream خبردار کرتا ہے کہ مختلف settings کے تحت بنائے گئے container پر start چلانے سے network غیر مستقل حالت میں رہ جاتا ہے۔ اگر آپ reboot کے بعد stack کو دوبارہ چلانا چاہتے ہیں تو restart: unless-stopped پہلے ہی اس کا انتظام کرتا ہے، اور compose services کے boot behaviour میں بتایا گیا ہے کہ یہ policy کیا کرتی ہے اور کیا ضمانت نہیں دیتی۔
Web UI TCP 51821 پر listening کرتی ہے۔ پہلی بار کھولنے پر یہ setup page دکھاتی ہے، جہاں آپ admin account بناتے ہیں اور اس host address کی تصدیق کرتے ہیں جس کے ذریعے clients server تک پہنچیں گے۔ یہ host address ہر client config کی Endpoint line میں شامل ہو جاتا ہے، اس لیے یہ VPS کا public IP یا DNS name ہونا چاہیے۔ اگر یہ غلط ہو تو فون کو دیا گیا QR code کسی ناقابل رسائی پتے کی طرف اشارہ کرے گا اور handshake کبھی مکمل نہیں ہوگا۔
اس port کے بارے میں ایک اور بات: wg-easy 15 plain HTTP کو مسترد کرتا ہے، جب تک آپ INSECURE=true set نہ کریں۔ غیر معتبر certificate کے ساتھ HTTPS کے ذریعے اس تک پہنچنا، یا اس کے سامنے موجود reverse proxy پر TLS terminate کرنا، دونوں درست طریقے ہیں۔ Default settings کے ساتھ http:// کے ذریعے اس تک پہنچنا درست نہیں ہے۔
UI port کو انٹرنیٹ پر شائع نہ کریں
compose فائل 51821 کو ہر interface پر شائع کرتی ہے۔ یہ ایسے box کا login page ہے جو آپ کے traffic کو route کر سکتا ہے، اس لیے اسے پوری دنیا کے لیے کھلا نہیں ہونا چاہیے۔ Docker میں port شائع کرنے سے DOCKER chain میں rules شامل ہوتے ہیں۔ اس chain کا جائزہ ufw سے پہلے لیا جاتا ہے، اس لیے ufw کی deny rule اس port کو بند نہیں کرتی۔ اس مسئلے کو الگ سے سمجھنا مفید ہے، اور Docker کے شائع کردہ ports ufw کو نظرانداز کیوں کرتے ہیں میں اس کی مکمل وضاحت ہے۔
آسان حل یہ ہے کہ UI کو loopback سے bind کریں اور SSH tunnel کے ذریعے اس تک رسائی حاصل کریں:
ports:
- "51820:51820/udp"
- "127.0.0.1:51821:51821/tcp"
environment:
- INSECURE=trueپھر اپنے laptop سے:
ssh -L 51821:127.0.0.1:51821 youruser@your.server.addressاپنے laptop کے browser میں http://127.0.0.1:51821 کھولیں۔ Traffic کو SSH encrypt کرتا ہے، یہ port کسی اور کو جواب نہیں دیتا، اور یہاں INSECURE=true محفوظ ہے کیونکہ plain HTTP hop loopback interface سے باہر نہیں جاتا۔
UDP 51820 کھولیں، اور دونوں فائر والز چیک کریں
WireGuard کو انٹرنیٹ سے UDP 51820 تک رسائی درکار ہوتی ہے۔ Docker یہ پورٹ شائع کرتا ہے، لیکن بہت سے فراہم کنندگان VPS کے سامنے ایک علیحدہ نیٹ ورک فائر وال رکھتے ہیں، جس کے بارے میں Docker کو کچھ معلوم نہیں ہوتا۔ دونوں مقامات پر یہ پورٹ کھولیں۔ اگر آپ host firewall کا انتظام ufw سے کرتے ہیں، تو VPS کے لیے بنیادی ufw قواعد کو ہاتھ سے nftables لکھنے کے مقابلے میں جلدی مکمل کیا جا سکتا ہے۔
چیک کریں کہ container واقعی listening کر رہا ہے:
sudo ss -ulnp | grep 51820آپ کو listening UDP socket نظر آنا چاہیے۔ اگر اس لائن میں کچھ بھی نظر نہ آئے، تو container نے interface شروع نہیں کیا، اور sudo docker compose logs wg-easy وجہ بتائے گا۔
کلائنٹ بنائیں اور اسے فون پر اسکین کریں
UI میں کلائنٹ بنائیں اور اسے ایسا نام دیں جسے آپ بعد میں پہچان سکیں، مثلاً اس ڈیوائس کا نام جس سے یہ وابستہ ہے۔ wg-easy اگلا دستیاب tunnel address مختص کرتا ہے اور آپ کے لیے key pair تیار کرتا ہے۔ ہر کلائنٹ row میں QR code اور ڈاؤن لوڈ کے لیے .conf file موجود ہوتی ہے۔
فون پر official WireGuard app انسٹال کریں، QR code سے tunnel شامل کرنے کا انتخاب کریں، اور کیمرہ اپنی اسکرین پر موجود code کی طرف کریں۔ tunnel اسی نام کے ساتھ ظاہر ہوگا جو آپ نے درج کیا تھا۔ اسے فعال کریں۔ اس کے بعد UI میں کلائنٹ row transfer counters اور حالیہ handshake time دکھانا شروع کر دے گی۔
جو کلائنٹ فعال کرنے کے بعد بھی handshake نہیں دکھاتا، وہ سرور تک بالکل نہیں پہنچ رہا۔ اس کی وجہ UDP 51820 ہو سکتی ہے، خواہ مسئلہ provider firewall میں ہو یا config میں شامل endpoint address میں۔ جو کلائنٹ handshake دکھاتا ہے لیکن internet کام نہیں کرتا، اس کا مسئلہ forwarding یا DNS میں ہوتا ہے۔
Desktop پر .conf file ڈاؤن لوڈ کریں اور اسے دوبارہ ٹائپ کرنے کے بجائے WireGuard client میں import کریں۔ اس file میں موجود private key صرف ایک بار generate اور ایک بار دکھائی جاتی ہے۔ اس file کو اسی طرح محفوظ رکھیں جیسے SSH private key کو رکھتے ہیں۔
UI سے آگے بڑھنے کا وقت
wg-easy اس وقت موزوں ٹول ہے جب آپ کے peers افراد اور phones ہوں۔ UI کے ذریعے config files میں ترمیم کرنے کے مقابلے میں کام تیزی سے ہوتا ہے، اور گمشدہ phone کو ایک click سے منسوخ کیا جا سکتا ہے۔
اس کی حدود اس وقت سامنے آتی ہیں جب آپ کو ایسا کام درکار ہو جسے UI ماڈل نہ کرتا ہو۔ Site-to-site routing میں peer کا AllowedIPs کسی ایک address کے بجائے پورے remote subnet کا احاطہ کرتا ہے۔ یہ عموماً پہلی بڑی رکاوٹ ہوتی ہے۔ Split tunnels میں ہر peer کے لیے الگ routing rules، یا آپ کے provisioning tool سے تیار کردہ config، اگلے مرحلے ہیں۔ اس مقام پر ہاتھ سے لکھی گئی setup زیادہ مشکل نہیں ہوتی؛ طریقہ صرف مختلف ہوتا ہے۔ سادہ WireGuard guide میں wg0.conf کے ذریعے اسی tunnel کی تشکیل دکھائی گئی ہے۔ اگر آپ control plane چلانا ہی بند کرنا چاہتے ہیں تو WireGuard کا Tailscale سے موازنہ managed option کی وضاحت کرتا ہے۔
اگر اوپر دیا گیا compose syntax، WireGuard کے بجائے، آپ کے لیے نیا تھا تو VPS پر Docker Compose کی بنیادی باتیں file format اور روزمرہ کے commands کی وضاحت کرتی ہیں۔
FAQ
wg-easy میرے WG_HOST اور PASSWORD_HASH کو نظرانداز کیوں کرتا ہے؟
یہ متغیرات wg-easy 14 سے تعلق رکھتے ہیں۔ Version 15 ازسرنو تیار کیا گیا ورژن ہے، اور upstream نے تقریباً تمام configuration کو web UI کے admin panel میں منتقل کر دیا ہے۔ Container ان دونوں متغیرات میں سے کسی کو بھی نہیں پڑھتا۔ اس لیے یہ معمول کے مطابق شروع ہوتا ہے اور پہلے visit پر آپ سے admin account بنانے کو کہتا ہے۔ Setup page پر client کے لیے قابلِ رسائی host address مقرر کریں۔
اگر میرے kernel میں پہلے ہی WireGuard موجود ہے تو کیا مجھے SYS_MODULE درکار ہے؟
نہیں۔ SYS_MODULE اور /lib/modules mount اس لیے موجود ہیں کہ host پر module نہ ہونے کی صورت میں container اسے load کر سکے۔ ایسے host پر جہاں sudo modprobe wireguard پہلے ہی کامیاب ہو، یہ capability استعمال نہیں ہوتی۔ اسے ہٹانا hardening کا ایک مناسب قدم ہے، اور NET_ADMIN بہرحال درکار رہتا ہے۔
Client connect ہو جاتا ہے، لیکن internet نہیں ہے۔ مسئلہ کیا ہے؟
Traffic کے بغیر handshake تقریباً ہمیشہ forwarding کے مسئلے کی نشاندہی کرتا ہے۔ تصدیق کریں کہ net.ipv4.ip_forward=1 اور net.ipv4.conf.all.src_valid_mark=1 اب بھی compose file میں موجود ہیں، کیونکہ ہاتھ سے edit کی گئی copy میں یہ اکثر ضائع ہو جاتے ہیں۔ اگر forwarding فعال ہے تو client کو موصول ہونے والے DNS server کو چیک کریں۔ ایسا tunnel جو تمام traffic VPN کے ذریعے بھیجتا ہو، لیکن ایسے DNS server کی طرف اشارہ کرتا ہو جس تک اب رسائی ممکن نہ ہو، browser میں بالکل بند connection جیسا دکھائی دیتا ہے۔
میں اپنے clients کا backup کیسے بناؤں؟
تمام data etc_wireguard named volume میں موجود wg0.json file میں محفوظ ہوتا ہے۔ UI میں backup button بھی موجود ہے، جو یہی data export کرتا ہے۔ کسی بھی upgrade سے پہلے اس file کو server سے باہر کسی محفوظ جگہ پر copy کریں۔ Restore کرنے کے لیے نئے container کے setup step کے دوران اسے upload کریں۔
کیا میں wg-easy کو reverse proxy کے پیچھے چلا سکتا ہوں؟
ہاں۔ Proxy کو TCP 51821 کے سامنے رکھیں، TLS کو وہیں terminate کریں، اور container پر INSECURE=true مقرر کریں تاکہ وہ proxy سے آنے والے plain HTTP hop کو قبول کرے۔ UDP 51820 کو براہِ راست published رکھیں، کیونکہ VPN traffic UDP ہوتا ہے اور HTTP proxy سے نہیں گزرتا۔