حل مشكلة تعطل DNS عند استخدام WireGuard
هل يتصل نفق WireGuard لكن لا تعمل الأسماء أو تتسرب الاستعلامات؟ اكتشف الأسباب الثلاثة الشائعة لفشل DNS وكيفية إصلاح إعدادات التوجيه وwg-quick لضمان عمل اتصالك بشكل صحيح.
لماذا يتعطل DNS فور تشغيل نفق WireGuard
يفشل DNS عبر WireGuard بثلاث طرق، ولكل طريقة إصلاحها الخاص. قد لا تُحل أي أسماء على الإطلاق، أو قد تُحل الأسماء لكن تغادر الاستعلامات جهازك خارج النفق، أو قد يعيد مدير حل الأسماء الخاص بالعميل ضبط الإعداد بعد ثوانٍ من بدء الواجهة. نادراً ما يكون النفق نفسه هو المشكلة. تكمن المشكلة في السطر الذي يحدد للعميل محلل الأسماء الذي يجب الاستعلام منه، وفي التوجيه الذي يحدد مسار الحزم إلى ذلك المحلل.
ينقل WireGuard حزم IP ولا يعرف شيئاً عن DNS (نظام أسماء النطاقات، وهو الخدمة التي تحوّل أسماء مثل example.com إلى عناوين IP). لا يُعد السطر DNS = في كتلة عميل [Interface] إعداداً لـWireGuard. يقرأه wg-quick، وهو الغلاف البرمجي shell الذي يشغّل الواجهة، ثم يحرّر wg-quick إعدادات حل الأسماء لدى العميل أثناء عمل النفق ويستعيدها عند wg-quick down. لذلك، فإن كل مشكلة أدناه هي مشكلة توجيه أو مشكلة wg-quick، وليست مشكلة تشفير مطلقاً. إذا لم تُنشئ النفق بعد، فابدأ بـإنشاء VPN ذاتي الاستضافة باستخدام WireGuard على VPS خاص بك ثم عد إلى هذه الصفحة.
تأكد من سلامة النفق قبل أن تغيّر أي إعدادات لـDNS.
sudo wg show
ping -c 3 10.8.0.1
ping -c 3 1.1.1.1يجب أن يعرض wg show النظير مع latest handshake حديث، ويجب أن تستجيب عمليتا ping. إذا انتهت مهلة ping 1.1.1.1، فغالباً لديك مشكلة في إعادة التوجيه أو NAT (ترجمة عناوين الشبكة)، وليست مشكلة DNS، ولن يفيدك أي قدر من إعدادات محلل الأسماء. قد يتسبب جدار ناري يحظر ICMP في المهلة نفسها، لذلك أكد ذلك باستخدام curl -sI https://1.1.1.1 قبل أن تبدأ بتغيير قواعد إعادة التوجيه. إذا استجابت عمليات ping لكن انهارت الإنتاجية عند بدء حركة الشبكة الفعلية، فهذه مشكلة منفصلة، وعادةً ما يعود بطء WireGuard إلى MTU وليس إلى أي شيء في هذه الصفحة. تستخدم كل الأمثلة هنا 10.8.0.0/24 كشبكة فرعية للنفق و10.8.0.1 كعنوان النفق للخادم. استبدلهما بالقيم الخاصة بك.
العطل الأول: لا يُحلّ أي اسم لأن خادم الحل لا يجيب
العَرَض واضح. يعمل ping 1.1.1.1، ويُرجع curl https://example.com النتيجة التالية:
curl: (6) Could not resolve host: example.comاستعلم مباشرةً من العميل عن خادم الحل عبر النفق. يأتي dig من حزمة dnsutils على Ubuntu وDebian.
dig +short @1.1.1.1 example.com
dig +short @10.8.0.1 example.comيعرض الأمر الأول عنواناً، وهذا يثبت أن الحزم تصل إلى الإنترنت عبر النفق. لا يعرض الأمر الثاني شيئاً ويطبع ;; communication timed out; no servers could be reached. هذا هو التشخيص كاملاً: العميل مُعدّ لاستخدام 10.8.0.1، و10.8.0.1 لا يجيب على UDP port 53.
يسبب ذلك عاملان. إما أنه لا يوجد خادم حل يعمل على الخادم، أو أن جدار حماية الخادم يُسقط الاستعلام قبل وصوله. تحقّق من الأمرين على الخادم.
sudo ss -ulnp | grep ':53'
sudo nft list rulesetيعرض خادم الحل الذي يعمل والمربوط بشكل صحيح سطراً يتضمن 10.8.0.1:53 أو 0.0.0.0:53. في Ubuntu يكون السبب غير المتوقع عادةً هو 127.0.0.53:53: هذا هو مستمع stub الخاص بـsystemd-resolved، وهو يربط عنوان loopback ولا يمكن الوصول إليه عمداً من الأجهزة الأخرى. يؤدي توجيه عميل VPN إلى خادم لا يملك سوى خادم الحل هذا إلى حدوث مهلة الانتظار نفسها تماماً.
الإصلاح هو استخدام خادم حل يستمع على عنوان النفق، مع إضافة قاعدة جدار حماية واحدة تسمح للأقران بالوصول إليه.
sudo apt update && sudo apt install -y unbound
printf 'server:\n interface: 10.8.0.1\n access-control: 10.8.0.0/24 allow\n' \
| sudo tee /etc/unbound/unbound.conf.d/wireguard.conf
sudo systemctl restart unbound
sudo ss -ulnp | grep '10.8.0.1:53'بعد ذلك، افتح المنفذ لحركة مرور النفق فقط. باستخدام nftables، أضف هذين السطرين إلى سلسلة input في /etc/nftables.conf، ثم أعد التحميل باستخدام sudo systemctl reload nftables.
udp dport 53 iifname "wg0" accept
tcp dport 53 iifname "wg0" acceptباستخدام ufw، ينفّذ sudo ufw allow in on wg0 to any port 53 المهمة نفسها. لا تفتح port 53 على الإنترنت العام مطلقاً. تعثر أدوات الفحص على خادم الحل التكراري المفتوح خلال أيام، ثم تستخدمه لتضخيم هجمات حجب الخدمة، وسيلحظ مزود الخدمة حركة المرور هذه قبلك.
أعد تشغيل dig +short @10.8.0.1 example.com من العميل. يعني ظهور عنوان في الناتج أن مسار خادم الحل يعمل، ولم يتبقَّ على العميل سوى استخدامه. أضف السطر إلى كتلة [Interface] في العميل، ثم أعد تشغيل الواجهة باستخدام sudo wg-quick down wg0 && sudo wg-quick up wg0.
[Interface]
PrivateKey = <client private key>
Address = 10.8.0.2/32
DNS = 10.8.0.1فشل ثانٍ: تسرّب DNS لأن split tunnel لا يوجّه محلّل الأسماء
هذا أسوأ، لأن كل شيء يبدو أنه يعمل. تُحلّ الأسماء، وتُحمّل الصفحات، وتنتقل الاستعلامات بنص واضح عبر الشبكة المحلية التي لم تكن تريد الوثوق بها.
يتسبب إعدادان في ذلك. الأول هو عميل يحتوي على AllowedIPs = 0.0.0.0/0, ::/0 ولا يحتوي على سطر DNS =. يثبّت wg-quick المسار الافتراضي في جدول التوجيه الخاص به، ويضيف قاعدة باستخدام suppress_prefixlength 0. ويحافظ ذلك عمداً على المسارات المحلية الأكثر تحديداً، كي يتمكن الجهاز من الوصول إلى طابعته. ويطابق محلّل الأسماء الذي تعلّمه العميل عبر DHCP، وعادةً ما يكون الموجّه عند 192.168.1.1، أحد تلك المسارات المحلية. تمر حركة الشبكة عبر النفق. لكن الشبكة المحلية ما زالت تتلقى القائمة الكاملة للأسماء التي تبحث عنها.
الحالة الثانية هي split tunnel: AllowedIPs = 10.8.0.0/24 مع DNS = 9.9.9.9. لأن 9.9.9.9 ليس ضمن AllowedIPs، لا يملك العميل مساراً إليه عبر النفق. لذلك يغادر الاستعلام عبر الوصلة المحلية، تماماً كما في الحالة الأولى.
أثبت أي محلّل أسماء يجيب فعلياً. إنّ whoami.akamai.net هو اسم اختبار عام يجيب بعنوان IP لمحلّل الأسماء التكراري الذي أجرى الاستعلام، وبذلك يمكنك مقارنة إجابته بالعنوان العام لخادمك.
resolvectl status
dig +short whoami.akamai.net
sudo tcpdump -ni any -c 10 port 53يطبع resolvectl status كتلة واحدة لكل وصلة. إذا كانت كتلة وصلة Ethernet أو الاتصال اللاسلكي لديك لا تزال تعرض Current DNS Server: 192.168.1.1، بينما لا تعرض كتلة wg0 أي شيء، فهذا هو التسرّب. ويؤكد إرجاع dig +short whoami.akamai.net لعنوان اتصال النطاق العريض المنزلي بدلاً من عنوان خادمك ذلك من الطرف البعيد. أما سطر tcpdump فهو الدليل الحاسم: يضع الناتج السليم كل حزمة على المنفذ 53 تغادر الجهاز في wg0، بينما يضعها التسرّب في wlan0 أو enp3s0. والحزم الموجودة على lo من وإلى 127.0.0.53 هي اتصالات التطبيقات بواجهة systemd-resolved المحلية، وليست تسرّباً.
يتكون الإصلاح من جزأين، وكلاهما مطلوب. عيّن DNS إلى عنوان موجود داخل النفق، وتأكد من أن ذلك العنوان يقع ضمن AllowedIPs.
[Interface]
Address = 10.8.0.2/32
DNS = 10.8.0.1
[Peer]
PublicKey = <server public key>
Endpoint = vpn.example.com:51820
AllowedIPs = 10.8.0.0/24, 10.20.0.0/16يقع 10.8.0.1 ضمن 10.8.0.0/24، لذلك يُشفَّر الاستعلام ويُرسل إلى الخادم. إذا أصررت على استخدام محلّل أسماء عام مع split tunnel، فأضفه كمسار لمضيف واحد: AllowedIPs = 10.8.0.0/24, 9.9.9.9/32. عندها تُمرَّر الحزم عبر النفق، لكن الشبكة المحلية ستظل قادرة على معرفة أنك اخترت ذلك المزوّد من الجلسات السابقة. ويجنّبك تشغيل محلّل أسماء خاص بك هذه المشكلة.
يُعد تعيين محلّل الأسماء أحد الفروق الظاهرة بين WireGuard المُنشأ يدوياً وشبكة mesh المنسّقة، وهو جزء من المفاضلة الموضحة في مقارنة WireGuard مع Tailscale. ويمنحك تشغيل خادم تحكم Headscale مستضاف ذاتياً هذا التنسيق دون تسليم مواد مفاتيحك إلى طرف ثالث. وإذا كانت هذه العبارة الأخيرة هي ما يقلقك، فتذكّر أن Tailscale لا يحتفظ مطلقاً بالمفاتيح التي تشفّر حركة شبكتك، وأن السؤال الأدق هو ما الذي يمكن لخادم تنسيق مخترق أو لحساب هوية مسروق أن يضيفه إلى شبكتك.
يفشل العطل الثالث: تعارض resolvconf وsystemd-resolved على عملاء Linux
تطبّق عملاء macOS وWindows وiOS وAndroid الإعداد DNS = عبر التطبيق الرسمي، ولا تسبب مشكلات تُذكر. أما Linux، فيطبّق الإعداد عبر shell script يحاول تخمين أيٍّ من عدة مديرات لحل الأسماء تستخدم.
يكون الفشل الأول واضحاً. يتوقف sudo wg-quick up wg0 مع الرسالة:
resolvconf: command not foundيستدعي wg-quick الأمر resolvconf، لكن ذلك الملف التنفيذي غير مثبّت. في Debian 12 وUbuntu 24.04 أو الإصدارات الأحدث، يوجد الأمر resolvconf الذي يتعامل مع systemd-resolved ضمن الحزمة systemd-resolved. ثبّت الحزمة، ثم ارفع الواجهة مجدداً. لا توجد حزمة منفصلة لهذا الأمر في Ubuntu 22.04. أنشئ هناك رابط التوافق بنفسك باستخدام sudo ln -s /usr/bin/resolvectl /usr/local/bin/resolvconf، وتجاوز سطر التثبيت.
sudo apt install -y systemd-resolved
sudo systemctl restart systemd-resolved
sudo wg-quick down wg0 && sudo wg-quick up wg0
resolvectl status wg0الفشل الثاني صامت، وهو الذي قد يستهلك أمسية كاملة. تعمل الواجهة، ويعرض resolvectl status wg0 القيمة DNS Servers: 10.8.0.1 بشكل صحيح، لكن عمليات البحث لا تزال تصل إلى محلل الأسماء القديم. لا يتجاهل systemd-resolved الإعداد wg0. يرسل اسماً لا يطابق أي نطاق توجيه إلى خوادم DNS لكل وصلة تُعد مساراً افتراضياً. وتُعد الوصلة التي تحتوي على خوادم DNS ولا تحتوي على نطاق مخصص للتوجيه وصلة افتراضية تلقائياً. لذلك يُرسل الاستعلام إلى 10.8.0.1 وإلى الموجّه على الوصلة اللاسلكية في الوقت نفسه، وتُعتمد أول إجابة ناجحة. يكون الموجّه على بُعد قفزة واحدة، ويرد عادةً أولاً، ويكون الاستعلام قد غادر الجهاز بنص واضح في كلتا الحالتين. أما الأسماء الواقعة ضمن نطاق البحث الخاص بالوصلة اللاسلكية، مثل lan، فتُرسل إلى تلك الوصلة فقط، لأن نطاق التوجيه الأكثر تخصيصاً هو الذي يفوز.
عندما يطبّق wg-quick الإعداد DNS = عبر غلاف resolvconf الخاص بـsystemd، فإنه يطلب بالفعل نطاق توجيه شاملاً. لذلك يظهر هذا الفشل غالباً عند استخدام تطبيق آخر لـresolvconf أو عند تطبيق الإعداد بواسطة مدير للشبكة. يؤدي تعيينه صراحةً إلى إزالة التخمين.
عيّن محلل الأسماء واطلب نطاق التوجيه الشامل في الخطوة نفسها. يتوسع %i إلى اسم الواجهة، لذلك تعمل هذه الكتلة دون تغيير على أي واجهة.
[Interface]
Address = 10.8.0.2/32
PostUp = resolvectl dns %i 10.8.0.1; resolvectl domain %i ~.
PostDown = resolvectl revert %iاحذف السطر DNS = عند استخدام PostUp بهذه الطريقة، وإلا فستكتب آليتان حالة محلل الأسماء، ولن تنظفها بعد ذلك إلا إحداهما. الوسيطة ~. هي الجزء المهم؛ فهي تجعل wg0 نطاقاً مخصصاً للتوجيه لكل اسم، وبذلك يتوقف systemd-resolved عن إرسال الأسماء التي لا يطابقها نطاق أكثر تخصيصاً إلى الوصلات الأخرى. وتظل الأسماء الواقعة ضمن نطاق خاص بوصلة أخرى، مثل lan، تُرسل إلى تلك الوصلة، وهذا هو المطلوب عادةً للمضيفين المحليين. تحقّق من النتيجة.
resolvectl status wg0يحتوي الخرج السليم على DNS Servers: 10.8.0.1 وDNS Domain: ~.. إذا كان ~. مفقوداً، فهذا يعني أن جزء resolvectl domain لم يُنفّذ، وأن wg0 عاد إلى التنافس مع الوصلات الأخرى. لا تستخدم راية المسار الافتراضي للتحقق؛ فهي تعرض yes، أو +DefaultRoute في سطر Protocols، حسب إصدار systemd، حتى من دون ~.، لأن الوصلة التي لا تحتوي على نطاق مخصص للتوجيه تُعد مساراً افتراضياً على أي حال.
تجدر الإشارة إلى حالة أخرى. إذا كان /etc/resolv.conf ملفاً فعلياً وليس رابطاً رمزياً إلى /run/systemd/resolve/stub-resolv.conf، فهناك مكوّن آخر يملكه، وعادةً يكون NetworkManager أو بيئة تشغيل حاويات. شغّل ls -l /etc/resolv.conf قبل تصحيح أي شيء آخر، لأن أداة تعيد كتابة ذلك الملف عند كل تغيير في الشبكة ستلغي عملك في أسوأ وقت.
الترقية: محلّل DNS خاص بك مع التصفية عبر النفق
بعد أن تنتقل الاستعلامات عبر النفق بشكل موثوق، يصبح محلّل DNS في الطرف البعيد نقطة تحكم. يوفّر تشغيل AdGuard Home هناك تصفية بقوائم الحظر وسجلّاً للاستعلامات لكل جهاز متصل، من دون تثبيت برنامج على العميل أو إعداد كل جهاز على حدة. نص التثبيت الرسمي، الذي جرى التحقق منه في أكتوبر 2026، يتكون من سطر واحد.
curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -vيستمع معالج الإعداد إلى المنفذ 3000 عند التشغيل الأول. افتحه عبر النفق على http://10.8.0.1:3000 بدلاً من فتح هذا المنفذ للعامة، واضبط في المعالج كلاً من عنوان الاستماع لـDNS وعنوان الاستماع للإدارة على 10.8.0.1. إذا كانت unbound من العطل الأول ما تزال تستخدم العنوان نفسه، فأوقفها أولاً باستخدام sudo systemctl disable --now unbound، لأن الخدمتين ستتنافسان على منفذ UDP 53 في عنوان واحد، ثم يخرج AdGuard Home مع listen udp 10.8.0.1:53: bind: address already in use.
لا تحتاج إعدادات العملاء إلى أي تغيير إذا كانت تشير بالفعل إلى DNS = 10.8.0.1. سيعرض سجل الاستعلامات الآن كل عملية بحث تصل إليه من كل peer، ما لم تستبعد عميلاً من التسجيل. وهذا قرار خصوصية فعلي، وليس مكسباً بلا تكلفة: فأنت تنقل الثقة من مزود الإنترنت إلى نفسك، وأنت المسؤول عن إبقاء ذلك الخادم محدّثاً. يحتاج الخادم المعرّض للإنترنت إلى تطبيق الأساسيات أولاً، ويغطي الدقائق العشر الأولى على VPS جديد هذه الخطوات.
FAQ
لماذا يتصل نفق WireGuard الخاص بي ولكن لا يتم حل أسماء النطاقات؟
لا يتعامل النفق مع الأسماء، فهو ينقل الحزم فقط، لذا فإن عمل النفق مع تعطل عمليات البحث يعني أن المحلّل الذي تشير إليه لا يستجيب. اختبر ذلك باستخدام dig +short @10.8.0.1 example.com من العميل. تعني استجابة communication timed out إما أن لا يوجد محلّل يستمع على عنوان النفق هذا، وغالباً ما يحدث ذلك لأن stub الخاص بـsystemd-resolved يرتبط بـ127.0.0.53 فقط، أو أن جدار حماية الخادم يسقط حزم UDP للمنفذ 53 القادمة على wg0. أصلح المستمع أولاً، ثم افتح المنفذ لـwg0 فقط.
كيف أتحقق مما إذا كان DNS الخاص بي يسرب البيانات عبر WireGuard؟
شغّل sudo tcpdump -ni any -c 10 port 53 على العميل وراقب عمود الواجهة أثناء التصفح. يجب أن تخرج كل حزمة تغادر الجهاز عبر wg0؛ الحزم الموجودة على lo من أو إلى 127.0.0.53 هي حزم stub الخاصة بـsystemd-resolved المحلي وهي سليمة. إذا ظهرت الحزم على واجهة الشبكة اللاسلكية أو الإيثرنت، فهذا يعني أن الاستعلامات تخرج كنص واضح. يقدّم dig +short whoami.akamai.net رأياً ثانياً، لأنه يجيب بالعنوان العام لأي محلّل تكراري قام بالاستعلام، لذا فإن الحصول على إجابة ليست عنوان خادمك يؤكد وجود تسريب.
هل أحتاج إلى سطر DNS = إذا كنت أستخدم نفقاً مقسماً (split tunnel)؟
نعم، ويجب أن يقع عنوان المحلّل أيضاً داخل AllowedIPs وإلا فلن يمتلك العميل مساراً للوصول إليه. مع AllowedIPs = 10.8.0.0/24، يكون المحلّل الموجود في 10.8.0.1 مغطى ويتم تشفير الاستعلام. أما المحلّل العام مثل 9.9.9.9 فهو غير مغطى، لذا يخرج الاستعلام عبر الرابط المحلي على الرغم من أن سطر DNS يبدو صحيحاً.
لماذا يُظهر resolvectl الخادم الصحيح ولكن عمليات البحث تذهب إلى مكان آخر؟
يرسل systemd-resolved أي اسم لا يطابق نطاق توجيه إلى كل رابط ذي مسار افتراضي في وقت واحد، بما في ذلك wg0، ويعيد أول إجابة ناجحة، والتي تأتي عادةً من الموجه المحلي. أضف PostUp = resolvectl dns %i 10.8.0.1; resolvectl domain %i ~. إلى كتلة [Interface] في العميل وأزل سطر DNS =. يجب أن يبلغ resolvectl status wg0 حينها عن DNS Domain: ~.، وسيتوجه كل اسم لا يطالب به رابط آخر بنطاق أكثر تحديداً إلى wg0 فقط.
أي عميل يجب أن أصلحه أولاً عندما يكون هناك عدة عملاء معطلين؟
أصلح عميل Linux واحداً، لأنه المنصة الوحيدة التي تظهر لك الآلية. يخبرك resolvectl status وtcpdump بالمحلّل الذي أجاب والواجهة التي نقلت الحزمة. تطبق تطبيقات الهواتف والحواسيب المكتبية نفس قيم DNS وAllowedIPs دون عرض البنية التحتية، لذا بمجرد أن يصبح عميل Linux صحيحاً، فأنت تنسخ إعداداً أثبتَّ صحته بالفعل.