כללי יציאה 80 ו-443 לא מעבירים את הדפדפן דרך VPN
התאמת יציאה בוחרת זרמי TCP, לא דפדפן. HTTP/3 פועל מעל UDP, DNS עשוי ללכת בנתיב אחר, ומעדכן תוכנה פוגע באותו כלל שכתבת.
מישהו מבקש שהדפדפן ישתמש במנהרה, והבקשה חוזרת ככלל חומת אש שמתאים ליציאות היעד 80 ו-443. זה נראה מדויק וזה לא. התאמת יציאה בוחרת מנות לפי כותרת התעבורה שלהן, לא לפי איזו תוכנית פתחה את השקע, וגלישה מודרנית אינה מגבילה את עצמה לשתי היציאות האלה מעל TCP. הכלל יפספס חלק מהתעבורה שרצית לכלול וילכוד תעבורה שמעולם לא התכוונת לגעת בה. לפני שתכתב אותו, החלט איזה משלושה גבולות שונים אתה באמת רוצה.
הכלל מתאר מחלקת תעבורה, לא יישום
ב-Linux, התאמת יציאת יעד בודקת את כותרת ה-TCP וכלום מעליה. סימון המנות האלה והולכתן בנתיב מדיניות עובד בדיוק כמתועד, ואף אחד מהמנגנונים האלה לא יודע מה המשמעות של המטען או איזה תהליך שלח אותו. הסימן הוא מספר שמצורף למנה, לא זהות שמצורפת ליישום.
nft add rule inet mangle output tcp dport { 80, 443 } meta mark set 0x1
ip rule add fwmark 0x1 table 100
ip route add default dev wg0 table 100
שתי תוצאות נובעות מיד. מעדכן תוכנה שיוצר קשר עם TCP 443 מקבל את אותה התייחסות כמו הדפדפן, וזה עשוי להיות בסדר או להיות תקלה שמחכה למחזור העדכון הבא. ושירות אינטרנט שפורסם במכוון ביציאה אחרת, נניח 8443, נופל לגמרי מחוץ לכלל אף שהוא עדיין תעבורת האינטרנט שעניינה את המשתמש.
המספרים הם בוררים לגיטימיים כשהדרישה באמת עוסקת ביציאות האלה. הם הופכים לבדיה כשבכרטיס כתוב «דפדפן» ובמערכת הכללים מיושם טווח יציאות. הפער הזה אינו קפדנות תיעוד. הוא ההבדל בין כלל שאתה יכול להגן עליו בסקירה לבין כזה שאיש אינו יכול לבדוק.
HTTP/3 עוזב בשקט את כלל ה-TCP שלך
HTTP/3 פועל מעל QUIC, ו-QUIC נישא ב-UDP. כלל שמתאים רק ל-TCP לא יכול לראות אותו, ולכן אותו דפדפן שעומד בדף הבדיקה שלך יכול לשלוח בקשה מאוחרת ב-UDP ולעקוף את המנהרה בלי שאיש ישנה הגדרה. RFC 9114 מתאר את HTTP/3 כפרוטוקול מבוסס QUIC, ו-QUIC משתמש ב-UDP עם יציאה ברירת מחדל 443 בפריסה המקובלת.
האם דפדפן נתון ינסה HTTP/3 תלוי בהגדרות שלו, באתר ובהצלחת ניסיון קודם. זה הופך אותו לדבר גרוע לנמק עליו מהזיכרון. שאל את הכלי במקום:
curl --http3 -sS -o /dev/null -w '%{http_version} %{time_total}\n' https://example.com
ss -tunp | grep -E ':443\b'
שורת curl מדפיסה את הגרסה שנקבעה, ולכן 3 מאשר שהנתיב ב-UDP שימש. לאחר מכן רשימת השקעים מראה אם החיבור הזה קשור לממשק המנהרה או לזה הפיזי. אם HTTP/3 אינו זמין בגרסת curl שלך, הדגל נכשל בקול רם במקום לסגת בשקט, וזו הרחמים הקטנים שלו.
DNS הוא החלטה נפרדת שעליך לקבל
כלל יציאה לתעבורת אינטרנט אינו אומר דבר על פתרון שמות. הדפדפן עשוי להשתמש בפותר המערכת, בפותר שהוגדר בתוך הדפדפן או בזה שדחף החיבור האחרון. כל אחד מהם עשוי לשלוח שאילתות בנתיב שונה מזה שהכלל שלך בוחר, מה שיוצר את הפיצול הקלאסי: הדף נטען, השם נפתר במקום שלא ציפית לו, והאתר הפנימי נפתר לכתובת ציבורית או לא נפתר כלל.
החלט על כך במפורש. אם שמות פנימיים חייבים להיפתר דרך המנהרה, הפותר חייב להיות בתוכה, ומערכת הכללים חייבת להתיר DNS לפותר הזה תוך הרחקת שאילתות אחרות. אם הדפדפן משתמש ב-DNS over HTTPS מול ספק ציבורי, השאילתה עוקפת את הפותר שלך לגמרי וכלל היציאה לא יכול לעזור. כתוב את הבחירה באותו רשומת שינוי כמו כלל הניתוב, כי את שניהם קורא יחד מי שיתקן את הכשל הבא.
לאחר מכן אמת עם הפותר ולא עם הדף:
resolvectl query intranet.example.internal
resolvectl status | grep -A3 'Current DNS Server'
תשובה חסרה היא בעיית פתרון גם כשההודעה על שגיאה בדפדפן מאשימה את הרשת. שני הכשלים האלה נראים זהים למשתמש והם כרטיסים שונים לחלוטין.
שלושה גבולות, שלושה מנגנונים שונים
רוב הבלבול נעלם ברגע שאתה נוקב בגבול שאתה רוצה. הם אינם ניתנים להחלפה, ולכל אחד אופן כשל אחר בזמן נפילת מנהרה.
| What you actually want | Mechanism that fits | What it does not cover |
|---|---|---|
| These transport ports use this exit | Firewall mark plus policy route | Applications, HTTP/3 over UDP, DNS |
| This browsing session stays separate | Application-aware VPN, or a separate network namespace plus a proxy | Other applications in the same session |
| Only these private sites are reachable | Destination-based routes with private DNS | Public sites on the same address family |
פרופיל דפדפן נפרד הוא המלכודת בשורה האמצעית. הוא מפריד קובצי Cookie והיסטוריה, והוא לא משנה דבר בטבלת הניתוב של המארח, ולכן שני הפרופילים הולכים באותו נתיב. בידוד דורש משהו שהגרעין כופה, כלומר מרחב שמות, מיכל או יישום שמחזיק בממשק מנהרה משלו.
באיזו שורה שיבחר, כתוב מה אמור לקרות כשהמנהרה נופלת. נתיב מבוסס סימן שנעלם עם הממשק נופל בדרך כלל חזרה לנתיב ברירת המחדל הפיזי, וזו התנהגות fail-open. זה עשוי להיות מקובל לגלישה ובלתי מקובל לכל דבר אחר, וזו החלטה, לא פרט יישום.
בדוק את הזרמים שאתה טוען שאתה מכסה
מבחן הקבלה חייב ללכת אחרי הגבול שכתבת, לא אחרי מספרי היציאות שהיו נוחים. בחר זרם אחד שחייב לעבור במנהרה, אחד שאסור, ואחד שמשתמש בתעבורה שלא חשבת עליה:
ip route get 203.0.113.40
curl -sS -o /dev/null -w 'v4 %{http_version} %{remote_ip}\n' https://example.com
nft list ruleset | grep -A2 'dport'
חיפוש הנתיב אומר לך באיזה ממשק יעד משתמש באמת, וזו העובדה שרוב הדוחות טועים בה. שורת curl מאשרת את הגרסה שנקבעה ואת משפחת הכתובות. תדפיס מערכת הכללים תופס את הכלל שהוספת בזמן הבדיקה ושכחת להגביל, וכך סימן זמני הופך לניתוב fail-open קבוע.
תעד את שלושת הפלטים עם חותמת זמן ושמור אותם עם השינוי. כשמישהו ידווח מאוחר יותר ש«ה-VPN שבר את האינטרנט הפנימי», ההבדל בין הגבול המתוכנן לזה שיושם יהיה גלוי ברשומה ההיא, והתיקון יהיה שינוי כלל ולא ויכוח.