יש לך שני קווי uplink, ו-ip -6 route show מדפיס את אותה קפיצה הבאה בשניהם: default via fe80::1 dev uplink0 ו-default via fe80::1 dev uplink1. זה אינו התנגשות כתובות כפולה, והעתקת הקפיצה הבאה החשופה fe80::1 לטבלת מדיניות אינה אומרת ל-kernel איזה קישור התכוונת. השאלה האמיתית צרה יותר מהתסמין: האם הטבלה השנייה צריכה קישור אחד או שניים, ומה משאיר את המסלולים האלה חיים לאחר אתחול. שלושה תנאים, שנבדקים לפי הסדר, פותרים את רוב זה.

אותו fe80::1 הוא שני שכנים שונים

כתובות link-local מוגבלות לקישור יחיד, ולכן fe80::1 אינו כתובת אחת שהודפסה פעמיים; אלה שני שכנים שמקרה חולקים סיומת. אינדקס האזור הוא הדרך שבה מארח אומר איזה מהם הוא מתכוון, ולכן fe80::1%uplink0 ו-fe80::1%uplink1 הם יעדים שונים עבור ה-kernel, והסיומת הזו אינה עוברת לעולם לנתב מרוחק. RFC 4007 מתאר את מודל האזורים שמאחורי זה, ולכן טבלת מדיניות חייבת לשאת התקן עם כל קפיצה הבאה link-local.

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

הסר את ההתקן והמסלול הופך לבלתי ניתן לכתיבה. ip -6 route add default via fe80::1 table 200 אינו יכול לפתור את השער, ו-iproute2 דוחה אותו עם Error: Nexthop has invalid gateway. הוסף dev uplink0 והפקודה מצליחה, מפני שההתקן הוא מה שמצמיד את הקפיצה הבאה לאחד משני השכנים האלה. מה שההתקן אינו יכול לומר לך הוא אם uplink0 הוא הקישור הנכון לטבלה הזו, ומסלול שהועתק ממארח אחר מביא איתו את שמות הממשקים של אותו מארח, ומשם מגיעות הטעויות האמיתיות.

תנאי ראשון: קישור אחד או שניים בטבלה

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

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

ip -6 rule add fwmark 0x2 table 201
ip -6 route add default via fe80::1 dev uplink1 metric 100 table 201
ip -6 route add 2001:db8:100::/48 dev uplink1 metric 100 table 201
ip -6 route show table 201

אף אחד מהאובייקטים אינו מחליף את השני, וטבלה שמחזיקה רק ברירת מחדל עדיין יכולה להיכשל בפתרון השער שלה. אם הוספה נדחית, או שהמסלול קיים אך אינו שמיש, הכנס את הקידומת המחוברת של הממשק הזה לאותה טבלה, או סמן את הקפיצה onlink כשהקידומת הזו מנותבת במקום אחר. בבלוק שלמעלה, 2001:db8:100::/48 מייצג את הקידומת המחוברת הזו ב-uplink1, ולא יעד שרירותי. כלל ה-fwmark צורך רק סימון שמישהו אחר חייב להציב, מכלל nftables או iptables בנתיב ההעברה או מ-SO_MARK על השקע, ולכן בלוק שהועתק בלי מקור סימון לא מתאים לשום דבר.

תנאי שני: מדדים אינם מזהים ספק מת

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

אמת את הבחירה לאחר בניית הטבלה, ואמת אותה כפי שה-kernel יראה אותה. ip -6 route get 2001:db8:100::1 מדפיס את המסלול שבו ייעשה שימוש, כולל ההתקן וכתובת המקור שנבחרה, והוא מכבד כללי מדיניות. כתובת מקור של הקו הלא נכון היא הסימן הרגיל לכך שכלל התאים מוקדם מהצפוי.

תנאי שלישי: החליטו מי הבעלים של ההתמדה

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

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

ip -6 route flush table 201
ip -6 rule del fwmark 0x2 table 201

בנתב שמעביר עבור מארחים אחרים, בדוק את net.ipv6.conf.all.forwarding לפני שאתה מאשים את הטבלה. כשההעברה כבויה, מנות המיועדות לרשת אחרת נזרקות לא משנה כמה טבלה 201 נכונה.

תעד את העיצוב כדי שהאדם הבא יוכל לבקר אותו

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

לפני שאתה מכריז שהטבלה מוכנה, אמת את השכן עם ip -6 neigh show dev uplink0, קרא שוב את ip -6 rule show לאיתור תאונות סדר, ובדוק בתעבורה שמתאימה לכלל ולא בפינג שלוקח את ברירת המחדל. אחר כך הורד קו אחד בכוונה וראה לאיזה מסלול ה-kernel חוזר; התשובה צריכה להתאים לזו שכתבת.

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