SSD Nodes Learn Hosting plans →
מדריכים Matt Connorמאת Matt Connor · עודכן 2026-10-25

פתרון בעיות DNS ב-WireGuard: שלושה כשלים נפוצים

החיבור ל-WireGuard פעיל אך שמות לא מתפענחים או דולפים החוצה? גלו כיצד לזהות ולתקן את שלושת הכשלים הנפוצים בהגדרות ה-DNS, בניתוב החבילות ובמנהלי ה-resolver של הלקוח.

מדוע ה־DNS מפסיק לעבוד ברגע שמתבצע חיבור למנהרת WireGuard

כשל ב־DNS מעל WireGuard מתרחש בשלוש דרכים, ולכל אחת פתרון משלה. לעיתים שום דבר לא מתבצע רזולוציה, לעיתים השמות מתורגמים אך השאילתות יוצאות מהמכונה מחוץ למנהרה, ולעיתים מנהל ה־resolver של הלקוח דורס את ההגדרה שניות לאחר עליית הממשק. המנהרה כמעט לעולם אינה הבעיה. הבעיה טמונה בשורה אחת שמורה ללקוח לאיזה resolver לפנות, ובניתוב שקובע כיצד חבילות המידע מגיעות לאותו resolver.

WireGuard מעביר חבילות IP ואינו מכיר את ה־DNS (מערכת שמות מתחם, השירות שהופך שמות כמו example.com לכתובות IP). השורה DNS = בבלוק [Interface] של הלקוח אינה הגדרה של WireGuard. היא נקראת על ידי wg-quick, מעטפת ה-shell שמעלה את הממשק, ולאחר מכן 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 עדכני, ושני ה-pings צריכים לקבל מענה. אם ping 1.1.1.1 מסתיים ב-timeout, סביר להניח שיש לכם בעיית forwarding או NAT (תרגום כתובות רשת) ולא בעיית DNS, ושום שינוי בהגדרות ה-resolver לא יועיל. firewall שחוסם ICMP יגרום לאותו timeout, לכן אשרו זאת עם curl -sI https://1.1.1.1 לפני שתתחילו לשנות חוקי forwarding. אם ה-pings עונים אך קצב העברת הנתונים קורס ברגע שמתחילה תעבורה אמיתית, מדובר בבעיה נפרדת, ו-ביצועים איטיים ב-WireGuard נובעים כמעט תמיד מ-MTU ולא משום דבר שמופיע בדף זה. כל דוגמה כאן משתמשת ב-10.8.0.0/24 כרשת המשנה של המנהרה וב-10.8.0.1 ככתובת המנהרה של השרת. החליפו אותם בערכים שלכם.

כשל ראשון: שום דבר לא מתבצע, כיוון שה־resolver לעולם אינו עונה

התסמין מדויק. ping 1.1.1.1 עובד, ו־curl https://example.com מחזיר את התוצאה הבאה:

curl: (6) Could not resolve host: example.com

בצעו שאילתה ל־resolver של ה־tunnel ישירות מהלקוח. 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 53.

שתי סיבות גורמות לכך. או שאין resolver שרץ על השרת, או שחומת האש של השרת חוסמת את השאילתה לפני שהיא מגיעה. בדקו את שניהם בשרת.

sudo ss -ulnp | grep ':53'
sudo nft list ruleset

resolver שרץ ומוגדר נכון יציג שורה עם 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, בתוספת חוק firewall אחד שמאפשר לעמיתים להגיע אליו.

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'

לאחר מכן פתחו את הפורט עבור תעבורת ה-tunnel בלבד. ב-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 לאינטרנט הציבורי. סורקים ימצאו resolver רקורסיבי פתוח בתוך ימים וישתמשו בו כדי להגביר התקפות מניעת שירות (DoS), והספק שלכם יבחין בתעבורה הזו לפניכם.

הריצו שוב את 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, כיוון ש־split tunnel אינו מנתב את ה־resolver

מצב זה חמור יותר, כיוון שהכול נראה תקין. שמות מתורגמים, דפים נטענים, והשאילתות עוברות בטקסט גלוי ברשת המקומית שאין ברצונכם לבטוח בה.

שתי תצורות גורמות לכך. הראשונה היא לקוח עם AllowedIPs = 0.0.0.0/0, ::/0 ללא שורת DNS =. wg-quick מתקין את נתיב ברירת המחדל בטבלת הניתוב שלו ומוסיף חוק עם 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 53

resolvectl status מדפיס בלוק אחד לכל חיבור. אם הבלוק עבור חיבור ה-ethernet או ה-wireless שלכם עדיין מציג Current DNS Server: 192.168.1.1 בעוד הבלוק של wg0 אינו מציג דבר, זוהי הדליפה. dig +short whoami.akamai.net שמחזיר את כתובת הפס הרחב הביתית שלכם במקום את כתובת השרת מאשר זאת מהצד המרוחק. השורה tcpdump היא ההוכחה שסוגרת את הדיון: פלט תקין מעביר כל חבילת port 53 שיוצאת מהמכונה דרך wg0, ודליפה מעבירה אותן דרך wlan0 או enp3s0. חבילות ב-lo אל או מ-127.0.0.53 הן יישומים המדברים עם ה-stub המקומי של 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, כך שהשאילתה מוצפנת ונשלחת לשרת. אם אתם מתעקשים על resolver ציבורי ב-split tunnel, הוסיפו אותו כ-host route: AllowedIPs = 10.8.0.0/24, 9.9.9.9/32. החבילות עוברות אז במנהרה, אם כי הרשת המקומית עדיין יכולה לראות שבחרתם בספק זה מתוך סשנים קודמים. resolver שאתם מריצים בעצמכם מונע את הבעיה הזו.

הקצאת resolver היא אחד ההבדלים הנראים לעין בין WireGuard שנבנה ידנית לבין רשת מתואמת (mesh), וזהו חלק מהפשרה ב-השוואה בין WireGuard ל-Tailscale. הרצה של שרת בקרה עצמי מסוג Headscale מעניקה לכם את התיאום הזה מבלי למסור את חומרי המפתח שלכם לצד שלישי. אם המשפט האחרון הוא מה שמדאיג אתכם, שימו לב ש-Tailscale לעולם אינה מחזיקה במפתחות שמצפינים את התעבורה שלכם, והשאלה החדה יותר היא מה שרת תיאום שנפרץ או חשבון זהות שנגנב יכולים להוסיף לרשת שלכם.

כשל שלישי: התנגשות בין resolvconf לבין systemd-resolved בלקוחות Linux

לקוחות macOS, Windows, iOS ו-Android מחילים את DNS = דרך האפליקציה הרשמית וכמעט אינם גורמים לבעיות. ב-Linux, ההגדרה מוחלת על ידי סקריפט shell שצריך לנחש איזה מנהל resolver מותקן אצלכם.

הכשל הראשון הוא רועש. 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, אך שאילתות עדיין מגיעות ל-resolver הישן. systemd-resolved אינו מתעלם מ-wg0. שם שאינו תואם לאף domain ניתוב נשלח לשרתי ה-DNS של כל ממשק שנחשב ל-default route, וממשק עם שרתי DNS ללא route-only domain נחשב לכזה כברירת מחדל. לכן, השאילתה נשלחת ל-10.8.0.1 ולנתב של החיבור האלחוטי בו-זמנית, והתשובה הראשונה שמתקבלת מנצחת. הנתב נמצא במרחק hop אחד ובדרך כלל עונה ראשון, והשאילתה בכל מקרה יצאה בטקסט גלוי. שמות תחת ה-search domain של החיבור האלחוטי עצמו, כמו lan, הולכים רק לאותו חיבור, כיוון שה-domain הספציפי ביותר מנצח.

כאשר wg-quick מחיל את DNS = דרך ה-wrapper של systemd, כלומר resolvconf, הוא כבר מבקש catch-all routing domain, לכן כשל זה מופיע בעיקר כאשר מימוש אחר של resolvconf או מנהל רשת החיל את ההגדרה. הגדרה מפורשת מסירה את הצורך בניחושים.

הגדירו את ה-resolver ודרשו את ה-catch-all routing domain באותו שלב. %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 בדרך זו, כיוון שאחרת שני מנגנונים כותבים את מצב ה-resolver ורק אחד מהם מנקה אחריו. הארגומנט ~. הוא החלק החשוב: הוא הופך את wg0 ל-route-only domain עבור כל שם, כך ש-systemd-resolved מפסיק לשלוח שמות שאין להם domain ספציפי יותר לחיבורים האחרים. שמות תחת ה-domain של חיבור אחר, כמו lan, עדיין יופנו לאותו חיבור, וזה בדרך כלל מה שנדרש עבור מארחים מקומיים. ודאו זאת.

resolvectl status wg0

פלט תקין מכיל את DNS Servers: 10.8.0.1 ואת DNS Domain: ~.. אם ~. חסר, החלק של resolvectl domain לא רץ, ו-wg0 חזר להתחרות מול החיבורים האחרים. אל תשתמשו בדגל ה-default route כבדיקה: הוא קורא yes (או +DefaultRoute בשורת Protocols, תלוי בגרסת systemd) גם ללא ~., כיוון שממשק ללא route-only domain הוא בכל מקרה default route.

מקרה נוסף שראוי לציין: אם /etc/resolv.conf הוא קובץ אמיתי ולא קישור סימבולי ל-/run/systemd/resolve/stub-resolv.conf, משהו אחר שולט בו, בדרך כלל NetworkManager או container runtime. הריצו את ls -l /etc/resolv.conf לפני שאתם מנפים שגיאות אחרות, כיוון שכלי שכותב מחדש את הקובץ הזה בכל שינוי רשת יבטל את עבודתכם ברגע הכי פחות נוח.

השדרוג: פותר (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 באותה כתובת ו-AdGuard Home יקרוס עם 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 בלקוח ועקבו אחר עמודת ה-interface בזמן הגלישה. כל חבילה שעוזבת את המכונה צריכה לעבור ב-wg0; חבילות ב-lo אל או מ-127.0.0.53 הן ה-stub המקומי של systemd-resolved והן תקינות. אם הן מופיעות בממשק ה-wireless או ה-ethernet שלכם, השאילתות יוצאות בטקסט גלוי. dig +short whoami.akamai.net מספק חוות דעת שנייה, מכיוון שהוא משיב עם הכתובת הציבורית של ה-recursive resolver שביצע את השאילתה, כך שתשובה שאינה הכתובת של השרת שלכם מאשרת את הדליפה.

האם אני זקוק לשורת DNS = אם אני משתמש ב-split tunnel?

כן, וכתובת ה-resolver חייבת גם היא להימצא בתוך AllowedIPs, אחרת ללקוח אין נתיב אליה. עם AllowedIPs = 10.8.0.0/24, ה-resolver ב-10.8.0.1 מכוסה והשאילתה מוצפנת. resolver ציבורי כגון 9.9.9.9 אינו מכוסה, לכן השאילתה יוצאת דרך החיבור המקומי למרות ששורת ה-DNS נראית נכונה.

מדוע resolvectl מציג את השרת הנכון אך השאילתות הולכות למקום אחר?

systemd-resolved שולח שם שאינו תואם לאף routing domain לכל חיבור עם default-route בו-זמנית, כולל wg0, ומחזיר את התשובה המוצלחת הראשונה, שמגיעה בדרך כלל מהנתב המקומי. הוסיפו את PostUp = resolvectl dns %i 10.8.0.1; resolvectl domain %i ~. לבלוק ה-[Interface] בלקוח והסירו את שורת ה-DNS =. לאחר מכן resolvectl status wg0 אמור לדווח על DNS Domain: ~., וכל שם שאף חיבור אחר אינו תובע עם domain ספציפי יותר יופנה רק ל-wg0.

איזה לקוח עלי לתקן ראשון כאשר מספר לקוחות אינם תקינים?

תקנו לקוח Linux אחד, מכיוון שזו הפלטפורמה היחידה שמציגה לכם את המנגנון. resolvectl status ו-tcpdump מראים לכם איזה resolver השיב ואיזה ממשק נשא את החבילה. אפליקציות לטלפון ולמחשב שולחני מיישמות את אותם ערכי DNS ו-AllowedIPs ללא תשתית גלויה, כך שברגע שלקוח ה-Linux תקין, אתם מעתיקים תצורה שכבר הוכחתם.

האם המאמר הזה היה מועיל?