למה שמות DNS פרטיים נכשלים בלקוחות VPN ואיפה כדאי לבדוק
שמות פרטיים נפתרים רק כשהלקוח סומך על הפותר שלכם, הסיומת מוגבלת והתשובה יכולה לחזור דרך המנהרה.
אתם פותחים מחשב נייד בחדר מלון, מפעילים את הלקוח, מקלידים את שם שרת הקבצים הפנימי ולא מקבלים דבר. המנהרה מדווחת שמחוברים, ופינג לכתובת באותה תת-רשת עדיין עונה, כלומר התעבורה עצמה תקינה. רק השם נכשל, והפער הזה מצמצם את הבעיה לשני מקומות: באיזה פותר שאל הלקוח והאם התשובה שקיבל יכולה לחזור דרך המנהרה. תקנו אחד ותדלגו על השני, והתקלה רק תעבור מקום.
לפני עריכת פרופיל כלשהו, ודאו מה הלקוח עושה עם השם. ב-Linux, resolvectl query files.corp.example מראה איזה קישור ואיזה פותר יצרו את התשובה. ב-Windows, Resolve-DnsName files.corp.example מראה איזה שרת השיב ואיזו כתובת הוא החזיר.
קראו את התשובה לפני שאתם משנים משהו
אם השם חוזר כ-NXDOMAIN בתוך כמה אלפיות שנייה, השאילתה מעולם לא הגיעה לאזור שלכם ופותר ציבורי או של המלון ענה במקומה. אם הוא חוזר אחרי השהיה ארוכה, משהו בדרך מפיל את פורט UDP 53 והלקוח נסוג לבסוף לחלופה. אם הוא עונה בכתובת הנכונה אבל החיבור עדיין נתקע, הפתרון תקין והבעיה שלכם היא בניתוב או בשירות עצמו.
החלוקה הזו לשלושה חוסכת שעה של ניחושים. היא גם אומרת אם בכלל צריך לגעת ב-VPN: שם שנפתר לכתובת פרטית נכונה כבר הוכיח את מסלול הפותר, ולכן העבודה שנותרה נמצאת במסלול הנתונים.
חלקו את הפותר מתוך המנהרה
הלקוחות מתחלקים לשתי קבוצות. לקבוצה אחת השרת יכול לתת פותר בזמן הקמת החיבור; האחרת שומרת את ההגדרה בקובץ מקומי שאף שער לא יכול לשנות מרחוק.
OpenVPN נמצא בקבוצה הראשונה. בשרת, push "dhcp-option DNS 10.8.0.53" ו-push "dhcp-option DOMAIN corp.example" יורדים דרך ערוץ הבקרה, אבל רק אם בקונפיגורציית הלקוח pull עדיין מופעל. לקוח שנערך ביד ונושא pull-filter ignore "dhcp-option" לעולם לא יראה אותם, והשורה האחת הזו מסבירה מספר מפתיע של מקרים של «השרת דוחף את זה אבל המחשב שלי לא מסכים».
WireGuard נמצא בקבוצה השנייה, כי לפרוטוקול אין שום משא ומתן על אפשרויות. הפותר ודומיין החיפוש נכנסים לבלוק [Interface] של הלקוח עצמו בתור DNS = 10.8.0.53, corp.example. wg-quick מחיל זאת דרך resolvconf או systemd-resolved, וב-Windows הלקוח הרשמי מתקין כללי NRPT שקיימים רק כל עוד המנהרה למעלה: Get-DnsClientNrptPolicy מציג אותם, ולכן זו דרך מהירה לראות אם הלקוח אי פעם החל את הקובץ שלכם.
IPsec/IKEv2 נמצא באמצע. תוסף attr של strongSwan יכול להחזיר שרת DNS שנלקח ממאגר, ולקוח Windows בדרך כלל מקבל אותו, אבל פרופיל שמקבע את שרת השמות שלו מנצח כל מה שהשער מציע. בלקוח Linux הצעד הידני המקביל הוא resolvectl dns wg0 10.8.0.53 ואחריו resolvectl domain wg0 '~corp.example'; שניהם נעלמים יחד עם הממשק, וזה בדיוק מה שרוצים בהגדרה שמוגבלת למנהרה.
הגבילו את הסיומת במקום לבלוע כל שאילתה
להפנות את כל רשימת הפותרים של הלקוח לשרת הפנימי שלכם זה קל ובדרך כלל שגוי. אז כל שם ציבורי נפתר דרך היציאה של מרכז הנתונים שלכם, ה-CDN מחזירים כתובות רחוקות, ותקלה אחת של הפותר גוררת איתה גם את הגלישה של המשתמש.
שלחו פנימה רק את הסיומת הפרטית. ב-systemd-resolved, דומיין שמתחיל ב-~ הוא לניתוב בלבד, ולכן ~corp.example אומר שהשאילתות מתחת לסיומת הזו הולכות לשרתים של אותו קישור בעוד כל השאר ממשיך להשתמש ברשת הפיזית. Windows עושה את אותו דבר בכללי NRPT שמוגבלים למרחב שמות, ו-macOS בקובץ פותר משלים תחת /etc/resolver/.
שמות multicast ראויים לתשובה משלהם. שמות .local הם link-local לפי התכנון (RFC 6762) וממשק tun מנקודה לנקודה לא נושא את קבוצת ה-multicast הזו, ולכן הוספת פותר ציבורי לא תפרסם אותם, ושאלה לפותר פנימי מסוג unicast עליהם מחזירה NXDOMAIN. משקף כמו avahi במצב שיקוף יכול לגשר בין שני מקטעים, אבל זו החלטה בצד השרת שאין לקוח שיכול לדרוש אותה. אם מדפסת או NAS חייבים להיות נגישים לפי שם, תנו להם רשומת A באזור שלכם.
הוכיחו שהתשובה יכולה לחזור
תשובה נכונה שמצביעה על כתובת שאינה נגישה נראית בדיוק כמו בעיית פותר עד שתבדקו את המסלול. שאלו את הליבה לאן התשובה תלך: ip route get 10.20.5.20 נוקב בשם הממשק, ובדרך שימושית יותר, בכתובת המקור שהוא ישתמש בה.
עקבו אחרי כתובת הפותר עצמה. לקוח שיש לו DNS = 10.8.0.53 לצד AllowedIPs = 10.20.0.0/16 שולח את השאילתות שלו החוצה דרך כרטיס הרשת הפיזי, ושם הן מתות בשקט, כי הפותר אינו בתוך אף קידומת שהמנהרה תובעת. אי ההתאמה הזה הוא הכשל הנפוץ ביותר עם סיבה אחת בכל התחום הזה, והוא בלתי נראה אלא אם תשוו את הגדרת ה-DNS לקידומות המותרות שורה אחר שורה.
טווחים חופפים גורמים לכשל ההפוך. התשובה נכונה, המסלול קיים, והוא מצביע על מארח שגוי, כי 192.168.0.0/24 בבית ספציפי יותר מהמסלול של המנהרה לאותו טווח. ספרו מחדש צד אחד או דחפו מסלול צר יותר, ואז אשרו את חומת האש ואת דרך החזרה של מארח השירות; ההערות של strongSwan על העברה מכסות את צד ה-sysctl של אותו מסלול.
תעודות הן בדיקת זהות נפרדת שאנשים מאשימים בה את ה-DNS. אם הדפדפן מדווח על אי-התאמת שם במקום שגיאת פתרון, החיפוש כבר עבד ומה שצריך לתקן הוא ה-SAN בתעודה. בדקו HTTPS מול השם, אף פעם לא מול כתובת IP חשופה.
בדקו שוב מהלקוח, לא מהשער
בדקו בתוך היישום שהמשתמש מתלונן עליו, כי חיפוש משורת הפקודה אינו מוכיח שהדפדפן עובר באותו מסלול. ה-DNS המאובטח של Chrome ו-network.trr.mode של Firefox יכולים לעקוף לגמרי את פותר המערכת, וכשהם עושים זאת שם פרטי או נכשל או דולף לפותר ציבורי. השוואה בין resolvectl query לבין dig @10.8.0.53 files.corp.example שהורץ ביד תגיד לכם מה משני אלה קרה.
אחר כך התנתקו והתחברו מחדש לפני שאתם מכריזים שזה תוקן. הגדרות שהוחלו ביד על ממשק נעלמות יחד עם הממשק, ופרופיל שנראה נכון רק בגלל שינוי מקומי שנשכח ייכשל באתחול הבא.
רשימת בדיקה קצרה למכונה הבאה: השם נפתר דרך הפותר של המנהרה, הסיומת מוגבלת ולא גלובלית, כתובת הפותר נמצאת בתוך הקידומות המותרות, המארח שבתשובה עונה בפורט השירות, והתעודה מכסה את השם שהמשתמש הקליד.