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

שלוש אפשרויות, ומה כל אחת באמת משנה

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

What the far side needsPrefix mappingPer-host DNATRouted prefix
Users visible to its logsOnly without source NATSame conditionYes, unchanged
To start a connection toward youNo, alias is localNo, same reasonYes, both ends route
To absorb a new hostYes, arithmetic onlyNo, one rule per addressYes, it simply routes
To require no config changeYes, with source NATYes, same conditionNo, it needs a route back

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

זוגות קידומות, ולמה הגדלים חייבים להתאים

NETMAP הוא יעד בטבלת nat שעובד על זוג קידומות באורך זהה. אין בו טבלה לכל כתובת: הוא מסיר את הקידומת, שומר את סיביות המארח ומחבר אותן שוב לקידומת החדשה, ולכן /24 ממופה ל-/24 ואף פעם לא ל-/25. המיקום קובע את הכיוון: התאמת יעד ב-PREROUTING כותבת מחדש לאן המנה הולכת, והתאמת מקור ב-POSTROUTING כותבת מחדש מאיפה היא באה.

מארח בכתובת 192.168.2.17 מופיע ללקוחות שלכם כ-10.50.1.17, והאוקטט האחרון אינו קישוט — זה אותו מספר בשני הצדדים. הוסיפו מחר מארח ב-192.168.2.40 והכינוי שלו יהיה 10.50.1.40, בלי שום כלל לעריכה.

הלקוחות עדיין צריכים נתיב לטווח הכינויים שמצביע על המכונה שלכם, אלא אם הכינוי נופל בתוך תת-רשת שהם כבר מגיעים אליה. לשער אין צורך בנתיב לכינוי, כי תרגום היעד רץ ב-PREROUTING, לפני חיפוש הנתיב. גם העברה קדימה חייבת להיות פעילה, אחרת הגרעין מפיל את המנה לאחר הכתיבה מחדש. שלוש הפקודות שלמטה הן כל ההגדרה בשער בסגנון Debian עם לקוחות על br0, הכינוי על 10.50.1.0/24 והמנהרה על tun0.

sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A PREROUTING -i br0 -d 10.50.1.0/24 -j NETMAP --to 192.168.2.0/24
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE

התשובה חייבת למצוא את דרכה חזרה בעצמה

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

מיסוך ביציאה הוא הדרך הקצרה: כלל אחד ב-POSTROUTING והצד המרוחק רואה את כתובת המנהרה שלכם, כך שהוא לא צריך נתיב משלו. המחיר הוא שכל המשתמשים מתמזגים לכתובת אחת, והיומנים לכל משתמש מפסיקים לומר משהו. השארת המקור שלם שומרת את המידע הזה, אבל אז האתר המרוחק חייב לשלוח את התשובות לטווח הלקוחות חזרה דרך המנהרה. על OpenVPN שרת זה push "route 10.50.9.0 255.255.255.0", בתוספת שורת route 192.168.2.0 255.255.255.0.

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

conntrack -L -d 10.50.1.17
iptables -t nat -L PREROUTING -v -n

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

התנגשויות והחיפוש שרץ ראשון

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

בשער, ip route get 192.168.2.17 אמור לנקוב בהתקן המנהרה; גשר מקומי פירושו שהטווח המרוחק מוסתר ושום כלל nat לא יתקן זאת. אם הרשת שלכם כבר משתמשת ב-192.168.2.0/24, מספרו מחדש את האתר המרוחק במקום לערום מיפוי על ההתנגשות.

לבדוק מלקוח אמיתי, ואז לשמור

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

curl -sv http://10.50.1.17/ -o /dev/null
ss -tn dst 10.50.1.17
conntrack -L -d 10.50.1.17

שני חיבורים מוצלחים או שלושה מוכיחים את האריתמטיקה, אבל הם לא אומרים דבר על התמדה או על המהנדס הבא. שמרו את הכללים במקום שבו תהליך האתחול קורא אותם, שב-Debian ו-Ubuntu פירושו iptables-save > /etc/iptables/rules.v4 עם netfilter-persistent מופעל. מיפוי שנעלם באתחול גרוע מכלום, כי התקלה מגיעה בלי שינוי אחרון לתלות בו אשמה.

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

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