إصلاح DNS عبر WireGuard: 3 أسباب شائعة وحلولها
هل يظهر النفق متصلاً لكن يفشل حل الأسماء أو تتسرب الاستعلامات إلى الموجّه المحلي؟ تعرّف على أسباب DNS الثلاثة وأصلح كل حالة بخطوات واضحة.
لماذا يتعطل 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، ولن يفيد أي قدر من تعديل إعدادات محلّل الأسماء. إذا استجاب اختبارا 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.
يتطلب الإصلاح جزأين، وكلاهما ضروري. عيّن 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. عندئذ تمرّر الحزم عبر النفق، لكن الشبكة المحلية تظل قادرة على معرفة أنك اخترت ذلك الموفّر من جلسات سابقة. يجنّبك تشغيل محلّل أسماء خاص بك هذه المسألة.
يُعدّ تعيين محلّل DNS من الفروق الواضحة بين إعداد 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، لكن ذلك الملف التنفيذي غير مثبّت. ثبّت التطبيق الذي يتصل بـsystemd-resolved، ثم شغّل الواجهة مرة أخرى.
sudo apt install -y openresolv
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 بقائمة محلّلات منفصلة لكل وصلة، ويختار وصلة لكل استعلام. ما لم تُعيَّن إحدى الوصلات كمسار افتراضي للأسماء، فسيستمر في استخدام محلّل الوصلة اللاسلكية، لأن هذه الوصلة تحمل نطاق بحث بينما لا تحمل وصلةك ذلك.
اضبط محلّل الأسماء وعيّن المسار الافتراضي في الخطوة نفسها. يتوسع %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 جميع الاستعلامات إليه بدلاً من اختيار وصلة لكل استعلام. تحقّق من ذلك.
resolvectl status wg0يحتوي الخرج السليم على DNS Servers: 10.8.0.1 وDefault Route: yes. إذا قرأ Default Route القيمة no، فهذا يعني أن الجزء resolvectl domain لم يُنفّذ، وأنك عدت إلى اختيار الوصلة.
هناك حالة أخرى تستحق الذكر. إذا كان /etc/resolv.conf ملفاً فعلياً وليس رابطاً رمزياً إلى /run/systemd/resolve/stub-resolv.conf، فهذا يعني أن مكوّناً آخر يديره، وعادةً يكون NetworkManager أو مشغّل حاويات. نفّذ ls -l /etc/resolv.conf قبل تصحيح أي شيء آخر، لأن أداة تعيد كتابة ذلك الملف عند كل تغيير في الشبكة ستلغي عملك في أكثر لحظة غير مناسبة.
الترقية: محلّل DNS خاص بك مع التصفية عبر النفق
بمجرد أن تنتقل الاستعلامات عبر النفق بشكل موثوق، يصبح محلّل DNS في الطرف الآخر نقطة تحكّم. يوفّر تشغيل AdGuard Home هناك تصفية بقوائم الحظر وسجلّاً للاستعلامات لكل جهاز متصل، من دون برنامج على العميل أو إعدادات لكل جهاز. يكون سكربت التثبيت الرسمي، الذي تم التحقق منه في July 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 على عنوان واحد، وستخرج العملية الثانية مع listen udp 10.8.0.1:53: bind: address already in use.
لا تحتاج إعدادات العملاء إلى أي تغيير إذا كانت تحتوي بالفعل على DNS = 10.8.0.1. سيعرض سجل الاستعلامات الآن كل عملية بحث من كل نظير. وهذا قرار خصوصية فعلي، وليس فائدة مجانية: فأنت تنقل الثقة من مزوّد خدمة الإنترنت إلى نفسك، وأنت المسؤول عن إبقاء ذلك الخادم محدّثاً. يحتاج الخادم المعرّض للإنترنت إلى تطبيق الأساسيات أولاً، ويغطي الدقائق العشر الأولى على 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. إذا ظهرت على الواجهة اللاسلكية أو واجهة ethernet، فهذا يعني أن الاستعلامات تغادر بنص واضح. يقدّم dig +short whoami.akamai.net رأياً ثانياً، لأنه يجيب بالعنوان العام لمحلّل الأسماء التكراري الذي أرسل الاستعلام. لذلك تؤكد إجابة لا تحتوي على عنوان خادمك حدوث التسرّب.
هل أحتاج إلى السطر DNS = عند استخدام نفق مقسّم؟
نعم. يجب أن يكون عنوان محلّل الأسماء أيضاً ضمن 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 بعد ذلك القيمة Default Route: yes.
أي عميل يجب أن أصلحه أولاً عند تعطل عدة عملاء؟
أصلح عميلاً واحداً يعمل بنظام Linux، لأنه المنصة الوحيدة التي تعرض لك الآلية. يوضح لك resolvectl status وtcpdump محلّل الأسماء الذي أجاب، والواجهة التي نقلت الحزمة. تطبّق تطبيقات الهاتف وسطح المكتب القيمتين DNS وAllowedIPs نفسيهما دون عرض تفاصيل البنية، لذلك يمكنك بعد إصلاح عميل Linux نسخ إعداد أثبتَّ صحته بالفعل.