למה קונטיינר macvlan לא יכול להשיב ללקוח VPN
קונטיינר macvlan לא יכול לדבר עם המארח שלו, והתשובות שלו עשויות לצאת דרך השער הלא נכון. הוסיפו נתיב שים בצד המארח ואז בחרו מודל מקור.
דמיינו מארח Linux שמסיים מנהרת VPN ובמקביל מריץ קונטיינר ברשת macvlan. ה-LAN הוא 192.168.60.0/24, הקונטיינר מחזיק בכתובת 192.168.60.210, ולקוחות VPN מגיעים מ-10.95.0.0/24. הלקוח מגיע לשירות, התשובה לא חוזרת אף פעם, וכל כלל חומת אש על המארח נראה תקין. שני אילוצים נפרדים מייצרים את הסימפטום הזה, ותיקון של אחד מהם משאיר את השני במקומו.
שני אילוצים, סימפטום אחד
האילוץ הראשון הוא בידוד: מנהל ההתקן macvlan של Docker לא מאפשר לקונטיינר לדבר עם המארח שלו דרך ממשק האב. לתעבורה בין מחסנית המארח לקונטיינר אין נתיב, לא משנה איך נכתבו הנתיבים על המארח.
האילוץ השני הוא נתיב החזרה. שער ברירת המחדל של הקונטיינר הוא בדרך כלל הנתב של ה-LAN, ולכן תשובה שמופנית ללקוח VPN יוצאת דרך הנתב הזה. אם לנתב אין נתיב חזרה למאגר ה-VPN, התשובה נזרקת אי שם באמצע.
שני הכשלים נראים זהים מנקודת המבט של הלקוח: בקשה שמגיעה ותשובה שאף פעם לא מגיעה. הם דורשים תיקונים שונים, וכלל masquerade רחב יכול להסתיר איזה מהם עדיין שבור. לכן הבדיקה הראשונה היא לכידת מנות בצד הקונטיינר ולא שינוי נוסף בחומת האש. אם הבקשה אף פעם לא מופיעה שם, אילוץ הבידוד הוא זה שפועל.
בנו את השים בצד המארח, באופן צר
ממשק macvlan שני על המארח, המחובר לאותו אב במצב גשר, נותן למחסנית המארח זהות משל עצמה באותו פלח LAN. הקצו לו כתובת מחוץ למאגר ה-DHCP ומחוץ לטווח הקונטיינר, ונתבו רק את הקונטיינר דרכו.
ip link add macvlan-vpn link eth0 type macvlan mode bridge ip address add 192.168.60.250/32 dev macvlan-vpn ip link set macvlan-vpn up ip route add 192.168.60.210/32 dev macvlan-vpn src 192.168.60.250
הפקודה הראשונה יוצרת את הממשק במצב גשר, שהוא ברירת המחדל המתועדת של מנהל התקן זה והמצב הרצוי לתעבורה בין מארח לקונטיינר. השנייה מקצה /32 כדי שהכתובת לא תתנגש בתחילית ה-LAN, והרביעית שולחת רק את כתובת הקונטיינר דרך השים.
אל תפנו את כל ה-LAN דרך הממשק החדש. הנתיב המחובר הרגיל נשאר כפי שהוא, ונתיב המארח צר במכוון כדי שקונטיינר אחד יקבל נתיב בלי ששאר הפלח ישנה את התנהגותו. נתיב ברירת מחדל שמצביע על השים יהיה תכנון אחר עם השלכות אחרות. שמרו אותו ספציפי ורדיוס הפגיעה נשאר קטן.
הפקודות האלה משנות את הגדרות הרשת במארח פעיל. במכשיר ייעודי או בפלטפורמה מנוהלת, השתמשו במנגנון התצורה הנתמך של אותה פלטפורמה, כי שינוי אינטראקטיבי ב-root shell עשוי לא לשרוד שדרוג.
החליטו איך נשמר המקור
כשהשים במקום, הקונטיינר יכול להגיע למארח, והשאלה הופכת להיות איזו כתובת מקור התשובה נושאת. שימור מקור ה-VPN המקורי הוא המודל הנקי יותר: הקונטיינר רואה את כתובת הלקוח האמיתית, והלוגים וכללי הגישה של השירות יכולים להשתמש בה.
כדי שזה יעבוד, תצורת הרשת של הקונטיינר חייבת לשלוח עבור נתיב זה תעבורה של 10.95.0.0/24 אל 192.168.60.250 כשער שלו. זו הגדרת נתיב או שער נתמכת בתוך התצורה של הקונטיינר עצמו, לא טריק בצד המארח. אמתו אותה מתוך הקונטיינר במקום להניח שההגדרה נכנסה לתוקף. שער ברירת מחדל שעדיין מצביע על נתב ה-LAN ימשיך לשלוח תשובות לאותו חור.
אם התכנון המאושר מסתיר במקום זאת את מקורות ה-VPN, הגבילו את התרגום באופן צר: מאגר ה-VPN האמיתי, השים כממשק יוצא, והקונטיינר והשירות המסוימים.
iptables -t nat -A POSTROUTING -s 10.95.0.0/24 -o macvlan-vpn -j SNAT --to-source 192.168.60.250
התאימו את השים כממשק יציאה, לא את המנהרה. כלל שמכנה את המנהרה כממשק יציאה לא יתאים למנה שמופנית אל הקונטיינר, וזו הטעות שסידור כזה בדרך כלל מכיל. שמרו על הכלל צר כמו המשפט שלמעלה ובדקו אותו כשהמאגר משתנה.
אמתו מהלקוח, לא מהמארח
בקשה מהמארח עצמו, הקשורה לכתובת השים, מוכיחה שהשים יכול להגיע לקונטיינר. היא לא מוכיחה שהקונטיינר יכול להחזיר תעבורה למקור משומר 10.95.0.x, כי כתובת המקור בבדיקה הזו היא של השים עצמו.
curl -sS --interface 192.168.60.250 -o /dev/null -w '%{http_code}\n' http://192.168.60.210:8080/health
sudo tcpdump -ni macvlan-vpn host 192.168.60.210הפקודה הראשונה בודקת את הקטע מהמארח לקונטיינר, והשנייה מראה מה באמת עובר דרך השים בזמן שלקוח VPN אמיתי שולח את הבקשה. הביטו בכתובת המקור בדרך פנימה ובשאלה אם מופיעה תשובה באותו זרם.
העברה קדימה חייבת להיות מופעלת במארח, ונתיב ההעברה צריך אישור עבור מאגר ה-VPN אל השים בפורט השירות ובנוסף תשובות מבוססות. כלל INPUT במארח לא מאשר תעבורה מועברת, וזו סיבה נפוצה לכך שהמנה נזרקת אחרי שהניתוב נראה תקין.
הריצו את היישום האמיתי עם אישורים אמיתיים, ואז בדקו ששירות שני, לא קשור, על אותו קונטיינר עדיין מסרב לכם. אם הדרך היחידה לגרום לזה לעבוד הייתה לפתוח כל כלל העברה, התכנון לא הושלם. שימו לב גם איזו כתובת מקור השירות רשם, כי בה ישתמשו כללי הגישה שלו מעתה.