إصلاح DNS عبر WireGuard: 3 أسباب لتعطله
هل يعمل نفق WireGuard دون حل الأسماء أو تتسرب الاستعلامات إلى الموجّه المحلي؟ تعرّف إلى أعطال DNS الثلاثة وأصلح كل عطل بالتوجيه المناسب.
لماذا يتعطل DNS فور بدء نفق WireGuard
يفشل DNS عبر WireGuard بثلاث طرق، ولكل طريقة إصلاحها الخاص. قد لا تُحل أي أسماء على الإطلاق. أو قد تُحل الأسماء، لكن تغادر الاستعلامات جهازك خارج النفق. أو قد يعيد مدير حل الأسماء الخاص بالعميل الكتابة فوق الإعداد بعد ثوانٍ من بدء الواجهة. نادرًا ما يكون النفق نفسه هو المشكلة. المشكلة هي السطر الذي يحدد خادم الحل الذي يجب على العميل الاستعلام منه، والتوجيه الذي يحدد كيفية انتقال الحزم إلى ذلك الخادم.
ينقل WireGuard حزم IP ولا يعرف شيئًا عن DNS (نظام أسماء النطاقات، وهو الخدمة التي تحول أسماء مثل example.com إلى عناوين IP). لا يمثل السطر DNS = في كتلة العميل [Interface] إعدادًا لـ WireGuard. يقرأه wg-quick، وهو غلاف الصدفة الذي يشغّل الواجهة، ثم يحرر 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، ولن يفيد أي قدر من ضبط إعدادات خادم الحل. تستخدم كل الأمثلة هنا 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، لأن النفق المنقسم لا يوجّه محلّل الأسماء
هذا أسوأ، لأن كل شيء يبدو وكأنه يعمل. تُحلّ الأسماء، وتُحمّل الصفحات، وتنتقل الاستعلامات بنص واضح عبر الشبكة المحلية التي لم تكن تريد الوثوق بها.
يتسبب إعدادان في ذلك. الأول هو وجود عميل يستخدم AllowedIPs = 0.0.0.0/0, ::/0 من دون سطر DNS =. يثبّت wg-quick المسار الافتراضي في جدول التوجيه الخاص به، ويضيف قاعدة باستخدام suppress_prefixlength 0. ويحافظ ذلك عمداً على المسارات المحلية الأكثر تحديداً، حتى يتمكن الجهاز من الوصول إلى طابعته. ويطابق محلّل الأسماء الذي تعلّمه العميل عبر DHCP، وعادةً ما يكون الموجّه عند 192.168.1.1، أحد تلك المسارات المحلية. تمر حركة الشبكة عبر النفق. لكن الشبكة المحلية تستمر في تلقي القائمة الكاملة للأسماء التي تبحث عنها.
الثاني هو النفق المنقسم: 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، ولذلك يُشفّر الاستعلام ويُرسل إلى الخادم. إذا أصررت على استخدام محلّل أسماء عام مع نفق منقسم، فأضفه كمسار لمضيف: AllowedIPs = 10.8.0.0/24, 9.9.9.9/32. وستمر الحزم عبر النفق، لكن الشبكة المحلية ستظل قادرة على معرفة أنك اخترت ذلك المزوّد من الجلسات السابقة. ويجنبك تشغيل محلّل أسماء خاص بك هذه المشكلة.
يُعد تعيين محلّل الأسماء أحد الفروق الواضحة بين WireGuard المُنشأ يدوياً والشبكة المترابطة التي تُدار بتنسيق مركزي. وهذا جزء من المفاضلة الموضحة في مقارنة WireGuard مع Tailscale. ويمنحك تشغيل خادم تحكم Headscale مستضافاً ذاتياً هذا التنسيق من دون تسليم مواد مفاتيحك إلى طرف ثالث.
الإخفاق الثالث: يتعارض 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 أن محلل الأسماء لا يستمع على عنوان النفق، وغالبًا يكون السبب أن كعب 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، ستنسخ إعدادًا سبق أن أثبت صحته.