העברת פורט לעומת גישה ב-VPN: לאן החבילה באמת הולכת
העברת פורט כותבת מחדש את היעד ועוצרת שם; VPN עוטף את החבילה קודם. ראו איזו שכבה כל אחת משנה ומה זה אומר ל-HTTPS.
שני עיצובים, אפליקציית HTTPS אחת, והחבילה עוברת מסלול שונה בכל אחד. העברת פורט משנה היכן החבילה נמסרת ומשאירה את השאר ללא שינוי. VPN נושא את החבילה בתוך חבילה אחרת קודם, ולכן המאזין של האפליקציה רואה מקור אחר ומטען מרבי קטן יותר. ההצפנה שאנשים מתווכחים עליה קיימת בשני המקרים, כי האפליקציה היא עדיין HTTPS; מה ששונה הוא מי יכול לפתוח חיבור ומה הרשת שבדרך יכולה לצפות בו. ההבחנה הזו מכריעה את רוב השאלות המעשיות.
כלל DNAT כותב מחדש את היעד ועוצר שם
בשער Linux, פרסום שירות פירושו כלל בשרשרת PREROUTING של טבלת nat, או המקבילה ב-nftables. הכלל מתאים לכתובת ולפורט הציבוריים, ואז כותב מחדש את היעד לכתובת הפרטית של האפליקציה. כתובת המקור, פורט המקור והמטען נשארים ללא שינוי, ו-conntrack רושם את המיפוי כדי שהתשובות ייכתבו מחדש ביציאה. ההתנהגות היא מודל תרגום הכתובות המסורתי המתואר ב-RFC 3022.
sudo iptables -t nat -A PREROUTING -d 203.0.113.10 -p tcp --dport 443 \
-j DNAT --to-destination 10.20.30.40:443
sudo iptables -t nat -L PREROUTING -n -v
sudo conntrack -L -p tcp --dport 443
המאזין של האפליקציה לעולם לא לומד שהחיבור הגיע דרך תרגום. הוא רואה את כתובת המקור האמיתית של הלקוח, מה שמועיל ליומני גישה ולמגבלות קצב, והוא עונה לכתובת הפרטית כי conntrack הופך את המיפוי. שום דבר במסלול הזה לא מפענח או מצפין מחדש: TLS עדיין פועל בין הלקוח לתעודה של האפליקציה עצמה.
הכלל גם קובע את מצבי הכשל שתפגשו בהמשך. אם השער מעביר אבל למארח האפליקציה אין מסלול חזרה אל הלקוח, התשובות יוצאות עם מקור שגוי ולחיצת היד נתקעת. אם כלל שני מתאים ראשון, הסדר מכריע את התוצאה, ו-iptables -t nat -L -n -v מציג את המונים שמוכיחים איזה כלל לקח את החבילה.
המנהרה עוטפת את החבילה לפני שהמאזין רואה אותה
VPN לא מפרסם את האפליקציה בכלל. הלקוח בונה חבילה חיצונית הממוענת לכתובת הציבורית של השער, מצפין בתוכה את החבילה הפנימית, והשער מפענח ומנתב את החבילה הפנימית ליעד הפרטי. ב-WireGuard התעבורה החיצונית היא UDP, בדרך כלל בפורט גבוה; ב-OpenVPN מעל TCP 443 החבילה החיצונית נראית כמו TLS לכל דבר שצופה במסלול.
בתוך המנהרה החבילה הפנימית שומרת על כתובות פרטיות: כתובת המנהרה של הלקוח, נניח 10.8.0.6, והאפליקציה ב-10.20.30.40. לכן המאזין רואה מקור מבריכת המנהרה, וכל לקוח חולק את השער הזה כקפיצה הבאה. יומני גישה מאחורי VPN מציגים לעתים קרובות את השער ולא את המשתמש בדיוק מהסיבה הזו, אלא אם השער שומר על המקור המקורי.
העטיפה עולה במקום בכותרת, וזהו ההבדל היחיד ברמת המנגנון שיש לו תוצאה מדידה. כותרת IP חיצונית ועוד UDP ועוד הכותרת של WireGuard עצמו אוכלות מה-MTU של המסלול, ולכן חבילות גדולות חייבות להתפצל או שמחסנית ה-TCP הפנימית חייבת להגביל את ה-MSS שלה. העברה שעובדת במסלול המועבר עלולה להיתקע במנהרה כשהתקן ביניים מפיל את ה-ICMP שהיה מסמן את ה-MTU הקטן יותר.
ip route get 10.20.30.40
ping -M do -s 1400 10.20.30.40
sudo iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
החשיפה נקבעת בכניסה, לא בצופן
שני העיצובים מסתיימים באותו מאזין TLS, ולכן שניהם יורשים את אותה תעודה, את אותן גרסאות פרוטוקול ואת אותה התחברות לאפליקציה. מה שמשתנה הוא מי רשאי להתחיל לחיצת יד. בהעברה ציבורית, כל מארח שמגיע אל 203.0.113.10:443 מקבל לחיצת יד TCP ו-TLS ClientHello לפני שהרשאת האפליקציה שלכם נבדקת בכלל. בגישה דרך מנהרה בלבד, המאזין נגיש רק מכתובות שהשער מנתב לתוך המנהרה, וה-SYN של זר מת במדיניות השער.
ההבדל הזה עוסק בנגישות, לא בסודיות. שירות HTTPS מועבר אינו טקסט גלוי, ו-VPN לא מבטל את הצורך באימות אפליקציה: קבלה למנהרה עונה אם התקן רשאי לשלוח חבילות לרשת הזו, בעוד שאפליקציית הקבצים עונה אם משתמש רשאי לקרוא מסמך. ערבוב השניים הוא הדרך שבה צוותים מגיעים ל-VPN שמעניק את כל ה-LAN ולאפליקציה עם סיסמה משותפת אחת.
בדקו את המאזין ואת המדיניות בנפרד, כי כל אחד מהם יכול להיות רחב ממה שאתם מניחים:
sudo ss -ltnp 'sport = :443'
sudo nft list ruleset
openssl s_client -connect 203.0.113.10:443 -servername files.example.com </dev/null
אם ss מראה שהמאזין כרוך אל 0.0.0.0, האפליקציה נגישה מכל מקום שבו ניתוב ומדיניות חומת האש מאפשרים, וההעברה היא רק אחת מדרכי הכניסה. כריכה לכתובת הפרטית, או הגבלת טווח המקורות בחומת האש, היא החלטה נפרדת מבחירת VPN, והיא ההחלטה שבאמת מצמצמת את החשיפה.
מדדו את המסלול, לא את התווית
כשמישהו טוען שההעברה מהירה יותר, ההשוואה ההוגנת מחזיקה את כל השאר קבוע: אותו לקוח, אותה רשת גישה, אותו קובץ, אותה תצורת TLS, אותו מארח אפליקציה. הריצו את ההעברה פעמיים לכל מסלול ותעדו זמן כולל, מספר כשלים והיענות, לא את הפלט של מבחן מהירות לא קשור.
curl -sS -o /dev/null -w '%{time_connect} %{time_appconnect} %{time_total}\n' \
https://files.example.com/report.pdf
mtr -rwc 20 203.0.113.10
mtr -rwc 20 10.20.30.40
המספרים האלה מפרידים בין הקמת החיבור לזמן ההעברה, וזה חשוב כי שני המסלולים נבדלים בדרך כלל בהשהיה הלוך ושוב וב-MTU ולא בעלות הצופן. עבודת TLS מתרחשת בקצוות בשני העיצובים, ומנהרה מוסיפה עטיפה, מסלול אחר ואולי שער עמוס יותר. אם מסלול המנהרה ארוך יותר או שהשער שלו עמוס, ההבדל שייך למסלול ולא למילה הצפנה.
בחרו את מדיניות הכניסה שהשירות באמת צריך, ואז החליטו אם הבדל מדוד מצדיק לשנות אותה. העברה ציבורית מתאימה לשירות שמיועד לאינטרנט הפתוח, עם הגבלות מקור, TLS מעודכן וניטור מלפנים. גישה דרך מנהרה בלבד מתאימה לכלי פנימי שמשתמשיו כבר רשומים, בתנאי שהניתוב בשער וההרשאות באפליקציה שניהם צרים יותר מכל ה-LAN.
לפני שתכריזו שהעיצוב הושלם, אשרו ארבעה דברים: לאיזו כתובת המאזין כרוך, איזה כלל או מסלול מכניס את החבילה, אם מסלול החזרה עובד מכתובת הלקוח האמיתית, ואם מטענים גדולים שורדים את ה-MTU. לכל אחד מאלה יש פקודה למעלה, ואף אחד מהם לא נענה במילה מאובטח או בתרשים רוחב פס.