לשמר או לבצע SNAT לכתובות IP של לקוחות VPN בגבול הענן
שימור המקור שומר על זהות הלקוח בכל יומן, SNAT שומר על טבלת הניתוב קטנה. שלושה תנאים אומרים מה האפליקציה צריכה.
שמירת הכתובת של לקוח ה-VPN עד לאפליקציה גורמת לכל שורת יומן ולכל רשומה ברשימת ההיתרים לומר את אותו הדבר. כתיבה מחדש שלה בקצה הענן הופכת את טבלת הניתוב לפשוטה יותר ואת היומנים לפחות שימושיים. אף אחת משתי האפשרויות אינה שגויה כשלעצמה, והטיעון שמכריע ביניהן עוסק לעתים רחוקות בביצועים. שלושה תנאים מכריעים: האם האפליקציה חייבת לדעת איזה אדם התחבר, האם בד הענן יקבל את המקור שאתם מתכוונים לשלוח, ומי ייקח על עצמו את נתיב החזרה בהמשך.
שלושה תנאים מכריעים
התחילו מהדרישה של האפליקציה, לא מתרשים הרשת. אם ההרשאה או הביקורת תלויות בכתובת הלקוח הבודדת, הרי ששימורה הוא דרישה תפקודית ותרגום הוא רגרסיה. אם האפליקציה צריכה לדעת רק שהתעבורה הגיעה בנתיב הגישה מרחוק, די בכתובת מתורגמת והיא זולה בהרבה לתפעול.
התנאי השני מכני. רשת וירטואלית אינה סומכת אוטומטית על מנה שמצהירה על כתובת שלא הוקצתה לממשק השולח. רוב בדות הענן אוכפות זאת, בדרכים ובשמות שונים, ועיצוב שמתעלם מכך ייראה נכון בתרשים וייפול בשקט בייצור.
השלישי ארגוני. שימור מקורות פירושו שטבלת הניתוב של תת-הרשת של האפליקציה חייבת להצביע בחזרה אל השער עבור קידומת הלקוח, וכל צוות שמוסיף תת-רשת לאחר מכן חייב לשמור על הנתיב הזה עקבי. זו עלות קטנה פעם אחת ועלות חוזרת על פני עשרות חשבונות. החליטו מי משלם אותה לפני שאתם מבטיחים את ההתנהגות.
נתיב אינו הרשאה לזיוף
הוספת נתיב חזרה אומרת לתת-הרשת שלכם לאן התשובות צריכות ללכת. היא אינה אומרת לבד שהמופע שמעביר את המנות האלה רשאי לפלוט אותן עם מקור זר. ב-AWS הבקרה הרלוונטית היא בדיקת מקור ויעד, והיא נראית לכל מופע:
aws ec2 describe-instances --instance-ids i-0a1b2c3d4e5f60718 \
--query "Reservations[].Instances[].SourceDestCheck"
aws ec2 modify-instance-attribute --instance-id i-0a1b2c3d4e5f60718 \
--no-source-dest-check
כבו אותה רק עבור המופע שתפקידו המתועד הוא העברה, ולשום דבר אחר. כל מכונה וירטואלית של אפליקציה שמשאירה את הבדיקה פעילה היא מכונה אחת פחות שאפשר להשתמש בה כדי לפלוט תעבורה עם מקור שאול. אם הפלטפורמה שלכם אינה AWS, חפשו את ההגדרה המקבילה של מניעת זיוף או כתובות מותרות במקום להניח שההתנהגות עוברת כמות שהיא.
לכידת מנות מהירה מכריעה את השאלה מהר יותר מקריאת הקונסולה. אם התשובות יוצאות והלקוח אף פעם לא רואה אותן, הבד הוא שמשליך את המקור המזויף, ולא האפליקציה שנכשלת.
מה התרגום קונה ומה הוא עולה
כתיבה מחדש של המקור בשער מבטלת את בעיית נתיב החזרה. האפליקציה רואה כתובת אחת שהיא כבר יודעת איך להגיע אליה, וקידומת הלקוח לא צריכה להופיע לעולם בטבלת ניתוב של הענן. בלינוקס הכלל הוא שורה אחת, וכדאי לכתוב את הגרסה הצרה ביותר שאתם יכולים:
sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -s 172.20.8.0/24 -o ens5 -j SNAT --to-source 10.40.3.10
שימו לב למה האפליקציה רושמת כעת: 10.40.3.10 לכל משתמש, בכל חיבור, לנצח. כל רשימת כתובות מותרות שנבנתה על הערך הזה מעניקה כעת גישה לכל אוכלוסיית הגישה מרחוק, וכל סקירת תקרית חייבת לחזור אל השער כדי לענות מי זה היה.
הפתרון אינו לנטוש את התרגום, אלא להפסיק להעמיד פנים שהכתובת היא זהות. נשאו את זהות הלקוח בשדה מאומת, רשמו אותה בשער יחד עם הטאפל המתורגם, ותנו לאפליקציה להצטרף עליו. בלי מפתח ההצטרפות, התרגום הופך בעיית רשת לבעיה פורנזית קבועה.
הממסר הוא ממשק אחר
פרוקסי הפוך לפני האפליקציה עוקף לחלוטין את שאלת הנתיב המנותב. הפרוקסי פותח חיבור קצה אחורי משלו, כך שקידומת הלקוח לא צריכה להיות ניתנת לניתוב בתוך הרשת הווירטואלית, והאפליקציה יכולה לקבל זהות בכותרת שהפרוקסי מגדיר.
הכותרת הזו מהימנה רק כאשר הקצה האחורי מקבל אותה מהפרוקסי ומשום דבר אחר. במונחי nginx פירוש הדבר למנות את העמית המהימן במפורש במקום להאמין לכל מה שמגיע:
set_real_ip_from 10.40.3.10;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
כל לקוח שמסוגל להגיע לקצה האחורי ישירות יכול לזייף את אותה כותרת, ולכן הקצה האחורי חייב להיות בלתי נגיש אלא דרך הפרוקסי. זו עובדה של חומת אש, לא דעה של תצורה, וזו ההנחה שאנשים מדלגים עליה כשהם מעתיקים את הקטע.
הממסר משנה גם את מה שאתם קונים. אתם מקבלים זהות ברמת האפליקציה ומקום טבעי לתעד אותה; אתם מוותרים על כלליות, כי כל פרוטוקול חדש צריך תמיכת פרוקסי משלו. עבור שירותי HTTP העסקה הזו בדרך כלל טובה, וכל דבר שאינו HTTP בדרך כלל אינו זמין בכלל.
רשמו מה כל גבול רואה
יהיה אשר תבחרו, סקירת העיצוב צריכה להסתיים בטבלה אחת שמציינת את כתובת המקור ואת הזהות הניתנת להוכחה בכל קפיצה. בלעדיה, התקרית הראשונה מייצרת שלושה צוותים שכל אחד מתאר לקוח אחר.
| Boundary | Source the next hop sees | What is actually proven |
|---|---|---|
| Client to gateway | 172.20.8.14 | A certificate or credential was presented |
| Gateway to app subnet, preserved | 172.20.8.14 | The same session, if the return route exists |
| Gateway to app subnet, translated | 10.40.3.10 | Only that traffic came through the gateway |
| Proxy to backend | 10.40.3.10 plus a header | The proxy asserted an identity it authenticated |
ואז בחרו. שמרו כאשר ההרשאה של האפליקציה באמת תלויה בכתובת הלקוח ואתם יכולים לקחת על עצמכם את הנתיב. תרגמו כאשר זה אינו המצב ואתם יכולים לשאת זהות מחוץ לרצועה, והשתמשו בהנחיות AWS למופעי העברה עבור הגדרות ההעברה הספציפיות לפלטפורמה. פנו לממסר כאשר השירות מדבר HTTP ואתם רוצים שהזהות תפסיק להיות כתובת.