למה NAT ביתי לא מגן על ממשק ה-VPN שלך
נתב ביתי מעביר את המנהרה, אך המארח שופט את החבילה המפוענחת. קראו בנפרד את המאזין, הנתיב הפנימי ומדיניות הכניסה.
מחשבים ניידים מאחורי נתב ביתי בלי העברת פורטים עדיין מקבלים חיבורי SSH שמגיעים דרך ה-VPN. זו אינה סתירה, כי שני התקנים שונים שופטים שתי חבילות שונות. הנתב מעביר את התעבורה המוצפנת, והמארח מחליט מה לעשות עם החבילה המפוענחת שמגיעה לממשק המנהרה שלו. הפרדת שתי ההחלטות האלה היא כל התרגיל.
הנתב מעביר את המנהרה, המארח שופט את החבילה
שרטטו את הנתיב מהמקור המרוחק אל השירות לפני שתסתכלו על כלל אחד. הקטע החיצוני הוא תעבורת ה-VPN, שהנתב והשער מטפלים בה. הקטע הפנימי מתחיל כשנקודת הקצה מסירה את שכבת המנהרה והמארח מקבל חבילה שממוענת לכתובת ה-VPN שלו.
אחדו את שני הקטעים והנתב זוכה בקרדיט על החלטה שהמארח מקבל. עמוד העברת פורטים או יומן נתב מתארים רק שיחות חיצוניות, ואף אחד מהם לא אומר איזו תעבורה מפוענחת המארח יקבל. המארח מחיל את מדיניות הכניסה שלו על החבילה הפנימית, כפי שהוא מחיל אותה על כל חבילה שמגיעה לממשק. במדיניות הזו בדיוק נפתרת שאלת החשיפה.
מאזין כללי אינו שירות ציבורי
ב-Linux, כריכיה ל-INADDR_ANY פרושה כל כתובת מקומית, ולכן שירות יכול להשיב על ממשק מנהרה שמעולם לא נקב בשמו. מדריך ה-IP socket מתאר את הכריכה הזו, וכדאי לקרוא אותו לפני שמסיקים מסקנות מרשימת מאזינים. רשומת כללי היא עובדה על ה-socket, לא הצהרה על נגישות.
שתי השורות שלמטה הן אותו שירות בשתי כריכות שונות, וההבדל הוא כל התשובה לשאלה אם הממשק חשוב. קראו על איזו כתובת יושב ה-socket לפני כל דבר אחר.
ss -lntp "sport = :22"
LISTEN 0 4096 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=812,fd=3))
LISTEN 0 4096 10.8.0.6:22 0.0.0.0:* users:(("sshd",pid=812,fd=4))
נקבו בשם הסידור שיכול היה להגיע לפורט
שלושה סידורים שמים חבילה על אותו ממשק, ויש להם בעלים שונים. נקב בשם הנכון קובע מי צריך לשנות מדיניות.
| Arrangement | What reaches the port | Where the decision lives |
|---|---|---|
| Another permitted VPN peer | A packet from the same tunnel subnet | Gateway forwarding policy and host input rules |
| A deliberate public forward | Traffic the gateway publishes on purpose | Gateway service definition |
| A subnet routed behind the gateway | Client traffic from the far side | Gateway route and host input rules |
תוצאת דפדפן שמציגה כתובת יציאה ציבורית לא אומרת דבר על אף אחד מהשלושה, כי היא מתארת איך תעבורה יוצאת יוצאת ולא מה מותר לתעבורה נכנסת. עבדו לאחור מהמאזין ומכתובת המקור ביומן השירות. אם המקור הוא עמית מנהרה אחר, מדיניות השער היא המסמך המעניין. אם זו כתובת מתורגמת, מצאו את התרגום לפני שתשנו כלל.
הגבילו את השירות לנתיב שהתכוונתם אליו
אם SSH נדרש רק מנתיב ניהול, כתבו את הנתיב הזה כטווח מקור ועוד ממשק. לאחר מכן הגבילו את כללי הכניסה של המארח לפי ממשק, יעד ומקור ולא לפי שם רשת, מכיוון ששם שנראה פרטי יכול לייצג כל כתובת. השאירו מסלול למי שיפתור את הבעיה הבאה.
nft add rule inet filter input iifname "tun0" ip saddr 10.8.0.0/24 tcp dport 22 accept
nft list chain inet filter input
כלל שמנקב בשם ממשק המנהרה ובטווח הניהול מבטא את הכוונה במקום אחד. השוו אותו לכלל שנכתב עבור רשת ה-Wi-Fi, שאינו אומר דבר על תעבורת מנהרה מפוענחת. כששתי השכבות לא מסכימות, מדיניות המארח היא זו שהחבילה פוגשת.
השאירו כניסות וטלאים בדיוק במקומם; להגיע לפורט מעולם לא היה אותו דבר כמו לקבל רשות להשתמש בו. רשמו את משפחת הכתובות ואת הזמן עבור כל מקור לא מוכר, וחקרו לפני שתאשימו תכונה או פרצה. כלל שמקבל כל עמית מנהרה הוא עיצוב אחר מזה שמקבל תת-רשת ניהול, ואף שורת יומן לא תאמר איזה מהם נועד.
קבלו את התיקון בהצלחה אחת ובסירוב אחד
הוכיחו את שני החצאים: חיבור מאושר אחד מצליח ונתיב מוחרג אחד נדחה. הסירוב הוא החצי שאנשים מדלגים עליו, והוא זה שמראה שהכלל עובד ולא עומד לצד ברירת מחדל מתירנית. בדקו מהצד המוחרג במקום להתווכח על זה.
חזרו על הזוג לאחר התחברות מחדש, כי מנהרה שחוזרת בשם ממשק אחר יכולה לעקוף בשקט כלל שמוגבל לישן. הגבול שחשוב הוא זה שהמארח מחיל על חבילות שהוא באמת מקבל.