حل مشکل DNS در WireGuard: سه خطای رایج و راهکارها
تونل WireGuard فعال است اما DNS کار نمیکند یا درخواستها نشت میکنند؟ با بررسی این 3 سناریوی خرابی، مشکل تنظیمات DNS و مسیریابی سیستم خود را در چند دقیقه شناسایی و رفع کنید.
چرا DNS بلافاصله پس از بالا آمدن تونل WireGuard از کار میافتد
DNS روی WireGuard به سه روش مختلف دچار اختلال میشود و هر کدام راهکار خاص خود را دارند. یا هیچ نامی ترجمه نمیشود، یا نامها ترجمه میشوند اما درخواستها خارج از تونل از سیستم شما خارج میشوند، یا مدیر resolver خودِ کلاینت، تنظیمات را چند ثانیه پس از شروع interface بازنویسی میکند. مشکل تقریباً هرگز خودِ تونل نیست. مشکل، آن خطی است که به کلاینت میگوید از کدام resolver بپرسد و مسیریابیای است که تعیین میکند بستهها به سمت آن resolver چگونه حرکت کنند.
WireGuard بستههای IP را جابهجا میکند و هیچ دانشی درباره DNS (سیستم نام دامنه، سرویسی که نامهایی مانند example.com را به آدرسهای IP تبدیل میکند) ندارد. خط DNS = در بلوک [Interface] کلاینت، یک تنظیم WireGuard نیست. این خط توسط wg-quick خوانده میشود؛ همان shell wrapper که interface را بالا میآورد و سپس wg-quick پیکربندی resolver کلاینت را در زمان فعال بودن تونل ویرایش کرده و در هنگام 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 باید peer را با یک latest handshake اخیر فهرست کند و هر دو ping باید پاسخ دهند. اگر ping 1.1.1.1 با timeout مواجه شد، شما با مشکل forwarding یا NAT (ترجمه آدرس شبکه) روبرو هستید، نه مشکل DNS، و هیچ مقدار تغییر در پیکربندی resolver کمکی نخواهد کرد. اگر pingها پاسخ میدهند اما با شروع ترافیک واقعی، throughput فرو میپاشد، این یک خطای جداگانه است و کند بودن WireGuard تقریباً همیشه به MTU برمیگردد، نه به هیچکدام از موارد این صفحه. تمام مثالهای اینجا از 10.8.0.0/24 به عنوان زیرشبکه تونل و 10.8.0.1 به عنوان آدرس تونل سرور استفاده میکنند. مقادیر خود را جایگزین کنید.
خطای اول: هیچچیزی resolve نمیشود، زیرا resolver هرگز پاسخ نمیدهد
نشانه دقیق است. دستور ping 1.1.1.1 کار میکند و دستور curl https://example.com خروجی زیر را برمیگرداند:
curl: (6) Could not resolve host: example.comمستقیماً از سمت کلاینت، tunnel resolver را پرسوجو کنید. ابزار 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 53 پاسخ نمیدهد.
دو دلیل برای این اتفاق وجود دارد. یا هیچ resolver روی سرور در حال اجرا نیست، یا فایروال سرور پیش از رسیدن پرسوجو، آن را مسدود میکند. هر دو مورد را روی سرور بررسی کنید.
sudo ss -ulnp | grep ':53'
sudo nft list rulesetیک resolver که در حال اجراست و بهدرستی bind شده، خطی شامل 10.8.0.1:53 یا 0.0.0.0:53 را نشان میدهد. در Ubuntu، معمولاً با 127.0.0.53:53 مواجه میشوید: این همان stub listener مربوط به systemd-resolved است که روی آدرس loopback قرار دارد و عمداً از ماشینهای دیگر غیرقابلدسترسی است. تنظیم کلاینت VPN روی سروری که تنها resolver آن همین stub است، دقیقاً منجر به این timeout میشود.
راهحل، استفاده از resolverای است که روی آدرس تونل گوش میدهد، به همراه یک قانون فایروال که به کلاینتها اجازه دسترسی به آن را میدهد.
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 همین کار را انجام میدهد. هرگز پورت 53 را برای اینترنت عمومی باز نکنید. یک recursive resolver باز، ظرف چند روز توسط اسکنرها پیدا شده و برای تقویت حملات denial of service استفاده میشود؛ ارائهدهنده خدمات شما پیش از خودتان متوجه این ترافیک خواهد شد.
دستور dig +short @10.8.0.1 example.com را دوباره از سمت کلاینت اجرا کنید. وجود یک آدرس در خروجی به این معنی است که مسیر resolver کار میکند و کلاینت اکنون فقط باید از آن استفاده کند. خط مربوطه را به بلوک [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، به دلیل عدم هدایت resolver در split tunnel
این مورد بدتر است، زیرا همهچیز بهظاهر درست کار میکند. نامها resolve میشوند، صفحات بارگذاری میشوند و پرسوجوها بهصورت متن آشکار (cleartext) از شبکهٔ محلی که قصد اعتماد به آن را نداشتید، عبور میکنند.
دو پیکربندی باعث بروز این مشکل میشوند. اولی، کلاینتی با AllowedIPs = 0.0.0.0/0, ::/0 و بدون خط DNS = است. wg-quick مسیر پیشفرض را در جدول مسیریابی خود نصب کرده و یک rule با suppress_prefixlength 0 اضافه میکند که مسیرهای محلی خاصتر را عمداً فعال نگه میدارد تا دستگاه همچنان بتواند به چاپگر خود دسترسی داشته باشد. resolverای که کلاینت از طریق DHCP یاد گرفته، معمولاً روتر در 192.168.1.1 است که با یکی از آن مسیرهای محلی مطابقت دارد. ترافیک شما از تونل عبور میکند، اما شبکهٔ محلی همچنان لیست کامل نامهایی که جستجو میکنید را دریافت میکند.
دومی یک split tunnel است: AllowedIPs = 10.8.0.0/24 با DNS = 9.9.9.9. از آنجا که 9.9.9.9 داخل AllowedIPs نیست، کلاینت مسیری به آن از طریق تونل ندارد؛ بنابراین پرسوجو دقیقاً مانند حالت اول، از طریق لینک محلی خارج میشود.
اثبات کنید کدام resolver واقعاً پاسخ میدهد. whoami.akamai.net یک نام تست عمومی است که با آدرس IP همان recursive resolver که پرسوجو را انجام داده پاسخ میدهد، بنابراین میتوانید پاسخ آن را با آدرس عمومی سرور خود مقایسه کنید.
resolvectl status
dig +short whoami.akamai.net
sudo tcpdump -ni any -c 10 port 53resolvectl status برای هر لینک یک بلوک چاپ میکند. اگر بلوک مربوط به لینک اترنت یا وایرلس شما همچنان 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/1610.8.0.1 داخل 10.8.0.0/24 قرار میگیرد، بنابراین پرسوجو رمزنگاری شده و به سرور ارسال میشود. اگر اصرار دارید از یک resolver عمومی در split tunnel استفاده کنید، آن را به عنوان یک host route اضافه کنید: AllowedIPs = 10.8.0.0/24, 9.9.9.9/32. بستهها سپس تونل میشوند، هرچند شبکهٔ محلی همچنان میتواند ببیند که شما آن ارائهدهنده را از نشستهای قبلی انتخاب کردهاید. resolverای که خودتان اجرا میکنید، این مسئله را منتفی میکند.
اختصاص resolver یکی از تفاوتهای قابلمشاهده میان WireGuard که بهصورت دستی ساخته شده است و یک mesh هماهنگشده محسوب میشود و بخشی از tradeoff مطرح در مقایسه WireGuard با Tailscale است. اجرای یک control server خودمیزبان Headscale این هماهنگی را بدون واگذاری key material شما به یک شخص ثالث فراهم میکند. اگر همین بخش پایانی باعث نگرانی شماست، توجه داشته باشید که Tailscale هرگز کلیدهای رمزکننده ترافیک شما را نگه نمیدارد و پرسش مهمتر این است که یک coordination server بهخطرافتاده یا یک حساب هویتی سرقتشده چه چیزی میتواند به شبکه شما اضافه کند.
شکست سوم: تداخل resolvconf و systemd-resolved در کلاینتهای لینوکسی
کلاینتهای macOS، ویندوز، iOS و اندروید تنظیمات DNS = را از طریق اپلیکیشن رسمی اعمال میکنند و مشکل چندانی ایجاد نمیکنند. در لینوکس، این تنظیمات توسط یک اسکریپت شل اعمال میشود که باید حدس بزند شما از کدامیک از چندین مدیریتکننده resolver استفاده میکنید.
شکست اول پر سروصدا است. sudo wg-quick up wg0 با خطای زیر متوقف میشود:
resolvconf: command not foundwg-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 را نشان میدهد، اما جستجوها همچنان به سمت resolver قدیمی میروند. سرویس systemd-resolved برای هر لینک یک لیست resolver جداگانه نگه میدارد و برای هر پرسوجو (query) یک لینک را انتخاب میکند. تا زمانی که یک لینک بهعنوان مسیر پیشفرض (default route) برای نامها علامتگذاری نشود، سیستم همچنان از resolver لینک وایرلس استفاده میکند، زیرا آن لینک دارای یک search domain است و لینک شما ندارد.
resolver را تنظیم کنید و در همان مرحله، مسیر پیشفرض را مطالبه کنید. %i به نام اینترفیس بسط داده میشود، بنابراین این بلوک روی هر اینترفیسی بدون تغییر کار میکند.
[Interface]
Address = 10.8.0.2/32
PostUp = resolvectl dns %i 10.8.0.1; resolvectl domain %i ~.
PostDown = resolvectl revert %iهنگامی که از PostUp به این روش استفاده میکنید، خط DNS = را حذف کنید؛ در غیر این صورت دو مکانیزم وضعیت resolver را مینویسند و تنها یکی از آنها پس از پایان کار، آن را پاکسازی میکند. آرگومان ~. بخش مهم ماجرا است: این آرگومان wg0 را بهعنوان دامنه مسیریابی برای هر نام علامتگذاری میکند، بنابراین systemd-resolved بهجای انتخاب لینک برای هر پرسوجو، تمام پرسوجوها را به آنجا میفرستد. آن را بررسی کنید.
resolvectl status wg0خروجی سالم شامل DNS Servers: 10.8.0.1 و Default Route: yes است. اگر Default Route مقدار no را نشان دهد، بخش resolvectl domain اجرا نشده است و شما دوباره به وضعیت انتخاب لینک بازگشتهاید.
یک مورد دیگر نیز ارزش ذکر کردن دارد. اگر /etc/resolv.conf یک فایل واقعی باشد و نه یک symlink به /run/systemd/resolve/stub-resolv.conf، یعنی چیز دیگری مالک آن است؛ معمولاً NetworkManager یا یک container runtime. پیش از عیبیابی هر چیز دیگری، ls -l /etc/resolv.conf را اجرا کنید، زیرا ابزاری که این فایل را در هر تغییر شبکه بازنویسی میکند، کار شما را در نامناسبترین زمان ممکن خنثی خواهد کرد.
ارتقا: استفاده از resolver فیلترکننده شخصی روی تونل
هنگامی که پرسوجوها (queries) بهطور مطمئن از طریق تونل منتقل میشوند، resolver در انتهای دیگر به یک نقطه کنترل تبدیل میشود. اجرای 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 را روی یک آدرس bind کنند و پردازش دوم با خطای listen udp 10.8.0.1:53: bind: address already in use خارج میشود.
اگر پیکربندی کلاینتها از قبل روی DNS = 10.8.0.1 تنظیم شده باشد، نیازی به تغییر ندارند. لاگ پرسوجوها اکنون تمام جستوجوهای هر peer را نشان میدهد که یک تصمیم جدی در زمینه حریم خصوصی است و نه فقط یک مزیت رایگان: شما اعتماد را از ارائهدهنده اینترنت خود به خودتان منتقل میکنید و مسئولیت بهروزرسانی و وصله کردن آن سرور نیز بر عهده شماست. سروری که در معرض اینترنت قرار دارد، ابتدا به رعایت اصول اولیه نیاز دارد و ده دقیقه اول روی یک VPS جدید این موارد را پوشش میدهد.
FAQ
چرا تونل WireGuard من متصل میشود اما نامها resolve نمیشوند؟
تونل فقط بستهها را منتقل میکند و هیچ نقشی در مدیریت نامها ندارد؛ بنابراین اگر تونل برقرار است اما جستجوی نامها با خطا مواجه میشود، به این معناست که resolver مورد نظر شما پاسخگو نیست. با استفاده از dig +short @10.8.0.1 example.com از سمت کلاینت تست کنید. دریافت پاسخ communication timed out به این معنی است که یا هیچ resolver روی آن آدرس تونل گوش نمیدهد (که اغلب به دلیل این است که stub مربوط به systemd-resolved فقط روی 127.0.0.53 bind شده است) و یا فایروال سرور بستههای UDP پورت 53 که به wg0 میرسند را مسدود میکند. ابتدا listener را اصلاح کنید و سپس پورت را فقط برای wg0 باز کنید.
چگونه بررسی کنم که آیا DNS من از طریق WireGuard نشت (leak) میکند؟
دستور sudo tcpdump -ni any -c 10 port 53 را روی کلاینت اجرا کنید و هنگام مرور وب، ستون interface را زیر نظر بگیرید. هر بسته باید روی wg0 دیده شود. اگر بستهها روی رابط بیسیم (wireless) یا اترنت شما ظاهر شوند، پرسوجوها به صورت متن آشکار (cleartext) ارسال میشوند. dig +short whoami.akamai.net نظر دوم را ارائه میدهد، زیرا با آدرس عمومی هر resolver بازگشتی (recursive resolver) که پرسوجو را انجام داده پاسخ میدهد؛ بنابراین اگر پاسخ دریافتی آدرس سرور شما نباشد، نشت DNS تأیید میشود.
آیا در صورت استفاده از split tunnel همچنان به خط DNS = نیاز دارم؟
بله، و آدرس resolver نیز باید درون AllowedIPs قرار داشته باشد، در غیر این صورت کلاینت مسیری به آن نخواهد داشت. با استفاده از AllowedIPs = 10.8.0.0/24، یک resolver در آدرس 10.8.0.1 تحت پوشش قرار میگیرد و پرسوجو رمزنگاری میشود. یک resolver عمومی مانند 9.9.9.9 تحت پوشش نیست، بنابراین پرسوجو از طریق لینک محلی ارسال میشود، حتی اگر خط DNS درست به نظر برسد.
چرا با اینکه resolvectl سرور درست را نشان میدهد، جستجوها به جای دیگری میروند؟
systemd-resolved برای هر لینک یک لیست resolver جداگانه نگه میدارد و برای هر پرسوجو یک لینک را انتخاب میکند؛ بنابراین یک ورودی صحیح در wg0 نادیده گرفته میشود اگر لینک دیگری مسیر پیشفرض برای نامها را در اختیار داشته باشد. عبارت PostUp = resolvectl dns %i 10.8.0.1; resolvectl domain %i ~. را به بلوک [Interface] در کلاینت اضافه کنید و خط DNS = را حذف نمایید. پس از آن resolvectl status wg0 باید Default Route: yes را گزارش دهد.
وقتی چندین کلاینت دچار مشکل هستند، کدام را ابتدا اصلاح کنم؟
یک کلاینت Linux را اصلاح کنید، زیرا تنها پلتفرمی است که مکانیزم عملکرد را به شما نشان میدهد. resolvectl status و tcpdump به شما میگویند کدام resolver پاسخ داده و کدام رابط، بسته را حمل کرده است. اپلیکیشنهای موبایل و دسکتاپ همان مقادیر DNS و AllowedIPs را بدون نمایش جزئیات فنی اعمال میکنند؛ بنابراین وقتی کلاینت Linux را اصلاح کردید، در واقع در حال کپی کردن پیکربندیای هستید که قبلاً صحت آن را اثبات کردهاید.