תיקון DNS דרך WireGuard: שלוש תקלות נפוצות
ה-tunnel של WireGuard פעיל, אך שמות אינם נפתרים או ששאילתות DNS דולפות לנתב המקומי. זהו את אחת משלוש התקלות ותקנו אותה.
מדוע DNS מפסיק לפעול ברגע ש-tunnel של WireGuard עולה
DNS דרך WireGuard נכשל בשלוש דרכים, ולכל אחת מהן יש תיקון משלה. לפעמים שום דבר אינו נפתר. לפעמים השמות נפתרים, אך השאילתות יוצאות מהמחשב מחוץ ל-tunnel. לפעמים מנהל ה-resolver של הלקוח עצמו מחליף את ההגדרה כמה שניות לאחר הפעלת הממשק. ה-tunnel כמעט אף פעם אינו הבעיה. הבעיה היא השורה שמציינת לאיזה resolver הלקוח ישלח את השאילתה, והניתוב שקובע כיצד המנות יגיעו לאותו resolver.
WireGuard מעביר מנות IP ואינו מכיר DNS (מערכת שמות המתחם, השירות שממיר שמות כגון example.com לכתובות IP). השורה DNS = בתוך בלוק [Interface] של לקוח אינה הגדרה של WireGuard. היא נקראת על ידי wg-quick, מעטפת ה-shell שמעלה את הממשק, ו-wg-quick עורך לאחר מכן את תצורת ה-resolver של הלקוח בזמן שה-tunnel פעיל ומשחזר אותה בעת wg-quick down. לכן כל בעיה להלן היא בעיית ניתוב או בעיית wg-quick, ולעולם אינה בעיית הצפנה. אם ה-tunnel עצמו עדיין לא הוקם, התחילו ב-הקמת VPN עצמאי של WireGuard ב-VPS שבבעלותכם וחזרו לדף זה לאחר מכן.
ודאו שה-tunnel תקין לפני שתבצעו שינוי כלשהו ב-DNS.
sudo wg show
ping -c 3 10.8.0.1
ping -c 3 1.1.1.1wg show אמור להציג את ה-peer עם latest handshake עדכני, ושתי פקודות ה-ping אמורות לקבל תשובה. אם ping 1.1.1.1 מסתיים ב-timeout, מדובר בבעיית forwarding או NAT (תרגום כתובות רשת), ולא בבעיית DNS. שום כמות של שינויי תצורת resolver לא תפתור זאת. בכל הדוגמאות כאן נעשה שימוש ב-10.8.0.0/24 כרשת המשנה של ה-tunnel וב-10.8.0.1 ככתובת ה-tunnel של השרת. החליפו אותן בערכים שלכם.
כשל אחד: שום דבר אינו נפתר, מכיוון שה־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הפקודה הראשונה מחזירה כתובת, ולכן מוכיחה שמנות מגיעות לאינטרנט דרך ה־tunnel. הפקודה השנייה אינה מחזירה דבר ומדפיסה ;; communication timed out; no servers could be reached. זו כל האבחנה: הלקוח שלך מוגדר להשתמש ב־10.8.0.1, ו־10.8.0.1 אינו משיב ב־UDP port 53.
שני גורמים אפשריים לכך. ייתכן שאין resolver שפועל בשרת, או שחומת האש של השרת משליכה את השאילתה לפני שהיא מגיעה אליו. בדוק את שני המצבים בשרת.
sudo ss -ulnp | grep ':53'
sudo nft list rulesetResolver שפועל ומאזין כראוי מציג שורה הכוללת 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 שמאזין בכתובת ה־tunnel, וכן כלל אחד בחומת האש שמאפשר לעמיתים לגשת אליו.
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'לאחר מכן פתח את ה־port עבור תעבורת ה־tunnel בלבד. עם nftables, הוסף את שתי השורות האלה ל־chain 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 לאינטרנט הציבורי. סורקים מאתרים resolver רקורסיבי פתוח בתוך ימים ומשתמשים בו להגברת מתקפות מניעת שירות, וספק השירות שלך יבחין בתעבורה הזאת לפניך.
הרץ שוב את 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, משום שמנהור מפוצל אינו מנתב את פותר השמות
הכשל הזה חמור יותר, משום שהכול נראה תקין. שמות נפתרים, דפים נטענים, והשאילתות עוברות בטקסט גלוי ברשת המקומית שלא רצית לסמוך עליה.
שתי תצורות גורמות לכך. הראשונה היא לקוח עם 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 53resolvectl 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/1610.8.0.1 נמצא בתוך 10.8.0.0/24, ולכן השאילתה מוצפנת ונשלחת לשרת. אם אתה מתעקש להשתמש בפותר שמות ציבורי במנהור מפוצל, הוסף אליו נתיב למארח: AllowedIPs = 10.8.0.0/24, 9.9.9.9/32. החבילות יעברו אז במנהרה, אך הרשת המקומית עדיין תוכל לראות שבחרת בספק הזה מתוך הפעלות קודמות. פותר שמות שאתה מפעיל בעצמך מונע את הבעיה.
הקצאת פותר השמות היא אחד ההבדלים הגלויים בין WireGuard שנבנה ידנית לבין רשת Mesh מתוזמרת. זהו חלק מהפשרה המתוארת ב-WireGuard בהשוואה ל-Tailscale. הפעלת שרת בקרה עצמאי של Headscale מספקת את התיאום הזה בלי למסור את חומר המפתחות שלך לצד שלישי.
כשל שלישי: resolvconf ו-systemd-resolved מתחרים על השליטה בלקוחות Linux
לקוחות macOS, Windows, iOS ו-Android מחילים את DNS = באמצעות האפליקציה הרשמית וגורמים למעט בעיות. ב-Linux ההגדרה מוחלת באמצעות סקריפט מעטפת שצריך לזהות באיזה ממנהלי פותרי השמות אתה משתמש.
הכשל הראשון בולט מיד. 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, ובכל זאת החיפושים עדיין נשלחים לפותר השמות הישן. 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 מסנן משלכם דרך המנהרה
לאחר שהשאילתות עוברות באופן אמין דרך המנהרה, הפותר בצד המרוחק הופך לנקודת בקרה. הפעלת AdGuard Home בצד זה מספקת לכל מכשיר מחובר סינון באמצעות רשימות חסימה ויומן שאילתות, ללא תוכנת לקוח וללא הגדרה נפרדת לכל מכשיר. סקריפט ההתקנה הרשמי, שנבדק ביולי 2026, הוא שורה אחת.
curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -vאשף ההגדרה מאזין ב-port 3000 בהפעלה הראשונה. גשו אליו דרך המנהרה בכתובת http://10.8.0.1:3000 במקום לפתוח את ה-port לציבור, ובאשף הגדירו גם את כתובת ההאזנה של DNS וגם את כתובת ההאזנה של הניהול ל-10.8.0.1. אם unbound מהכשל הראשון עדיין מחזיק באותה כתובת, עצרו אותו תחילה באמצעות sudo systemctl disable --now unbound, מכיוון ששני תהליכים אינם יכולים לבצע bind ל-UDP port 53 באותה כתובת, והתהליך השני יוצא עם listen udp 10.8.0.1:53: bind: address already in use.
אין צורך לשנות את תצורות הלקוחות אם הן כבר מציינות DNS = 10.8.0.1. יומן השאילתות יציג כעת כל חיפוש מכל עמית. זו החלטת פרטיות ממשית ולא יתרון ללא עלות: אתם מעבירים את האמון מספק האינטרנט שלכם אל עצמכם, ואתם האחראים לשמור על השרת מעודכן בתיקוני אבטחה. שרת החשוף לאינטרנט זקוק תחילה לאמצעי ההגנה הבסיסיים, והמאמר עשר הדקות הראשונות ב-VPS חדש מפרט אותם.
FAQ
מדוע מנהרת WireGuard מתחברת, אך שמות אינם נפתרים?
המנהרה מעבירה מנות ואינה מטפלת בשמות כלל. לכן, מנהרה תקינה עם חיפושים כושלים מצביעה על כך שה־resolver שאליו אתם מפנים אינו משיב. בדקו באמצעות dig +short @10.8.0.1 example.com מצד הלקוח. תשובת communication timed out משמעותה שאף resolver אינו מאזין בכתובת המנהרה, לעיתים משום ש־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 מספק בדיקה נוספת, משום שהוא משיב בכתובת הציבורית של ה־recursive resolver שטיפל בשאילתה. לכן, תשובה שאינה הכתובת של השרת שלכם מאשרת את הדליפה.
האם דרושה לי השורה DNS = אם אני משתמש במנהרת split?
כן. כתובת ה־resolver חייבת להימצא גם בתוך AllowedIPs, אחרת אין ללקוח נתיב אליה. עם AllowedIPs = 10.8.0.0/24, resolver בכתובת 10.8.0.1 נכלל בטווח והשאילתה מוצפנת. Resolver ציבורי כגון 9.9.9.9 אינו נכלל בטווח, ולכן השאילתה יוצאת דרך הקישור המקומי, אף שהשורה DNS נראית תקינה.
מדוע resolvectl מציג את השרת הנכון, אך החיפושים עדיין נשלחים למקום אחר?
systemd-resolved מחזיק רשימת resolvers נפרדת לכל קישור ובוחר קישור לכל שאילתה. לכן, ערך תקין ב־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 תקין, אתם מעתיקים תצורה שכבר הוכחה.