שרת VPN שעונה מרשת סלולרית ונכשל מהספה הוא בדרך כלל לא בעיית תעודה. הלקוח בתוך ה-LAN מבקש מהנתב לתרגם מנה שהיעד שלה הוא הכתובת הציבורית של הנתב עצמו, כלומר המנה חייבת לצאת ולחזור פנימה מיד. התמרון הזה נקרא hairpinning, והרבה נתבים או שאינם מיישמים אותו או שהם עושים זאת רק כאשר תיבת סימון מופעלת. דווקא הצלחת הבדיקה מבחוץ היא שמבלבלת, כי היא מוכיחה שהמאזין וכלל ההעברה תקינים.

המנה יוצאת וחוזרת פנימה

עקבו אחרי המנה. הלקוח מפענח את השם הציבורי, מתחבר לכתובת הציבורית, וה-NAT של היעד בנתב כותב מחדש את היעד אל השרת הפנימי. התשובה של השרת ממוענת לכתובת ה-LAN של הלקוח, ולכן היא חוזרת דרך ממשק ה-LAN של הנתב בלי לעבור אף פעם בכלל ה-NAT שהיה מתרגם את המקור בחזרה.

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

RFC 4787 מתאר את ההתנהגות שמצופה מ-NAT במקרה הזה, והגרסה הקצרה היא שהיא אופציונלית בפועל גם במקום שבו היא מוגדרת בתאוריה. יש נתבים שקוראים להגדרה NAT loopback, אחרים קוראים לה hairpin NAT או NAT reflection, ויש שאינם חושפים דבר. נתב שאין לו את זה אינו מוגדר שגוי; הוא עושה את הדבר הרגיל, והתיקון שייך למקום אחר. אל תסיקו מבדיקה מקומית שנכשלה שכלל ההעברה הציבורי שגוי.

בדיקה 1: בדקו את שני המסלולים בנפרד

מחוץ ל-LAN, התחברו עם אותה פרופיל שמשתמש אמיתי היה משתמש בו ואשרו שהחיבור נוצר. מבפנים, התחברו לכתובת הציבורית עם אותה פרופיל ורשמו את השגיאה המדויקת ואת השעה.

בדיקה מקומית מדויקת שומרת על שם המארח ומחליפה רק את הכתובת: curl -v --resolve vpn.example.com:443:203.0.113.10 https://vpn.example.com/ שולח את הבקשה לכתובת הציבורית ובמקביל מציג את שם השרת הנכון. זה מפריד בין בעיית פענוח שמות לבעיית תרגום, שקשה להבדיל ביניהן כשם אותו שם עובד מבית קפה. שימו לב אם הלקוח נכשל בחיבור TCP או מאוחר יותר ב-TLS, כי הראשון מצביע על תרגום והשני על זהות.

בדיקה 2: קראו מה השרת רואה

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

אם חיבור מגיע מכתובת ה-LAN של הנתב ולא משל הלקוח, מתרחש hairpinning והמקור נכתב מחדש. זו תצורה עובדת, לא תקלה.

בדיקה 3: תקנו בלי לגעת במסלול החיצוני

קיימות שלוש צורות נתמכות, לפי סדר גדל של רדיוס ההשפעה. הצרה ביותר היא DNS מפוצל: פרסמו רשומה פנימית כך שאותו שם שרת יפוענח לכתובת הפנימית עבור לקוחות ב-LAN, מה שנמנע מהמסלול הציבורי לגמרי. הבאה היא הפעלת אפשרות ה-loopback או ה-reflection המתועדת של הנתב, אם יש כזו, והחלתה רק על השירות הזה. הרחבה ביותר היא כלל source-NAT בנתב שכותב מחדש תעבורה שמקורה ב-LAN אל השרת כדי שהתשובה תחזור דרך הנתב; בנתב Linux זה כלל MASQUERADE בתוך POSTROUTING שמתאים לכתובת השרת ולפורט שלו. שלושתם משאירים את המסלול החיצוני ללא שינוי, וזו התכונה שיש לשמר.

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

ל-DNS מפוצל יש מלכודת אחת שראויה לציון. החלפת שם מארח ב-IP שרירותי משנה את מה שהלקוח מאמת, ולכן הרשומה הפנימית חייבת עדיין להתאים לשם בתעודה.

בדיקה 4: אמתו את שני המסלולים לאחר מכן

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

שמרו על הרשומה קצרה: באיזו כתובת כל לקוח השתמש, מה השרת ראה ואיזה משלושת התיקונים הוחל. דרישות ה-hairpinning של RFC 4787 הן ההפניה למה שמצופה מ-NAT כאן, והן מסבירות מדוע נתב בלי התכונה מתנהג כרגיל. כשל מקומי שהעולם החיצוני אינו יכול לשחזר הוא שאלת תרגום עד שיוכח אחרת, ולכן בדקו אותו ככזה.

מאמרים קשורים