נתיב ברירת המחדל של IPv6 נעלם לאחר הפעלת העברה ב-Linux
הפעלת העברת IPv6 גורמת לליבה להתעלם מהודעות ראוטר ב-uplink, ונתיב ברירת המחדל שנלמד פג. תקנו זאת עם accept_ra.
הגדרתי net.ipv6.conf.all.forwarding=1 בשער Debian כדי שיוכל להעביר תעבורה של לקוחות VPN, וכחצי שעה לאחר מכן למכונה לא היה יותר נתיב ברירת מחדל של IPv6. הראוטר שמעלה היה פעיל, השכן link-local עדיין ענה, וה-uplink עדיין החזיק בכתובת הגלובלית שלו. מה שהפסיק היה הנכונות של הליבה להמשיך ולקבל הודעות ראוטר באותו ממשק. הנתיב לא נעלם ברגע שהקלדתי את ה-sysctl; הוא נעלם כשפג תוקף חיי נתיב ברירת המחדל שנלמד מ-RA ושום דבר לא חידש אותו.
במבט ראשון שום דבר לא נראה שבור. ההעברה עבדה, הלקוחות עדיין עברו כל עוד הנתיב הישן היה במטמון, והכשל הגיע מאוחר יותר מהשינוי שגרם לו. בדיוק העיכוב הזה הוא הסיבה שהאשמה נופלת על הצד שמעלה או על כלל חומת אש שמעולם לא היה מעורב.
קראו את טבלת הנתיבים לפני שנוגעים בכל sysctl
התחילו עם ip -6 route show default וקראו את המאפיינים, לא רק את השער. נתיב ברירת מחדל שנלמד מ-RA מסומן ב-proto ra, נושא העדפה ומציג ספירה לאחור של expires. לנתיב שהוספתם ביד אין אף אחד מהם, וההבדל הזה אומר לכם איזה מנגנון מחזיק בנתיב.
$ ip -6 route show default
default via fe80::1 dev eth0 proto ra metric 1024 expires 1432sec hoplimit 64 pref mediumלאחר מכן הסתכלו בכתובת: ip -6 addr show dev eth0. כתובת גלובלית עם חיי תוקף מועדפים ותקפים הנמדדים בשעות תשרוד יותר מנתיב ברירת מחדל שחיי הראוטר שלו נמדדים בדקות. כתובת קיימת ונתיב ברירת מחדל חסר הוא החתימה של בעיית הודעות. אם גם הכתובת חסרה, תחילה יש לרדוף אחר הקישור, מידע הקידומת או זיהוי כתובות כפולות.
למה העברה מכבה את עיבוד RA
RA הוא מנות ICMPv6 מסוג 134, הנשלח ממקור link-local עם מגבלת קפיצה 255. לפני שהליבה משתמשת בו היא בודקת את accept_ra של הממשק. ערך ברירת המחדל הוא 1, ו-1 אינו אומר כן. הוא אומר: קבל רק כל עוד המארח הזה אינו מעביר. הגדירו forwarding=1 והתנאי הזה נכשל, ולכן ההודעה נזרקת לפני שנשקלת כל קידומת או ראוטר ברירת מחדל בתוכה.
קיימים שלושה ערכים, ורק השלישי שורד את ההעברה:
accept_ra | forwarding=0 | forwarding=1 |
|---|---|---|
| 0 | ignored | ignored |
| 1 (default) | accepted | ignored |
| 2 | accepted | accepted |
שני דגלים אחרים קובעים מה באמת מותקן. accept_ra_defrtr שולט בשאלה אם הראוטר המוגדר כברירת מחדל בהודעה הופך לנתיב, ו-accept_ra_pinfo שולט בשאלה אם מידע הקידומת משמש לתצורת הכתובת. כיבוי accept_ra_defrtr הוא הדרך המקובלת לשמור כתובות SLAAC במארח שמעביר בלי ללמוד נתיב ברירת מחדל. זה מנוף אחר מ-accept_ra, וזה המנוף שאליו פונים כשמחפשים כתובות ולא נתיב. מדריך הליבה ל-IP sysctl מפרט את שלושתם.
אמתו זאת בשלוש פקודות
ראשית, קראו את הערכים החיים במקום את הקובץ שאתם חושבים שנטען:
sysctl net.ipv6.conf.eth0.forwarding net.ipv6.conf.all.forwarding \
net.ipv6.conf.eth0.accept_ra net.ipv6.conf.eth0.accept_ra_defrtrשנית, הוכיחו שההודעות עדיין מגיעות. סינון לפי בייט הסוג של ICMPv6 מספיק, והוא חוסך קריאת קיר של תעבורת גילוי שכנים:
tcpdump -ni eth0 'icmp6 and ip6[40] == 134'אם לא מופיע דבר במשך כמה דקות, accept_ra אינו הבעיה שלכם. הצד שמעלה הפסיק להכריז, משהו בדרך מסנן ICMPv6, או שהממשק הזה באמת אינו בסגמנט שאתם חושבים. שלישית, בקשו הודעה בעצמכם וקראו את השדות שלה:
rdisc6 eth0rdisc6 מגיע בחבילת ndisc6 ב-Debian וב-Ubuntu. בפלט, הסתכלו בחיי הראוטר ובהעדפה לפני שתשנו משהו אחר. הודעה עם חיי ראוטר 0 היא הוראה להסיר את ראוטר ברירת המחדל, ואף ערך של accept_ra לא הופך אותה לנתיב שמיש. כך גם תופסים CPE במעלה בזמן גשר שמחלק קידומות אך אינו מציע את עצמו כראוטר מעולם.
הפכו את ה-uplink לממשק המתירני היחיד
אם הצד שמעלה אמור להיות ראוטר ברירת המחדל, קבלו שם הודעות למרות ההעברה, ובשום מקום אחר:
# /etc/sysctl.d/60-ipv6-router.conf
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.eth0.accept_ra = 2
net.ipv6.conf.eth0.accept_ra_defrtr = 1התחימה חשובה כי העברת IPv6 בלינוקס היא מתג גלובלי אחד, ולא אחד לכל קישור. כתבו 1 אל net.ipv6.conf.wg0.forwarding ואז קראו את net.ipv6.conf.all.forwarding: הערך הגלובלי מתהפך וכל ממשק מתחיל להעביר. אינכם יכולים להיות ראוטר במנהרה ומארח רגיל ברשת המקומית. את מה שאפשר לתחום זה את הקבלה. השאירו את accept_ra=2 על ה-uplink ותנו לממשקי המנהרה והרשת המקומית להישאר על 1 או 0, כדי שהודעה תועה שמגיעה דרך המנהרה לא תוכל להתקין נתיב ברירת מחדל שמצביע לתוכה.
sysctl -w זמני לא ישרוד את האתחול הבא, וגם systemd-networkd וגם NetworkManager כותבים את הערכים האלה מהתצורה שלהם. ב-networkd הגדירו IPv6Forwarding=yes ו-IPv6AcceptRA=yes בקובץ ה-.network של ה-uplink; networkd מתעד את IPv6Forwarding כגלובלי מאותה סיבה בליבה. ב-NetworkManager, ipv6.method=auto על ה-uplink הוא מה שמניע את ערך accept_ra, לכן קראו שוב את ה-sysctl אחרי nmcli connection up במקום לסמוך על הבדיקה הראשונה.
החלופה הסטטית, ip -6 route add default via fe80::1 dev eth0, אכן עובדת, והיא תשובה סבירה כשלמארח שמעלה יש כתובת link-local יציבה. היו ברורים לגבי מה שאתם מוותרים עליו. נתיב ברירת מחדל סטטי אינו מתחדש ואינו נסוג לעולם, ולכן הוא ממשיך להצביע על שכן מת לאחר שהצד שמעלה הוחלף. נתיב RA נכשל בבטחה; הסטטי נכשל בשקט.
בדקו מנה שהועברה, לא את זו של השער עצמו
הפינג של השער עצמו יכול להצליח בנתיב שאף לקוח אינו יכול להשתמש בו, והוא יכול להצליח גם מפני שהשער הוא המקור. בדקו מלקוח מחובר ואז שאלו את השער מה היה עושה עבור הכתובת של אותו לקוח:
# on the VPN client
ping -6 -c 3 2001:4860:4860::8888
# on the gateway, using a client address
ip -6 route get 2001:4860:4860::8888 from fd42:20::2לאחר מכן המתינו חיי ראוטר אחד והסתכלו שוב. המצב היציב שאתם רוצים הוא נתיב ברירת מחדל מסומן ב-proto ra שערך ה-expires שלו מתאפס שוב ושוב, יחד עם all.forwarding=1. אם expires רק סופר לאחור, ההודעות עדיין נזרקות במקום כלשהו, והאשם הרגיל הוא מנהל רשת שכותב מחדש את accept_ra לאחר שה-sysctl בזמן האתחול כבר רץ.
לפני שתסגרו את זה, אמתו ארבעה דברים: נתיב ברירת המחדל הוא proto ra והוא מתחדש, accept_ra=2 חל רק על ה-uplink, ההעברה עדיין 1 לאחר אתחול ולאחר אתחול המנהל, ולקוח ולא השער משלים פינג IPv6. אם הלקוח עדיין נכשל עם נתיב תקין, החשוד הבא הוא נתיב החזרה או חומת אש במעלה, לא ההודעה.