SSD Nodes Learn Hosting plans →
الأدلة Matt Connorبقلم Matt Connor · آخر تحديث في 2026-08-28

كيف تنشئ VPN باستخدام WireGuard على VPS؟

أنشئ WireGuard على خادم Linux لديك مع wg0.conf والمفاتيح وإعادة توجيه IP وNAT وDNS، وتعرّف إلى خطأ Operation not permitted ومشكلات المصافحة.

ما الذي ستبنيه

تتكوّن شبكة VPN باستخدام WireGuard على خادم تملكه من نحو 40 سطراً من الإعدادات: زوج مفاتيح واحد، وملف واجهة واحد، وإعداد sysctl واحد، وقاعدة NAT واحدة، وفتحة واحدة في الجدار الناري. التثبيت بسيط، لذلك يركّز معظم هذا الدليل على الأعطال الشائعة، وصلاحيات المفاتيح، وAllowedIPs، وإعادة التوجيه، وDNS.

WireGuard نفق من الطبقة 3 داخل النواة، وهو جزء من النواة الرئيسية منذ Linux 5.6. لذلك يأتي مضمّناً في Ubuntu 24.04 وDebian 13 من دون وحدة خارجية. لا توجد مفاوضة على الشيفرة، ولا سلطة شهادات، ولا خطوة لاسم مستخدم وكلمة مرور: النظير هو مفتاح عام، إضافة إلى عناوين IP التي يُسمح لذلك المفتاح باستخدامها. تُسقط الحزمة التي تفشل في فحص MAC من دون إرسال رد، لذلك لا يستجيب المنفذ لعمليات الفحص. لكن لا يوجد خادم مصادقة، لذا فإن إزالة الوصول تعني حذف نظير من الخادم.

تحقق من المحاكاة الافتراضية أولاً

يحتاج WireGuard إلى نواة يمكنك تحميل وحدة فيها، ويعمل مباشرةً على VPS يستخدم KVM. أما في المحاكاة الافتراضية المعتمدة على الحاويات، مثل OpenVZ وLXC، التي تشارك نواة المضيف، فسيفشل الأمر الأول مع RTNETLINK answers: Operation not supported، ويكون البديل هو تطبيق userspace ‏wireguard-go. تحقّق أولاً باستخدام sudo modprobe wireguard && echo ok.

إنشاء المفاتيح دون كشفها

يعادل جعل /etc/wireguard/server.key قابلاً للقراءة من الجميع عدم تشغيل VPN مطلقاً. إن سطر umask 077 && wg genkey | sudo tee ... الشائع غير موثوق، لأن sudo يطبّق umask الخاص به على الملف الذي ينشئه tee. حدّد الوضع صراحةً.

sudo apt update && sudo apt install -y wireguard nftables
sudo install -d -m 700 /etc/wireguard
sudo sh -c 'umask 077; wg genkey > /etc/wireguard/server.key'
sudo sh -c 'wg pubkey < /etc/wireguard/server.key > /etc/wireguard/server.pub'
sudo chmod 600 /etc/wireguard/server.key

أنشئ زوج مفاتيح العميل بالطريقة نفسها. يضيف wg genpsk مفتاحاً مشتركاً مسبقاً اختيارياً، بسطر واحد في كل إعداد.

واجهة الخادم: /etc/wireguard/wg0.conf

[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = <contents of /etc/wireguard/server.key>

[Peer]
PublicKey = <laptop public key>
PresharedKey = <psk, optional>
AllowedIPs = 10.8.0.2/32

chmod 600 ذلك؛ ظهور تحذير عند بدء التشغيل يفيد بأن الملف متاح لجميع المستخدمين يعني أنك تخطّيت هذه الخطوة. Address هو عنوان الخادم داخل النفق، مع قناع الشبكة الفرعية الكاملة لشبكة VPN. اختر نطاقاً لن تصادفه في الشبكات الفعلية. 192.168.1.0/24 يتعارض مع نصف أجهزة التوجيه المنزلية التي يتصل بها عملاؤك، وعندها يخسر النفق بصمت أمام المسار المحلي.

تكون قيمة AllowedIPs لنظير على جانب الخادم هي /32، أي عنوان النفق الوحيد الذي يملكه ذلك العميل. إذا منحت نظيرين عنوان IP مسموحاً به نفسه، ينتقل العنوان إلى النظير الذي عرّفته أخيراً، ويتوقف الأول عن تلقي حركة الشبكة من دون ظهور أي خطأ في أي مكان. اترك SaveConfig من دون ضبط، وإلا سيعيد wg-quick down كتابة هذا الملف انطلاقاً من الحالة الفعلية.

حوّل الخادم إلى موجّه

يسقط خادم Linux الحزم غير الموجّهة إليه. يكون التوجيه وNAT المصدر غير مفعّلين افتراضياً.

printf 'net.ipv4.ip_forward = 1\nnet.ipv6.conf.all.forwarding = 1\n' \
  | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl --system
sysctl net.ipv4.ip_forward

يعمل إعداد sysctl -w الأساسي حتى إعادة التشغيل التالية، ثم يتوقف بهدوء. يحتاج NAT إلى واجهة الخروج، أي بطاقة الشبكة التي تصل إلى الإنترنت، وليس wg0. لا تفترض eth0؛ استخرج اسم الواجهة من ip route show default، لأن الصور الحالية تستخدم أسماء مثل enp1s0 أو ens3.

الجدار الناري: المنفذ ومسار إعادة التوجيه

يغطي ملف nftables قواعد التصفية وNAT. اكتب /etc/nftables.conf؛ فهذا الأمر يفرغ مجموعة القواعد الحالية، لذلك لا تستخدمه على خادم تديره ufw أو Docker بالفعل.

#!/usr/sbin/nft -f
flush ruleset

table inet filter {
  chain input {
    type filter hook input priority filter; policy drop;
    ct state established,related accept
    iif lo accept
    tcp dport 22 accept
    udp dport 51820 accept
  }
  chain forward {
    type filter hook forward priority filter; policy drop;
    ct state established,related accept
    iifname "wg0" oifname "enp1s0" accept
  }
}

table ip nat {
  chain postrouting {
    type nat hook postrouting priority srcnat; policy accept;
    ip saddr 10.8.0.0/24 oifname "enp1s0" masquerade
  }
}

طبّق القواعد باستخدام sudo systemctl enable --now nftables، مع إبقاء جلسة SSH ثانية مفتوحة: يؤدي policy drop، إلى جانب أي خطأ إملائي في قاعدة SSH، إلى منعك من الوصول إلى خادمك. لاحظ ما لا تسمح به سلسلة إعادة التوجيه، wg0 إلى wg0. يمكن للأطراف الوصول إلى الإنترنت، لكنها لا تصل إلى بعضها بعضاً؛ أضف iifname "wg0" oifname "wg0" accept لشبكة VPN ندّية. تتحكم السلسلة نفسها في الموارد التي يمكن للند الوصول إليها على الخادم، وهذا مهم عندما يعمل الخادم أيضاً كـبيئة تطوير بعيدة تشغّل Claude Code داخل tmux ولا تريد تعريض هذا الجانب منه للعامة.

على خادم يستخدم ufw: ufw allow 51820/udp، وDEFAULT_FORWARD_POLICY="ACCEPT" في /etc/default/ufw، وقاعدة *nat POSTROUTING MASQUERADE في أعلى /etc/ufw/before.rules.

شغّلها ضمن systemd

sudo systemctl enable --now wg-quick@wg0
sudo wg show

ينشئ wg-quick الواجهة، ويضيف العناوين، ويثبّت المسارات المستمدة من AllowedIPs. أما enable --now فهو الجزء المهم: إذ يختفي تشغيل wg-quick up wg0 يدوياً بعد إعادة التشغيل التالية، كما أن ترقيات النواة تتطلب إعادة التشغيل. وتبقى الوحدة التي تفشل في العودة بعد إحدى عمليات إعادة التشغيل هذه صامتة إلى أن يحاول أحد الاتصال، لذلك يُعدّ drop-in من نوع OnFailure= على wg-quick@wg0 والموجّه إلى خادم ntfy الخاص بك الطريقة الأقل تكلفة لتلقي إشعار على هاتفك، بدلاً من معرفته من مستخدم مُنع من الوصول.

إعداد العميل، والإعداد الذي يخطئ فيه الجميع

[Interface]
PrivateKey = <laptop private key>
Address = 10.8.0.2/32
DNS = 10.8.0.1

[Peer]
PublicKey = <server public key>
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25

AllowedIPs يؤدي وظيفتين مختلفتين في الوقت نفسه، والخلط بينهما هو مصدر معظم الالتباس حول WireGuard.

من جهة الاتصالات الصادرة، يعمل كجدول توجيه. تُشفَّر الحزمة التي يطابق عنوان وجهتها AllowedIPs الخاص بنظير، ثم تُرسل إلى ذلك النظير. يرسل 0.0.0.0/0, ::/0 كل شيء عبر النفق، أي ينشئ نفقاً كاملاً ويجعل الخادم المسار الافتراضي. أما النفق المنقسم فهو قائمة أضيق: ينقل AllowedIPs = 10.8.0.0/24, 10.20.0.0/16 حركة VPN بالإضافة إلى شبكة خاصة واحدة خلف الخادم، بينما تحتفظ بقية الحركة بالمسار المحلي. تتيح لك هذه القائمة الضيقة إبقاء الخدمات خارج الإنترنت العام بالكامل. ويبقى مثيل Nextcloud خاص على VPS مرتبطاً بعنوان النفق، كما تبقى الأجهزة الافتراضية لمختبر المحاكاة الافتراضية المتداخلة التي تعمل على الخادم نفسه قابلة للوصول من النظائر وغير مرئية لأي جهة أخرى.

من جهة الاتصالات الواردة، يعمل كقائمة للتحكم في الوصول. تُسقط الحزمة المفكوك تشفيرها من نظير إذا لم يكن عنوان المصدر ضمن AllowedIPs الخاص بذلك النظير. لذلك يدرج الخادم 10.8.0.2/32 للابتوب. فإضافة 0.0.0.0/0 إليه ستتيح لذلك العميل انتحال أي عنوان داخل النفق.

يُستخدم PersistentKeepalive للعملاء الموجودين خلف NAT، حيث يُبقي الموجّه تعيين UDP مفتوحاً فقط أثناء تدفق الحزم. عند انتهاء صلاحيته، لا يعود الخادم قادراً على الوصول إلى العميل. يحافظ PersistentKeepalive = 25 على بقاء التعيين مفتوحاً. اضبطه على العميل، وليس على خادم يملك عنوان IP عاماً.

DNS، والتسرّب الذي لا يلاحظه أحد

مع AllowedIPs = 0.0.0.0/0 ومن دون سطر DNS =، يحتفظ العميل بمحلّل الأسماء الذي تعلّمه من الشبكة المحلية، أي من موجّه المقهى عند 192.168.1.1. يكون هذا المسار أكثر تحديداً من المسار الافتراضي، لذلك تخرج استعلامات DNS عبر الوصلة المحلية بنص واضح، بينما تمرر كل البيانات الأخرى عبر النفق. تكون حركة الشبكة خاصة، لكن قائمة أسماء النطاقات ليست كذلك.

هناك خياران واضحان. وجّه DNS إلى محلّل أسماء عام (DNS = 9.9.9.9)، فتمر الاستعلامات عبر النفق وتخرج من خادمك، مع بقاء هذا المحلّل قادراً على رؤيتها. أو شغّل unbound أو dnsmasq مرتبطاً بالعنوان 10.8.0.1، واضبط DNS = 10.8.0.1، وأضف udp dport 53 iifname "wg0" accept إلى سلسلة الإدخال، ثم اضبط ذلك السطر وتجاهل محلّل الأسماء؛ عندها لن تُحلّ أي أسماء على الإطلاق.

على عملاء Linux، يطبّق wg-quick الإعداد DNS عبر resolvconf؛ وإذا غاب، تحصل على resolvconf: command not found. ثبّت openresolv، أو اضبط PostUp = resolvectl dns %i 10.8.0.1 على عميل يستخدم systemd-resolved.

إضافة الأقران وإزالتهم من دون إسقاط النفق

تؤدي إعادة تشغيل الواجهة لإضافة مستخدم إلى قطع اتصال جميع المتصلين. ألحِق كتلة [Peer] بـ wg0.conf، ثم أعد تحميل مجموعة الأقران في مكانها.

sudo bash -c 'wg syncconf wg0 <(wg-quick strip wg0)'

يعرض wg-quick strip الإعدادات من دون المفاتيح الخاصة بـwg-quick فقط (Address وDNS وPostUp)، ويطبّق syncconf الفرق مع استمرار الجلسات النشطة. وهو يحدّث الأقران فقط؛ أما تغيير Address فيتطلب تنفيذ down/up كاملاً. ألغِ الصلاحية باستخدام sudo wg set wg0 peer <public key> remove، ثم احذف الكتلة من الملف، وإلا فستعود عند إعادة التحميل التالية.

أنماط الفشل، مع النصوص التي ستظهر لك

لا تكتمل المصافحة مطلقاً. يسرد wg show النظير من دون latest handshake، وتظهر في سجلات العميل الرسالة التالية:

Handshake for peer 1 (10.0.0.10:51820) did not complete after 5 seconds, retrying (try 2)

لا تصل أي حزم، أو لا تُقبل أي حزم. تحقّق بالترتيب مما يلي: هل المنفذ UDP 51820 مفتوح في جدار VPS الناري وفي جدار الشبكة الناري لدى مزود الخدمة، وهو عنصر تحكم منفصل في معظم لوحات التحكم؟ هل عنوان ومنفذ Endpoint صحيحان؟ هل تم تبديل المفاتيح؟ يجب أن يحتوي قسم [Peer] في إعدادات العميل على المفتاح العام للخادم، والعكس صحيح. يؤدي لصق مفتاح خاص أو المفتاح العام الخاص بالعميل إلى ظهور هذا العَرَض نفسه تماماً. يوضح sudo tcpdump -ni any udp port 51820 على الخادم ما إذا كانت الحزم تصل أصلاً. لا تسجل وحدة kernel شيئاً افتراضياً؛ تظهر رسائل WireGuard في dmesg فقط بعد تفعيل dynamic debug عبر echo module wireguard +p | sudo tee /sys/kernel/debug/dynamic_debug/control. عند تفعيله، يظهر عدم تطابق المفتاح على شكل إسقاط بسبب invalid-MAC.

تنجح المصافحة، لكن لا يوجد اتصال بالإنترنت. تنجح ping 10.8.0.1، لكن تنتهي مهلة ping 1.1.1.1: إعادة التوجيه أو NAT مفقود. تحقّق من أن sysctl net.ipv4.ip_forward يقرأ 1، ثم راقب العدادات أثناء تنفيذ العميل لاختبار ping، باستخدام sudo nft list ruleset أو sudo iptables -t nat -L POSTROUTING -n -v. يعني عدم تسجيل أي حزم في قاعدة masquerade أن اسم واجهة الخروج غير صحيح. أما ارتفاع العداد من دون ردود فيشير إلى سياسة سلسلة forward.

يعمل الإنترنت، لكن لا تعمل أسماء النطاقات. تنجح ping 1.1.1.1، وتُرجع curl https://example.com القيمة Could not resolve host. سطر DNS مفقود، أو أنه يحدد محلل أسماء لا يمكن الوصول إليه من داخل النفق.

تتعطل بعض مواقع HTTPS. يعمل SSH وping، لكن تحميل الصفحات الكبيرة يتوقف. السبب هو path MTU: يضيف النفق حمولة إضافية، وقد تُسقط إحدى الوصلات في المسار الحزم الأكبر من الحد من دون أن تصل رسالة ICMP إلى جهازك. خفّض MTU في إعدادات العميل [Interface]، وجرّب 1420، ثم 1380، ثم 1280. إذا أدى خفض MTU إلى حل التوقفات، لكن بقي معدل النقل أقل من المتوقع، فلا تواصل التخمين بقيم تقريبية. اتبع الخطوات الواردة في العثور على قيمة path MTU الفعلية باستخدام البحث بالتنصيف وضبط TCP MSS، إذ تساعد هذه الخطوات أيضاً على استبعاد الأسباب التي لا تتعلق بالنفق أصلاً.

ترفض الواجهة البدء. يعني Address already in use أن عملية أخرى تستخدم المنفذ UDP 51820. ويعني Cannot find device wg0 بعد فشل up عادةً أن الإعدادات رُفضت؛ اقرأ journalctl -u wg-quick@wg0 -n 50.

الترحيل من Streisand أو OpenVPN

Streisand غير مُصان، وقد أُرشف مستودعه. كما أن تشغيل VPN على أتمتة متروكة دون صيانة يسبب مشكلة أمنية تتفاقم ببطء. لا توجد ترقية مباشرة، ولا يمكن تحويل بنية مفاتيح OpenVPN التحتية. لا تستخدم WireGuard الشهادات أو CA أو تواريخ انتهاء الصلاحية، لذلك يحصل كل عميل على زوج مفاتيح جديد.

نفّذ الترحيل بالتوازي. يمكن لـWireGuard استخدام UDP 51820 بالتزامن مع استخدام OpenVPN للمنفذ 1194 على الخادم نفسه. شغّل wg0، ثم انقل العملاء واحداً تلو الآخر، وبعد ذلك أوقف الخدمة القديمة. لا ينتقل نموذج اسم المستخدم وكلمة المرور أو نموذج إلغاء الشهادات في OpenVPN إلى WireGuard. إذا كنت تحتاج إلى حسابات أو سجل تدقيق، فأضف هذه الطبقة فوق WireGuard.

النسخ الاحتياطية والترقيات وما يجهد النظام عند التوسع

/etc/wireguard هو الخادم. أنشئ له نسخة احتياطية (sudo tar czf wg-backup.tgz -C /etc wireguard، بالوضع 600، واحتفظ بها خارج الخادم)، وستتمكن من إعادة بنائه على VPS جديد خلال دقائق. إذا فقدت المفتاح الخاص للخادم، فيجب إصدار إعدادات كل عميل من جديد، لأن العملاء يثبتون المفتاح العام للخادم. الترقيات عبارة عن apt upgrade عادية، إضافةً إلى إعادة التشغيل عند تحديثات النواة، ويعود wg-quick@wg0 تلقائياً إذا فعّلته.

تكون الحالة الخاصة بكل نظير صغيرة، وتعمل التشفيرات داخل النواة، لذلك يعتمد الحد الأقصى على وحدة CPU وسعة النطاق الترددي المسموح بهما في VPS، وليس على أي شيء في هذا الإعداد. قِس ذلك باستخدام iperf3 عبر النفق بدلاً من الاعتماد على رقم منشور. ما يجهد النظام عند التوسع هو العمليات التشغيلية. يحتاج كل نظير إلى عنوان IP فريد للنفق، وتحرير ستين كتلة [Peer] يدوياً هو الطريق إلى تسلل AllowedIPs مكررة: أنشئ الإعدادات من خلال script. الخادم الواحد يعني نقطة نهاية UDP واحدة ونقطة فشل واحدة، ولا يوفّر WireGuard تجميعاً للعقد؛ لذا تعني التكرارية خادماً ثانياً بمفاتيحه الخاصة. تظل عملية تدوير المفاتيح يدوية، لذلك دوّن الجهة التي تحتفظ بكل مفتاح وطريقة إبطال كل مفتاح. عندما تتجاوز هذه السجلات قدرة ملف نصي، يكون الحل المعتاد هو طبقة تحكم مبنية فوق طبقة بيانات النواة نفسها، ويتولى خادم NetBird مستضاف ذاتياً توزيع العناوين، وتوزيع النظائر، ومفاتيح الإعداد التي كنت ستديرها يدوياً. إذا كان تشغيل طبقة التحكم بنفسك يعني إضافة خادم واحد أكثر من اللازم، فإن Tailscale يستضيفها نيابةً عنك، وتغطي خطته المجانية ستة مستخدمين مع أجهزة غير محدودة، وهو عدد يكفي لدرجة أن معظم البيئات الشخصية لا تدفع مقابلها. بعد ذلك، تُقاس التكلفة بعدد الأشخاص لا بعدد الأجهزة، لذا يعتمد المبلغ الذي تدفعه الأسرة أو الفريق الصغير فعلياً على عدد الأشخاص الذين لديهم بيانات تسجيل دخول، وليس على عدد النظائر التي كنت ستضيفها يدوياً إلى wg0.conf. وفي هذا الجانب، تتحول إدارة AllowedIPs الخاصة بالنفق المنقسم إلى الإعلان عن نطاقاتك الخاصة من موجّه شبكة فرعية، إذ يُعلَن عنها مرة واحدة من VPS واحد وتُعتمد مركزياً بدلاً من لصقها في ملف كل عميل. يتوقف جدوى هذا التبادل على نطاق ما تستطيع طبقة التحكم المستضافة الوصول إليه فعلياً، وهي لا تحتفظ بالمفاتيح التي تشفّر حركة الشبكة، لكنها تحدد النظائر التي تتعرف إلى بعضها.

يتطلب كل ذلك صندوق Linux تتحكم فيه، وعنوان IP عاماً، ونواة يمكنك تحميل module فيها، وجداراً نارياً تملكه وتديره بالكامل.

FAQ

لماذا لا تكتمل مصافحة WireGuard مطلقاً؟

يعني عرض wg show لنظير لا يحتوي على latest handshake أن الحزم لا تصل أو لا يجري قبولها. تحقّق من UDP 51820 في جدار VPS الناري وجدار الشبكة الناري المنفصل لدى مزوّد الخدمة، وتأكد من المضيف والمنفذ في Endpoint، ثم تحقّق من عدم تبديل المفاتيح؛ يجب أن يحتوي قسم [Peer] لدى العميل على المفتاح العام للخادم. يوضّح sudo tcpdump -ni any udp port 51820 على الخادم ما إذا كانت الحزم تصل أصلاً؛ أما dmesg فلا يعرض إلا حالات فشل مصافحة WireGuard بعد تفعيل التصحيح الديناميكي (echo module wireguard +p | sudo tee /sys/kernel/debug/dynamic_debug/control)، وعندها يظهر عدم تطابق المفتاح على شكل إسقاط بسبب MAC غير صالح.

تتصل الشبكة النفقيّة، لكن لا يتوفر لدي اتصال بالإنترنت. ما الناقص؟

يشير عمل ping 10.8.0.1 مع انتهاء مهلة ping 1.1.1.1 إلى وجود مشكلة في التمرير أو NAT. تأكد من أن sysctl net.ipv4.ip_forward يقرأ 1، وأنه مضبوط في /etc/sysctl.d/، وليس فقط عبر sysctl -w مؤقت يختفي بعد إعادة التشغيل. ثم تحقّق من أن قاعدة masquerade تستخدم اسم واجهة الخروج الفعلية من ip route show default أو enp1s0 أو ens3، ونادراً eth0.

هل أحتاج إلى سطر DNS = في إعدادات العميل؟

عند استخدام نفق كامل ومن دون سطر DNS =، يحتفظ العميل بمحلّل الأسماء الذي تعلّمه من الشبكة المحلية، وتخرج هذه الاستعلامات بنص واضح عبر الارتباط المحلي، بينما يمرّر كل شيء آخر عبر النفق. وجّه DNS إلى محلّل أسماء عام، أو شغّل unbound/dnsmasq مرتبطاً بـ10.8.0.1، وافتح udp dport 53 iifname "wg0" في سلسلة الإدخال.

ما الذي يتحكم فيه AllowedIPs فعلياً؟

يؤدي وظيفتين. في الاتجاه الصادر، يعمل كجدول توجيه: تُشفَّر حركة الشبكة المطابقة لـAllowedIPs الخاص بنظير، وتُرسل إلى ذلك النظير. في الاتجاه الوارد، يعمل كقائمة تحكم في الوصول: تُسقط الحزمة التي جرى فك تشفيرها إذا كان مصدرها خارج AllowedIPs الخاص بذلك النظير. لذلك يدرج جانب الخادم /32 لكل عميل، بينما قد يدرج جانب العميل 0.0.0.0/0.

هل يعمل WireGuard على أي VPS؟

يعمل على VPS يستخدم KVM عبر الوحدة الموجودة في kernel ومن دون إعداد إضافي. أما في المحاكاة الافتراضية القائمة على الحاويات والتي تشارك kernel المضيف، مثل OpenVZ أو LXC، فيفشل modprobe wireguard مع Operation not supported، ويكون البديل هو تنفيذ wireguard-go في userspace. شغّل sudo modprobe wireguard && echo ok قبل أي شيء آخر.