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

התחילו בלקוח ותנו שם לשני הקצוות

התחילו במקום שבו המשתמש מתחיל, בפרופיל החיבור. הוא מכיל כתובת מרוחקת אחת, שיטת אימות אחת וכאשר התכנון תומך בכך, רשימת מסלולים. תנו שם לאותה מנהרה חיצונית מהלקוח לשער A והוסיפו לה כתובות לדוגמה: כתובת המנהרה של הלקוח 10.77.0.2, זו של A 10.77.0.1 ונקודת הקצה הציבורית של A 198.51.100.10, שנלקחו מטווח התיעוד TEST-NET-2 כדי ששום דבר בדוגמה לא יתנגש במארח אמיתי.

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

סדרתי: A מפענח ואז מצפין מחדש

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

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

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

מקונן: A מסיר רק את השכבה החיצונית

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

אז הקישור העולה של הלקוח נושא שתי שכבות, ואילו הנתיב בין A ל-B נושא אחת. A רואה את הכתובות החיצוניות של המנהרה הפנימית, וזה מספיק כדי לדעת שיש תעבורה ולאן בערך היא הולכת, ולא מספיק כדי לקרוא את המטען. זה כל ההבדל מהמקרה הסדרתי, ואף מונה קפיצות אינו מראה אותו. מה ש-A עדיין יכול לעשות הוא לסרב להעביר את מה שאינו יכול לקרוא, וזה תמיד עומד לרשות מפעיל השער הזה.

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

ציירו את הצופים, לא רק את המנהרות

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

Vantage pointSerial chainNested chain
Client's access networkOuter tunnel onlyOuter tunnel only
Operator of AInner IP packet between A and BOuter addresses of the inner tunnel, not its payload
Path between A and BSecond tunnelSecond tunnel
Operator of BInner packet re-originated by APayload after the inner layer is removed
Service edgeTraffic from the exit addressTraffic from the exit address

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

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

עברו על נתיבי הכשל לפני שתבחרו

שברו דברים בכוונה מהלקוח, בסדר שבו משתמש היה פוגש אותם. התחילו בממשק וב-MTU שלו, כי קינון נכשל בגודל החבילה הרבה לפני שהוא נכשל באימות.

ip -4 addr show dev tun0
ip link show dev tun0 | grep mtu
ping -M do -s 1380 -c 2 10.77.1.1

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

openssl s_client -connect intranet.example.com:443 -brief < /dev/null

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

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

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