מדוע Port-Share גורם לכל מבקרי האתר להיראות כמו localhost
ה-backend רואה את קפיצת ההעברה, לא את הדפדפן. בדקו היכן הולכת לאיבוד כתובת המקור, ואז החליטו איזה רכיב רשאי לערוב לה.
כל שורה ביומן הגישה מציגה את אותה כתובת loopback, בעוד הדף עצמו נטען והתעודה נבדקת כראוי. שום דבר לא שבור במובן של אי-נגישות, וזו הסיבה שזה שורד חודשים. מה שנשבר הוא הייחוס: ה-backend של האינטרנט רושם את כתובת הקפיצה שהעבירה את החיבור, וכל החלטה מאוחרת שסמכה על היומן ירשה את אותה תשובה שגויה.
הבדיקות שלהלן הולכות מהכבל פנימה. עצרו בבדיקה הראשונה שמסבירה את הערך שאתם רואים, כי כל שלב מאוחר מניח שהקודמים כבר נכונים. אף אחת מהן לא דורשת לנחש את תצורת החזית.
עקבו אחרי שני החיבורים, לא אחרי שורת היומן
Port-Share מרבב שני פרוטוקולים על מאזין TCP אחד. OpenVPN בודק את הבתים הראשונים של חיבור נכנס, שומר עליו כשהוא נראה כמו הפרוטוקול שלו, ומעביר כל דבר אחר ליעד שני. היעד הזה הוא בדרך כלל שרת אינטרנט באותו מארח, ולכן לסוקט שהשרת קיבל יש את תהליך OpenVPN כעמית.
ss -ltnp 'sport = :443'
ss -tnp 'dport = :8080'
הפקודה הראשונה מראה למי שייך המאזין הציבורי. השנייה מראה את החיבורים שמגיעים לפורט של ה-backend, וכתובת העמית שלהם היא זו שיומן הגישה ידפיס. אם העמית הזה הוא loopback, היומן מדויק והמידע אבד שכבה אחת קודם. שינוי שם השדה ביומן או הפעלת מודול IP של לקוח לא יחזירו כתובת שהחיבור מעולם לא נשא.
זו הבדיקה שמכריעה את כל השאר. אם העמית של ה-backend הוא כתובת הדפדפן, שיתוף הפורט אינו הבעיה שלכם ותבנית היומן היא הבעיה.
העברת תעבורה אינה הזרקת כותרת
המעביר מזיז בתים. הוא אינו מנתח HTTP, ולכן אינו יכול להכניס כותרת לבקשה שהוא לעולם לא קורא כבקשה, ואינו יכול להוסיף דבר לזרם TLS שהוא מעביר ללא נגיעה. מודול שמצפה לכותרת פרוקסי ימשיך לחכות לכזו שאף רכיב אינו מייצר.
שני מנגנונים יכולים לשאת את הכתובת המקורית, ושניהם דורשים הסכמה בשני הקצוות. פרוטוקול PROXY מוסיף כותרת קטנה לתחילת החיבור, וה-backend חייב להיות מוגדר לצפות לה; backend שאינו מצפה לה יתייחס לבתים האלה כתחילת הבקשה וייכשל בדרך מבלבלת. כותרות פרוקסי מהימנות כמו X-Forwarded-For עובדות כאשר פרוקסי שמבין HTTP מגדיר אותן ואומרים ל-backend אילו עמיתים רשאים לאשר אותן.
אף אחד מהשניים אינו אוטומטי, ואף אחד אינו בטוח כברירת מחדל. backend שמאמין לכל כותרת מועברת נכנסת מאפשר ללקוח לבחור את כתובתו שלו, מה שהופך אי-דיוק ביומן לעקיפת בקרת גישה. הריצו את ההדגמה פעם אחת במארח בדיקה לפני שתסמכו על כותרת כלשהי בנתיב ייצור.
curl -sS -H 'X-Forwarded-For: 127.0.0.1' https://site.example.com/health
grep -F '127.0.0.1' /var/log/nginx/access.log | tail -n 3
ספריית מיפוי המקור האופציונלית
לשיתוף הפורט יש ארגומנט ספרייה אופציונלי שרושם מיפוי בין כתובת המקור המקורית לחיבור ההעברה, בפלטפורמות שבהן התכונה מיושמת. מצופה שהצד האינטרנטי יעיין במיפוי הזה; זו אינה כותרת, והיא אינה מוזרקת לבקשה.
כדאי להכיר את העיצוב הזה כי הוא מסביר מדוע פריסות מסוימות מדווחות על כתובות אמיתיות ואחרות לא, עם תצורת חזית שנראית זהה. ההבדל הוא בצד הקולט, והוא בדרך כלל חי במודול או בטלאי שרוב שרתי האינטרנט הארוזים אינם מפעילים כברירת מחדל. קראו בתיעוד של שרת האינטרנט שלכם על הקרס המדויק שהוא מציע, ואשרו שהמודול נטען במקום להניח זאת.
אם תלכו בדרך הזו, התייחסו אליה כאינטגרציה של שני חצאים: המיפוי שהמעביר כותב והחיפוש שה-backend מבצע. אמתו את שניהם, ואשרו שהספרייה שורדת הפעלה מחדש ואינה גדלה ללא גבול במאזין עמוס.
החליטו איזה רכיב ערב לכתובת
לפני שינוי התצורה, תנו שם לרכיב הרשאי לאשר כתובת לקוח ולרכיבים הרשאים להאמין לו. תשובה אחת כתובה מונעת את הסחיפה הרגילה, שבה שלוש שכבות שונות סומכות כל אחת על מקור אחר.
שלושה עיצובים מכסים את רוב הצרכים. הפרידו בין המאזין הציבורי למאזין האינטרנטי, כך ששרת האינטרנט רואה עמיתים אמיתיים ואין בעיית ייחוס. הציבו פרוקסי הפוך שמבין HTTP, סיימו או נתחו את הבקשה שם, ותנו לו להגדיר כותרת מועברת ל-backend שסומך רק על אותו פרוקסי. או השאירו את שיתוף הפורט והסכימו שהיומנים מציגים את הקפיצה, עם כללי גישה שנכתבו נגד זהות האפליקציה ולא נגד כתובת.
מה שלא עובד הוא להתייחס לכתובת loopback מועברת כהוכחה שהבקשה מקורה במכונה הזו. המסקנה הזו היא בדיוק הפוכה: הכתובת נוכחת דווקא מפני שרכיב מקומי יצר את החיבור. כלל שנכתב כך מקבל כל מי שמצליח להגיע למאזין.
בדקו את הכלל, לא את הדף
דף שנטען מוכיח שמסלול ההעברה עובד ואינו אומר דבר על ייחוס. בדקו את צרכן הכתובת: כלל הגישה, מגבלת הקצב, רשומת הביקורת, החיפוש הגיאוגרפי.
curl -sS -o /dev/null -w '%{http_code}\n' https://site.example.com/
tail -n 5 /var/log/nginx/access.log
grep -c '' /var/log/nginx/access.log
השוו בקשה חיצונית מורשית לרשומות של החזית ושל ה-backend גם יחד, ואשרו שכלל שאמור לחסום עדיין חוסם וכלל שאמור לאפשר עדיין מאפשר. אם שורת היומן נכונה אך הכלל עדיין מתנהג כאילו כולם מקומיים, הכלל קורא שדה אחר מזה שתיקנתם.
סיימו בכך שתכתבו את שרשרת הייחוס בהערות הפריסה: איזה מאזין, איזה מעביר, איזו כותרת או מיפוי, ואיזה backend מוגדר לסמוך עליה. האדם הבא שיקרא שורת יומן יזדקק לכל ארבעתם, והיעדר ההערה הזו הוא הדרך שבה אותו כרטיס נפתח מחדש שנה אחר כך. שמרו אותה לצד התצורה ולא בשרשור צ'אט.