OpenVPN מאחורי stunnel: העבר את העטיפה, לא את הפורט 1194
שני מאזינים, שלושה פורטים. בדקו לאן ההעברה נוחתת, היכן העטיפה נקשרת, לאן היא מתחברת, מה דילגה בדיקה מקומית ושתי הזהויות.
הציבו עטיפת TLS לפני OpenVPN והפריסה מקבלת מאזין שני, שרק אחד מהם אמור אי פעם לפנות לאינטרנט. כשהמנהרה עובדת מאותה מכונה ונכשלת מבחוץ, ההעברה בדרך כלל מכוונת לאחד מהשניים הלא נכון. מה שחייב להתיישר הוא שרשרת: הכלל הציבורי מגיע לעטיפה, וחיבור הבקאנד של העטיפה עצמה מגיע לשקע ה-VPN האמיתי. ארבעה צעדים נושאים את השרשרת, וכל אחד מהם יכול לסיים את החקירה מוקדם.
שני שקעים, שני בעלים, אחד מהם ציבורי
העטיפה מסיימת TLS עבור החיבור החיצוני ומעבירה את זרם הבתים המפוענח למאזין OpenVPN TCP רגיל. אלה שקעים נפרדים עם קובצי תצורה נפרדים, כך שעריכה של אחד משאירה את השני ללא נגיעה ולכאורה בריא. זה גם אומר שהשניים יכולים להתפצל בכל פעם שאחד משתנה בלי השני.
עבודה מהמכונה עצמה מוכיחה אפוא מעט מאוד על הנתיב הציבורי. חיבור ישיר לפורט המקורי מדלג על העטיפה, חיבור לעטיפה בכתובת ה-LAN שלה מדלג על התרגום, ורק הסידור המלא בצד הלקוח מתרגל את מה שמשתמש חיצוני עושה. גם שמות צריך לקרוא בקפידה, כי localhost פירושו המארח שמריץ את אותו רכיב בדיוק, ולא המארח שאתם מקלידים עליו במקרה. שמרו על ההבחנה הזו בהערות שלכם, כי בדיקה שנרשמה בלי הצעד שהיא כיסתה מזמינה השוואה בין שני דברים שונים.
לאן ההעברה באמת נוחתת
קל יותר להחזיק את השרשרת כארבעה צעדים מאשר כשלושה מספרי פורטים, מפני שאותו מספר יכול לומר דברים שונים בכל קצה. קראו את הטבלה שורה אחר שורה: כל שורה היא שקע אחד שחייב לקבל חיבור ואז לפתוח את הבא. כששורה מכוונת לעמית הלא נכון, הסימפטום בעמודה האחרונה הוא מה שהמשתמש מדווח.
| Hop | Listens on | Must reach | Symptom when it points elsewhere |
|---|---|---|---|
| Client machine | A local plaintext port | The wrapper's public TLS address | Plain text offered to a TLS endpoint |
| Router forward | Public TCP 443 | The wrapper host on its translated port | Wrapper records no connection at all |
| Wrapper, server mode | Its accepted port, 8443 here | The native VPN socket on loopback | Handshake completes, then silence |
| Native VPN listener | Loopback TCP port | Its peer, over TCP only | A UDP socket behind a byte-stream relay |
כלל שמכוון לפורט ה-VPN המקורי במקום לעטיפה מדלג לגמרי על סיום TLS, וזו הצורה הנפוצה ביותר של הטעות הזו: הלקוח פותח לחיצת יד עם מאזין שמצפה למסגור OpenVPN, כך שהחיבור עשוי להיפתח ואז להיתקע. אמתו את הפורט המתורגם מול קובץ התצורה של העטיפה ולא מול הזיכרון, כי האדם הבא שיערוך את הקובץ הזה אולי בחר מספר אחר. שתי הפקודות שלמטה מציגות את שני הצדדים של השאלה הזו בבת אחת.
grep -nE '^[[:space:]]*(accept|connect)' /etc/stunnel/stunnel.conf
ss -lntp | grep -E ':443|:8443|:1194'
כתובת הקישור שמסרבת לך
שורת accept שנקשרת ל-127.0.0.1 עונה רק למארח עצמו, כך שהעברה שמגיעה לכתובת ה-LAN לא יכולה להתחבר והלקוח רואה סירוב שנשמע כמו בעיית מסנן מנות. הביטו בשקע לפני שנוגעים בחומת האש, כי השקע הוא התשובה הזולה יותר. או לקשור את העטיפה לממשק שההעברה מכוונת אליו, או להשאיר אותה על loopback ולגרום להעברה להגיע ל-loopback דרך משהו שבאמת עובד. אלה שני עיצובים, וכל אחד צריך כלל משלו.
ערבוב שלהם הוא הדרך שבה עטיפה עובדת הופכת בלתי נגישה מבחוץ בזמן שכל קובץ נראה תקין. הבדיקה שלמטה היא פקודה אחת, והיא עונה על שאלה שסקירת כללי חומת האש לא יכולה. אם הפלט מראה כתובת loopback בעוד ההעברה מכוונת לכתובת ה-LAN, התיקון שייך לשורת accept ולא למסנן המנות.
ss -lntp '( sport = :8443 )'
מה הבדיקה המקומית באמת הוכיחה
הצלחה שנרשמה בלי הצעד שהיא כיסתה אינה ראיה לגבי הצעדים האחרים. ציינו באיזו כתובת השתמשה הבדיקה ואיזה תהליך ענה. אחר כך חזרו על זה מחוץ לרשת ולא מטלפון באותה Wi-Fi, כי התנהגות הסיכה משתנה בין נתבים וחיבור שמעולם לא עזב את ה-LAN יכול לספק לקוח בלי שההעברה תהיה מעורבת בכלל. רק הניסיון השני הזה מתרגל את הדרך שעובר זר.
כשהניסיון נכשל, עקבו אחר חיבור אחד בשני היומנים: שורות הקבלה וההתחברות של העטיפה, ואז יומן הסשן של דמון ה-VPN עצמו. הגבול הראשון שלא רושם דבר הוא המקום שבו שייך השינוי הבא. ברגע ש-OpenVPN מתחיל להשוות אפשרויות עמית, שפטו את ההודעות האלה לפי הכללים של אותו מימוש. אזהרת אי-עקביות של link-mtu אינה קטלנית אוטומטית, נעיצת link-mtu על 1500 אינה מוכיחה שהפיצול נעצר, ומשא ומתן על צופן שייך לתצורה הפנימית של OpenVPN ולא להעברה של הנתב.
nc -vz 127.0.0.1 1194
journalctl -u stunnel -n 50 --no-pager
הבדיקות האלה מכסות את שקע הבקאנד ואת יומן העטיפה, מה שמפריד בין בקאנד מסורב לבין לחיצת יד נדחית. הריצו אותן בזמן ניסיון אחד בתהליך ולא אחריו. חותמות הזמן מניסיון אחד הן מה שעושה את ההשוואה לאמינה.
שתי זהויות, שני סדרי כשל
התעודה החיצונית שייכת לעטיפה והזהות הפנימית שייכת ל-OpenVPN, והן עשויות לבוא מרשויות שונות. השבתת אחת מהבדיקות כדי שנתיב ייראה בריא מחליפה הגנה אמיתית בתוצאה קוסמטית. שמרו על שתי הבדיקות ונפו אותן לפי הסדר, כי רצף ההודעות נוקב בשכבה: בעיית תעודה של העטיפה מופיעה לפני שמתקיים משא ומתן על אפשרות VPN כלשהי, בעוד כשל של זהות פנימית מופיע רק לאחר שהזרם מבוסס.
מדריך stunnel מגדיר במדויק accept, connect ומצב לקוח, והסעיפים האלה עונים על שאלת השקע מהר יותר מניחוש. כשאינכם יכולים עדיין לומר איזו שכבה ענתה, קראו את התעודה שהפורט הציבורי מציג עם הפקודה שלמטה. תעודת עטיפה בפלט פירושה שההעברה הגיעה לעטיפה, ודממה או שגיאת פרוטוקול פירושה שלא. ההבחנה האחת הזו חוסכת יותר זמן מכל בדיקה אחרת כאן.
openssl s_client -connect vpn.example:443 -servername vpn.example </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer