wg-easy: إعداد WireGuard بواجهة ويب وDocker
شغّل WireGuard مع واجهة wg-easy عبر Docker Compose، وتعرّف إلى المنافذ وNET_ADMIN وsysctls المطلوبة، وفخ إعدادات الإصدار 15 ورموز QR للهواتف.
ما الذي ستنشئه
wg-easy هو WireGuard مع واجهة ويب، ويعمل داخل حاوية Docker واحدة. يتولى إدارة واجهة WireGuard نيابةً عنك، ويضيف واجهة متصفح لإنشاء العملاء. يحصل كل عميل تنشئه على ملف إعداد ورمز QR، لذلك يمكن للهاتف الانضمام إلى VPN بتوجيه الكاميرا نحو الشاشة.
النفق نفسه هو WireGuard عادي. تنقل وحدة kernel الحزم، لذلك تكون سرعة النقل مماثلة لإعداد مكتوب يدويًا. ما تحصل عليه هو إدارة دورة حياة العملاء: إضافة الأقران وتعطيلهم وحذفهم دون تعديل ملف إعداد عبر SSH. وما تتخلى عنه هو التحكم المباشر في ذلك الملف، وهذا هو موضوع إعداد WireGuard اليدوي على VPS.
تحتاج إلى VPS من نوع KVM مع عنوان IPv4 عام، وDocker Engine مع إضافة Compose، ووصول root. عادةً لا تستطيع تقنيات المحاكاة الافتراضية للحاويات التي تشارك kernel الخاص بالمضيف، مثل OpenVZ أو LXC، تحميل وحدة WireGuard، وستفشل الحاوية في تشغيل الواجهة.
نقل الإصدار 15 الإعدادات من متغيرات البيئة
كُتبت معظم الأدلة التي ستجدها لإصدار wg-easy 14، حيث كنت تضبط WG_HOST على عنوان خادمك وPASSWORD_HASH على تجزئة bcrypt لكلمة مرور المسؤول، وكان كلاهما متغيري بيئة. الإصدار 15 إعادة كتابة للبرنامج. توضح ملاحظات الترحيل الرسمية أن v15 لا يستخدم متغيرات البيئة نفسها التي يستخدمها v14، وأن معظم هذه الإعدادات نُقلت إلى لوحة المسؤول في واجهة الويب.
لذلك لم يعد WG_HOST وPASSWORD_HASH يؤديان أي وظيفة. إذا نسخت ملف compose قديماً، فستبدأ الحاوية وتتجاهل هذين السطرين، ثم تطلب منك إنشاء حساب مسؤول في المتصفح. هذا ليس خطأً. بل هو مسار الإعداد الجديد.
اعتباراً من July 2026، فإن الوسم الرئيسي الذي ينبغي تثبيته هو 15. ثبّت الإصدار الرئيسي بدلاً من استخدام latest، لأن ترقية الإصدار الرئيسي تغيّر تنسيق الإعدادات على القرص، ولن تتمكن من التراجع عنها بطريقة سليمة.
ملف compose
أنشئ دليلًا للمكدس واكتب ملف compose الرسمي فيه. هذا هو الملف المقدم من المشروع، من دون تعديل.
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تبدو المحتويات كما يلي:
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::/64يُعد etc_wireguard وحدة تخزين مسماة تحتوي على مفتاح الخادم وكل عميل تنشئه. انسخ هذه الوحدة احتياطيًا، وإلا فستؤدي إعادة البناء إلى حذف جميع أقرانك. إذا كنت تفضل رؤية هذه الملفات في نظام ملفات المضيف، فاستبدلها بتركيب ربط، واقرأ الفرق بين تركيبات الربط ووحدات التخزين المسماة قبل ذلك، لأن الأذونات تتصرف بطريقة مختلفة.
سبب حاجته إلى NET_ADMIN وSYS_MODULE وsysctls
لا يُسمح للحاوية بالوصول إلى مكدس الشبكة افتراضيًا. ويلغي كل سطر من هذه الأسطر عائقًا محددًا.
يتيح NET_ADMIN للحاوية إنشاء واجهة wg0 وتعيين عنوان لها وكتابة المسارات. وبدونه تبدأ الحاوية ثم تتوقف أثناء تشغيل الواجهة، لأن ip link add wg0 type wireguard يعيد Operation not permitted.
يسمح SYS_MODULE، إلى جانب التركيب للقراءة فقط /lib/modules، للحاوية بتحميل وحدة WireGuard في النواة إذا لم يكن المضيف قد حمّلها مسبقًا. توجد الوحدة في نواة المضيف، وليس داخل الصورة، ولذلك يجب أن يكون دليل المضيف مرئيًا. في النوى الحديثة تكون الوحدة مضمّنة عادةً، ويمكنك التحقق من ذلك باستخدام sudo modprobe wireguard && echo ok على المضيف.
يجعل net.ipv4.ip_forward=1 النواة تمرر الحزم التي لا تكون موجهة إلى الجهاز نفسه. وبدونه يتصل العميل وتنجح المصافحة، ثم تُسقط كل حزمة متجهة إلى الإنترنت، ولذلك تنتهي مهلة ping 1.1.1.1 بينما تبدو VPN متصلة.
أما net.ipv4.conf.all.src_valid_mark=1 فهو الإعداد الذي يفاجئ الكثيرين. يضع WireGuard علامات على حزم الخروج الخاصة به حتى لا تُوجَّه مجددًا إلى داخل النفق. يرى ترشيح المسار العكسي الصارم حزمةً لا يطابق عنوان مصدرها المسار المتوقع، فيسقطها. يخبر هذا sysctl النواة بقبول الحزم المعلَّمة، وهو ما يمنع النفق الكامل من تعطيل نفسه.
تشغيله وإنشاء حساب المسؤول
cd /etc/docker/containers/wg-easy
sudo docker compose up -d
sudo docker compose logs -fاستخدم docker compose up وdocker compose down، وليس start وstop. يحذّر المشروع الأصلي من أن استخدام start على حاوية أُنشئت بإعدادات مختلفة يترك الشبكة في حالة غير متسقة. إذا أردت استعادة المكدس بعد إعادة التشغيل، فإن restart: unless-stopped يتكفل بذلك بالفعل، وتشرح سلوك إقلاع خدمات compose ما تضمنه تلك السياسة وما لا تضمنه.
تستمع واجهة الويب على TCP 51821. عند زيارتها لأول مرة، تعرض صفحة إعداد تنشئ فيها حساب المسؤول وتؤكد عنوان المضيف الذي سيستخدمه العملاء للوصول إلى الخادم. يظهر عنوان المضيف هذا في سطر Endpoint في إعداد كل عميل، لذلك يجب أن يكون عنوان IP العام للخادم الافتراضي الخاص VPS أو اسم DNS له. إذا كان العنوان خاطئًا، فإن رمز QR الذي تعطيه للهاتف يشير إلى وجهة يتعذر الوصول إليها، ولا تكتمل عملية المصافحة.
هناك أمر آخر يتعلق بهذا المنفذ: يرفض wg-easy 15 استخدام HTTP العادي ما لم تضبط INSECURE=true. يمكنك الوصول إليه عبر HTTPS باستخدام شهادة غير موثوقة، أو إنهاء TLS عند وكيل عكسي أمامه. أما الوصول إليه عبر http:// باستخدام الإعدادات الافتراضية، فلا يعمل.
لا تنشر منفذ واجهة المستخدم على الإنترنت
ينشر ملف Compose المنفذ 51821 على كل الواجهات. هذه صفحة تسجيل دخول لخادم يمكنه توجيه حركة الشبكة لديك، لذلك يجب ألا تكون مفتوحة للجميع. يؤدي نشر منفذ في Docker إلى كتابة قواعد في السلسلة DOCKER، التي تُقيَّم قبل ufw. لذلك لا تؤدي قاعدة الرفض في ufw إلى إغلاقه. من المهم فهم هذا الخطأ بحد ذاته، ويشرح سبب تجاهل المنافذ التي ينشرها Docker لقواعد ufw هذه المسألة بالتفصيل.
الحل البسيط هو ربط واجهة المستخدم بواجهة loopback والوصول إليها عبر نفق SSH:
ports:
- "51820:51820/udp"
- "127.0.0.1:51821:51821/tcp"
environment:
- INSECURE=trueثم نفّذ ذلك من حاسوبك المحمول:
ssh -L 51821:127.0.0.1:51821 youruser@your.server.addressافتح http://127.0.0.1:51821 في المتصفح على حاسوبك المحمول. تُشفَّر حركة الشبكة بواسطة SSH، ولا يستجيب المنفذ لأي شخص آخر، ويكون INSECURE=true آمنًا هنا لأن اتصال HTTP غير المشفّر لا يغادر واجهة loopback.
افتح المنفذ UDP 51820 وتحقق من كلا الجدارين الناريين
يحتاج WireGuard نفسه إلى إمكانية الوصول إلى UDP 51820 من الإنترنت. ينشر Docker المنفذ، لكن العديد من موفري الخدمة يضعون جدارًا ناريًا منفصلًا للشبكة أمام VPS، ولا يعرف Docker شيئًا عنه. افتح المنفذ في كلا الموضعين. إذا كنت تدير جدار المضيف الناري باستخدام ufw، فإن قواعد ufw الأساسية لـ VPS أقصر من كتابة قواعد nftables يدويًا.
تحقق من أن الحاوية تستمع فعلًا:
sudo ss -ulnp | grep 51820يجب أن ترى مقبس UDP في حالة استماع. عدم ظهور أي شيء في ذلك السطر يعني أن الحاوية لم ترفع الواجهة، وسيحدد sudo docker compose logs wg-easy السبب.
أنشئ عميلًا وامسحه باستخدام هاتف
في واجهة المستخدم، أنشئ عميلًا وامنحه اسمًا يمكنك تمييزه لاحقًا، مثل اسم الجهاز الذي ينتمي إليه. يخصص wg-easy عنوان النفق الحر التالي وينشئ زوج المفاتيح نيابةً عنك. يوفّر كل صف للعميل رمز QR وملف .conf قابلًا للتنزيل.
ثبّت تطبيق WireGuard الرسمي على الهاتف، واختر إضافة نفق من رمز QR، ثم وجّه الكاميرا إلى الرمز الظاهر على الشاشة. يظهر النفق بالاسم الذي أدخلته. فعّله، وسيبدأ صف العميل في واجهة المستخدم بعرض عدادات النقل ووقت آخر مصافحة.
إذا لم يعرض العميل أي مصافحة بعد تفعيله، فهذا يعني أنه لا يصل إلى الخادم إطلاقًا. يشير ذلك إلى UDP 51820، إما في جدار الحماية لدى مزود الخدمة أو في عنوان نقطة النهاية المضمّن في ملف الإعداد. إذا عرض العميل مصافحة، لكن الإنترنت لا يعمل، فالمشكلة تتعلق بإعادة التوجيه أو بـ DNS.
على جهاز سطح المكتب، نزّل ملف .conf واستورده إلى عميل WireGuard بدلًا من إعادة كتابته يدويًا. يُنشأ المفتاح الخاص في هذا الملف مرة واحدة ويُعرض مرة واحدة. تعامل مع الملف كما تتعامل مع مفتاح SSH الخاص.
متى تتجاوز حدود واجهة المستخدم
يُعد wg-easy الأداة المناسبة ما دام النظراء أشخاصًا وهواتف. واجهة المستخدم أسرع من تعديل ملفات الإعداد، وإلغاء صلاحية هاتف مفقود لا يتطلب سوى نقرة واحدة.
ستصل إلى حدوده عندما تريد شيئًا لا تمثّله واجهة المستخدم. يُعد التوجيه من موقع إلى موقع، حيث تغطي AllowedIPs الخاصة بنظير شبكة فرعية بعيدة كاملة بدلًا من عنوان واحد، أول عائق شائع. وتأتي بعد ذلك الأنفاق المقسّمة مع قواعد توجيه لكل نظير، أو إعداد يُنشئه لديك نظام توفير الموارد. عند هذه النقطة، لا يكون الإعداد اليدوي أصعب؛ بل يختلف فقط. يوضح دليل WireGuard الأساسي إنشاء النفق نفسه باستخدام wg0.conf. وإذا كنت تفضّل إيقاف تشغيل مستوى التحكم بالكامل، يشرح WireGuard مقارنةً بـ Tailscale الخيار المُدار.
إذا كانت صيغة compose أعلاه هي الجزء غير المألوف، وليس جزء WireGuard، فإن أساسيات Docker Compose على VPS تشرح تنسيق الملف والأوامر اليومية.
FAQ
لماذا يتجاهل wg-easy المتغيرين WG_HOST وPASSWORD_HASH؟
ينتمي هذان المتغيران إلى wg-easy 14. أما الإصدار 15 فهو إعادة كتابة، وقد نقل المشروع الأصلي معظم الإعدادات إلى لوحة الإدارة في واجهة الويب. لا يقرأ الحاوي أيًا من المتغيرين، لذلك يبدأ بشكل طبيعي ثم يطلب منك إنشاء حساب إدارة عند أول زيارة. عيّن عنوان المضيف الذي سيستخدمه العملاء في صفحة الإعداد هذه.
هل أحتاج إلى SYS_MODULE إذا كانت نواة النظام تحتوي بالفعل على WireGuard؟
لا. يوجد كل من SYS_MODULE وتركيب /lib/modules حتى يتمكن الحاوي من تحميل الوحدة عندما لا يوفرها المضيف. على مضيف ينجح فيه sudo modprobe wireguard مسبقًا، لا تُستخدم هذه الإمكانية. يُعد حذفها خطوة معقولة لتعزيز الأمان، بينما يظل NET_ADMIN مطلوبًا في جميع الحالات.
يتصل العميل، لكن لا يوجد إنترنت. ما المشكلة؟
تعني المصافحة التي لا يصاحبها مرور بيانات في الغالب وجود مشكلة في إعادة التوجيه. تحقق من بقاء net.ipv4.ip_forward=1 وnet.ipv4.conf.all.src_valid_mark=1 في ملف compose، لأن النسخة التي عُدّلت يدويًا تفقدهما غالبًا. إذا كانت إعادة التوجيه مفعّلة، فتحقق من خادم DNS الذي تلقاه العميل. النفق الذي يرسل كل المرور عبر VPN، لكنه يشير إلى خادم DNS لم يعد قادرًا على الوصول إليه، يبدو في المتصفح تمامًا كأنه اتصال متوقف.
كيف أنشئ نسخة احتياطية من عملائي؟
توجد جميع البيانات في وحدة التخزين المسماة etc_wireguard، داخل ملف wg0.json. تحتوي واجهة المستخدم أيضًا على زر للنسخ الاحتياطي يصدّر البيانات نفسها. انسخ هذا الملف إلى مكان خارج الخادم قبل إجراء أي ترقية. تتم الاستعادة عبر رفع الملف أثناء خطوة الإعداد في حاوي جديد.
هل يمكنني تشغيل wg-easy خلف وكيل عكسي؟
نعم. ضع الوكيل أمام TCP 51821، وأنهِ TLS عنده، واضبط INSECURE=true على الحاوي حتى يقبل قفزة HTTP العادية من الوكيل. أبقِ UDP 51820 منشورًا مباشرة، لأن مرور VPN يستخدم UDP ولا يمر عبر وكيل HTTP.