מה REMOTE_ADDR של PHP באמת אומר מאחורי VPN
זה ערך שסיפק שרת האינטרנט שלכם, לא שאילתה בתוך המנהרה. עברו על נתיב הבקשה, בדקו מי רשאי לשכתב אותו והשאירו את הזהות באפליקציה.
מישהו שואל למה משתמש VPN מופיע ביומן האפליקציה עם כתובת ששייכת לשער, או עם כתובת שהשתנתה אחרי הצהריים. התשובה מתחילה במה הערך הזה הוא: רשומה שהשרת שם בסביבת הבקשה. זו אינה שאילתה לתוך המנהרה, אינה זהות תעודה ואינה הבטחה שהמספר שייך לאדם אחד. קריאה שלו כאחד משלושת אלה מניבה תשובות בטוחות שהן שגויות בדרכים שונות.
הערך מגיע מהשרת, לא מהמנהרה
PHP מקבל את סביבת הבקשה ממי שהריץ את הסקריפט. מדריך משתני השרת של PHP מתאר את הרשומות האלה ככאלה שנוצרו על ידי שרת האינטרנט, והזמינות שלהן תלויה באופן שבו הגיעה הבקשה.
סקריפט שרץ כ-hook של שורת הפקודה של ה-VPN הוא הקשר הרצה שונה לחלוטין. אין לו בקשת אינטרנט, אין סוקט לקוח ואין REMOTE_ADDR, ולכן קוד אינטרנט שמועתק לתוך hook מניב ערכים ריקים ולא שגויים. ל-hook יש סביבה משלו שמאכלס הדמון, והיא מתועדת בנפרד. להושיט שם יד אל REMOTE_ADDR זה להושיט יד אל משתנה שמעולם לא הוגדר.
שמרו את ההבחנה הזאת לפני שאתם משווים שני יומנים. ייתכן שאתם משווים בקשת עמוד ל-hook, וזו בכלל לא השוואה. בדקו קודם את הקשר ההרצה ואחר כך את הכתובת.
עברו על נתיב הבקשה לפני שתסמכו על המספר
הכתובת המדווחת היא ה-peer של החיבור שהשרת ראה. הכניסו כל דבר בין הלקוח לשרת הזה וה-peer משתנה. תרגום, סיום ופיזור עומסים מזיזים כל אחד את התצפית צעד אחד רחוק יותר מהמשתמש.
ארבעה נתיבים נפוצים מניבים ארבע תצפיות שונות.
| Path to the listener | What can be reported |
|---|---|
| Client routed straight to the private listener, no translation | The client's tunnel address |
| Gateway translates the source before forwarding | The gateway's translated address |
| Reverse proxy terminates the client and opens its own backend connection | The proxy's backend address |
| Load balancer in front of two proxies | Whichever hop the server treats as its peer |
רשמו את הנתיב עם שם היעד, משפחת הכתובות וכל נקודת תרגום. בלי המפה הזאת, ערך נכון וערך שגוי נראים זהים בשורת יומן. שתי שורות של תרשים חוסכות אחר צהריים של ויכוח.
החלפה מתרחשת רק במקום שבו היא מוגדרת
שרת או מסגרת יכולים להחליף בכוונה את כתובת הלקוח. המודול remote-IP של Apache והמודול real-IP של NGINX עושים זאת, והערך ש-PHP מקבל תלוי בהגדרה הזאת ובפרמטרים שמועברים למטפל הסקריפט.
לכן REMOTE_ADDR אינו תמיד ה-peer של TCP שלא נגעו בו. זה ה-peer כפי שהשרת בחר לדווח אותו לאחר שהחיל את המדיניות שלו. ההבחנה הזאת קובעת אם הערך הוא ראיה או קישוט.
שאלו את בעל השרת איזה שדה הוא הסמכותי בפריסה הזאת ואיך נשמר ה-peer המקורי כשמתרחשת החלפה. אם איש לא יכול לענות, היומן עדיין לא מוכיח דבר.
אל תקראו כותרות העברה מתוך אמון
הקורא יכול לשלוח כותרות העברה בעצמו. התייחסות לרשומה הראשונה שמופרדת בפסיק כאל כתובת משתמש מאומתת היא החלטה להאמין לכל מי שמתחבר, שזה ההיפך ממטרת הכותרת. הכותרת מתארת שרשרת, ורק שכבה מהימנה יכולה לערוב לשרשרת הזאת.
השתמשו בתמיכת ה-proxy המהימנים של השרת או המסגרת עם שרשרת ה-proxy האמיתית מוגדרת, ותנו לה לזרוק ערכים ממקורות שמחוץ לשרשרת. ניתוח שנכתב ביד הוא המקום שבו גרות רוב התקלות המעניינות.
כתובת שמדווחת על ידי proxy גם אינה משנה את מקור החבילות שחומת אש במעלה הזרם רואה. שמרו את מטא-נתוני ה-HTTP ואת סינון הרשת כתצפיות נפרדות, כי הן עונות על שאלות שונות.
השתמשו בזהות האפליקציה להחלטות
לגישה לרשומות של משתמש, הישענו על הזהות המאומתת ועל כללי ההרשאה של האפליקציה. כתובת פנימית יכולה להיות מוקצית מחדש, וכתובת מתורגמת אחת יכולה לייצג מאות משתמשים בו-זמנית. אף אחת מהתכונות האלה אינה משהו שבדיקת כתובת יכולה לתקן.
אם התפעול צריך לקשור בקשה לסשן VPN, קשרו את הכתובת הנצפית ואת חותמת הזמן לרשומות סשן סמכותיות לפי מודל התרגום שתיעדתם. זה יוצר קשר שאפשר להגן עליו; כתובת לבדה לא.
לאבחון, רשמו את השדות המעטים שאתם צריכים ולא את כל מערך השרת, שעלול לשאת כותרות וחומר אימות. המסקנה השימושית אומרת מה הערך הזה אומר בפריסה הזאת, לא איזה ערך נראה הכי כמו לקוח.