מדוע resolv.conf מציג את ה-DNS של ה-VPN שלכם אבל חיפושים מתעלמים ממנו
במארח עם resolved הקובץ הוא תצוגה, לא המצב עצמו. עקבו אחרי ה-stub, השרתים לכל קישור ושורת ה-nsswitch כדי לראות מה חיפוש באמת משתמש בו.
שום דבר ביומנים לא נראה שגוי: הממשק פעיל, הפותר מדווח על שרת ה-DNS של ה-VPN, והקובץ בדיסק מפרט אותו. בכל זאת שם מארח פנימי עדיין נפתר דרך הנתב המקומי. שלוש הקביעות אינן סותרות זו את זו, מפני שהקובץ, המצב לכל קישור ונתיב החיפוש הם אובייקטים שונים שמקרה גרם להם לחלוק שם. להלן הנתיב ששאילתה באמת עוברת במארח עם systemd-resolved.
שלושה אובייקטים בשם resolv.conf
במארח עם resolved, /etc/resolv.conf הוא בדרך כלל קישור סמלי אל /run/systemd/resolve/stub-resolv.conf. היעד הזה מחזיק את הכתובת של מאזין stub מקומי, 127.0.0.53, בתוספת דומיינים לחיפוש שחישב resolved. זו תצוגה של המצב, לא המצב עצמו.
המצב חי בתצורה של resolved לכל קישור, ולכן resolvectl status יכול לחלוק על הקובץ ועדיין להיות צודק. כל קישור נושא את השרתים שלו ואת דומיינים לניתוב שלו, וה-stub מתייעץ בנתונים האלה כששאילתה מגיעה. המדריך של systemd-resolved מתאר את הקבצים שנוצרים ואת המודל לכל קישור; ההפרדה בין תצוגה למצב היא החלק שכדאי לזכור. שינוי היעד של הקישור הסמלי משנה את מה שלקוחות מסורתיים קוראים, לא את מה שהפותר יודע.
אובייקט שלישי, /run/systemd/resolve/resolv.conf, משטח כל קישור לרשימת שרתים אחת. תוכנית שמצביעה על הקובץ הזה שולחת שאילתות ישירות לשרתים שברשימה ומדלגת על ה-stub, ולכן המדיניות לכל קישור כבר לא חלה עליה. לכן שתי תוכניות באותה מכונה יכולות לענות אחרת לאותו שם, ואף אחת מהן אינה שבורה.
עקבו אחרי חיפוש אחד דרך NSS
glibc קורא את /etc/nsswitch.conf כדי להחליט מי עונה לשם. שורת hosts שמכילה resolve מנתבת את השאלה אל nss-resolve, ששואל את resolved דרך D-Bus ומקבל את התשובה לכל קישור. שורה עם files dns בלבד שולחת את השאילתה לכתובת ש-/etc/resolv.conf מחזיק.
השורה האחת הזו מסבירה את רוב המחלוקות בין דפדפן ל-dig. dig קורא את resolv.conf ישירות ולא נוגע ב-NSS לעולם, ולכן הוא בודק את ה-stub או שרת במעלה הזרם ולא את הנתיב שהאפליקציה משתמשת בו. getent hosts internal.example עובר דרך NSS, והשוואת התשובה שלו לזו של dig היא המדידה השימושית הראשונה.
אפליקציות שמובילות פותר משלהן, או מדברות DNS על HTTPS עם נקודת קצה קבועה, עוקפות את שני הנתיבים. שום דבר ב-resolv.conf או במצב של resolved לא מגביל אותן.
בדקו מי הבעלים של הקובץ ולאן הוא מצביע
קראו את שרשרת הקישורים לפני שמשנים משהו, כי הבעלות קובעת איזה קובץ הוא הסמכותי. כל פקודה למטה רק קוראת מצב.
stat -c '%N' /etc/resolv.conf
resolvectl status --no-pager
grep '^hosts' /etc/nsswitch.conf
ls -l /run/systemd/resolve/
השורה הראשונה מדפיסה את הקישור ואת היעד שלו יחד, וקובץ רגיל שבבעלות סקריפט VPN פירושו שהפותר לעולם לא מתייחס לכתיבה הזו כקלט. פלט המצב מפרט שרתים לכל קישור בתוספת דומיינים לניתוב שקובעים לאן כל שאילתה הולכת. שורת nsswitch אומרת אם ה-stub נשאל בכלל, ולכן כתובת stub בקובץ בלי resolve שם פירושה ששאילתות מגיעות למאזין המקומי בעוד ששום דבר לא מנהל את הפיצול. גם הרשימה האחרונה חשובה, מפני שמארח בלי stub-resolv.conf לא מריץ את הסידור המתואר כאן.
אם השרשרת מסתיימת בקובץ שמנוהל על ידי חבילה אחרת, לקוח ה-VPN והחבילה הזו הם שני הבעלים שצריך ליישב. החלפת הקישור משליכה את העבודה של בעלים אחד ומשאירה את זו של האחר במקומה.
תקנו אצל בעל הקישור
חיבור VPN צריך לרשום את השרתים ואת הדומיינים שלו על הקישור שלו, ואז למשוך אותם בניתוק. אינטגרציית resolved של NetworkManager והעוזר של הלקוח עצמו פועלים כך; סקריפט שרק כותב מחדש את resolv.conf לא.
בקישור שכבר קיים, ההגדרות בזמן ריצה מראות את המנגנון. resolvectl dns tun0 10.40.0.53 מצרף שרת, ו-resolvectl domain tun0 '~corp.example' מצרף דומיין לניתוב. הטילדה היא התו הנושא את המשקל: היא מגבילה שאילתות לאותו סיומת לקישור הזה ומשאירה כל השאר בשקט, בעוד אותו ערך בלעדיה הופך לדומיין חיפוש והפיצול מתאדה. הכתובות האלה הן דוגמאות מעבדה, לא תצורה קבועה. אשרו עם resolvectl query host.corp.example וקראו איזה קישור ענה.
שרת רשום עדיין צריך נתיב. כשהשאילתה מגיעה לקישור הנכון ופוקעת, התקלה היא בנגישות דרך המנהרה ולא בבעלות הפותר.
איך נראה מצב עובד
תוצאה בריאה עקבית בכל שלוש התצוגות: השרתים לכל קישור תואמים למה שה-VPN חילק, הדומיינים לניתוב מכסים רק סיומות פנימיות, והאפליקציה החשובה פותרת שם פנימי בעוד שם ציבורי עדיין הולך בנתיב המקומי. שאילתה מוצלחת אחת מוכיחה פחות מההסכמה הזו.
אחר כך התנתקו וחזרו על שתי השאילתות. לקוח שמשאיר את הדומיינים שלו רשומים אחרי הפירוק יוצר מכונה שנכשלת בחיפושים פנימיים שעות אחר כך, בלי מנהרה פתוחה ובלי סיבה גלויה.