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

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

לאן client-to-client מעביר את החבילה

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

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

הנתיב שחבילת עמית באמת עוברת

נניח שירות Linux Community OpenVPN 2.6, עיבוד TUN במרחב המשתמש ולא DCO, טופולוגיית תת-רשת, tun0 ובריכה של 10.44.0.0/24 עם לקוח A בכתובת 10.44.0.21 ולקוח B בכתובת 10.44.0.37. בטופולוגיית תת-רשת הכתובת והמסכה שקיבל A כבר מכסות את הבריכה, ולכן A שולח את החבילה להתקן המנהרה בלי צורך בנתיב דחוף נוסף. בדקו את הנתיב האפקטיבי ב-A במקום להניח אחד.

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

שני כללים בשרת, בסדר הזה

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

sysctl -w net.ipv4.ip_forward=1
iptables -A FORWARD -i tun0 -o tun0 -s 10.44.0.21 -d 10.44.0.37 -p tcp --dport 22 -j ACCEPT
iptables -A FORWARD -i tun0 -o tun0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i tun0 -o tun0 -j DROP

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

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

מה B עדיין חייב להתיר

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

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

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

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