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

תארו את המסלול לפני שמשווים משהו:

Client -> approved reverse proxy -> application origin

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

שני סוגי ראיות לכתובת

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

שדה העברה הוא מטא-נתונים על שרשרת. X-Forwarded-For, X-Real-IP והשדה התקני Forwarded יכול להיכתב בידי כל לקוח שמגיע לנקודת קצה שמשקפת אותם, ולכן מהימנותם תלויה לחלוטין במי הורשה לקבוע אותם.

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

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

כתיבת כתובת בשדה העברה אינה משנה את מקור חיבור ה-TCP שמגיע לשרת, ואינה משנה את הניתוב בשום מקום לאורך המסלול. ניתוב VPN רגיל או NAT מקור מעבירים תעבורה בלי שום כותרת HTTP כלל. בדומה לכך, שער מעבר אינו כותב מחדש חילופי HTTPS מוגנים כיאות בלי לשנות את סידור נקודת הקצה של TLS.

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

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

נקבו בשם הפרוקסי שמותר לו להצהיר

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

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

set_real_ip_from 10.20.0.0/24;
real_ip_header X-Forwarded-For;
# real_ip_recursive off - take the rightmost value in the field
# real_ip_recursive on  - walk the list back past every trusted address

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

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

טפלו בכוונה בשרשראות מרובות דילוגים

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

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

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

שמרו את שתי התצפיות ביומן

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

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

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