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

שום דבר על המסך לא מפריד בין שלושת המצבים האלה, אז שאלו לאילו מזהים היו הכללים מוצמדים במקום איזה צבע המחוון מציג. ב-Linux כלל יכול לנקוב בשם ממשק או ב-ipset שמתמלא ממנו; ב-Android אפשר לומר ל-VpnService אילו רשתות בסיס לעקוב אחריהן דרך setUnderlyingNetworks. כל הצמדה מצביעה על קישור שעומד להיות מוחלף, וכל אחת מהן צריכה להיבחן מחדש לאחר מכן.

מה המעבר באמת כותב מחדש

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

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

לבנות מחדש את המנהרה החיצונית בלי לקדוח חור

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

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

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

ip route get 1.1.1.1
ip -6 route get 2606:4700:4700::1111

כשהקישור החדש מביא IPv6 והכללים לא

רשתות סלולריות ואורחים לעתים קרובות מחלקות קידומת IPv6 גלובלית גם כשה-LAN הקווי של המשרד מעולם לא עשה זאת. מדיניות שנכתבה רק ככללי IPv4, הצורה המובנית של רוב המתכונים שנכתבו ביד ל-iptables ול-nftables, אינה מכסה מזה דבר. המנהרה נשארת מחוברת, יישומים עם נגישות IPv6 יוצאים מחוצה לה, והמחוון לא יכול להראות את ההבדל כי המנהרה באמת למעלה. המקרה המשלים נפוץ באותה מידה: מערך כללים ל-IPv6 בלבד לא עושה דבר ברשת שאינה מציעה v6.

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

ip -4 route show default
ip -6 route show default
sudo nft list ruleset | grep -c 'ip6 '

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

הפותר מחליף ידיים באמצע הסשן

במערכות מודרניות הפותרים צמודים לקישורים, כך שקישור חדש מגיע עם מערך פותרים חדש ואולי עם תצוגת split-DNS שונה. systemd-resolved מחזיק scope לכל קישור ובוחר ביניהם לפי נתיב, בעוד macOS קורא פותרים עם scope מהמאגר הדינמי ומכבד את סדר הממשקים. לקוח שמתקין פותר משלו מתחרה בזה של הקישור, וכללי עדיפות שאיש לא צופה בהם מכריעים את המנצח. אז פתרון שמות יכול להישבר בזמן שסינון החבילות עושה בדיוק את מה שנכתב עבורו.

קראו את הפותר הפעיל ולא את זה המוגדר. במארח systemd פקודת המשנה status מראה מאיזה קישור הגיע כל scope והאם שם private-DNS בתוקף:

resolvectl status --no-pager
resolvectl query intranet.example.com

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

תרגלו את המעבר ושמרו את התיעוד

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

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

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

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