המנהרה מתחברת מקו ביתי ונתקעת ברשת של מלון או משרד, והעברת השרת לפורט 443 לא שינתה דבר. התוצאה הזאת נפוצה מספיק כדי שיש לה צורה: הפורט היה החלק הקל, ושאר ההחלטה שייכת לכל מה שיושב בין הלקוח לשרת. שתי שאלות מכריעות את רוב המקרים, ואף אחת מהן לא עוסקת בצפנים. האם הרשת מקבלת לחיצת יד TLS לכתובת הזאת, והאם הלקוח שומר על מסלול לעטיפה שלו בזמן שהמנהרה פעילה?

לחיצת היד מסגירה יותר מהמספר

מאזין VPN מקורי על TCP 443 מדבר בפרוטוקול שלו מהמנות הראשונה. ל-ClientHello יש שדה גרסה, ערך אקראי ורשימת הרחבות, והתקן שקורא כמה מאות בתים יכול להבחין בהבדל בלי לפענח דבר. מספרי פורטים זולים לסיפוק, וצורת הפרוטוקול היא מה שהמסנן באמת בודק. כללים נכתבים בדרך כלל גם לפי פרוטוקול, ולכן מדיניות שבודקת TLS לא אומרת דבר על UDP.

פרוקסי שקוף שמתעקש על הפעלת TLS תקינה מפיל את החיבור בזמן ההקמה, לעיתים קרובות אחרי שלחיצת היד של TCP הושלמה. הפרט הזה חשוב בהמשך, כי פירושו שהלוג של הלקוח נעצר אחרי שהסוקט נוצר.

עטיפת הזרם יוצרת שתי נקודות כשל

עטיפת TLS כמו stunnel מחזירה את הצורה הצפויה: הלקוח מתחבר למאזין מקומי, העטיפה פותחת הפעלת TLS אמיתית לשרת בפורט 443, ועטיפה שנייה בשרת מעבירה את הבתים המפוענחים לדמון ה-VPN. ההפעלה החיצונית נראית עכשיו כמו כל חיבור HTTPS אחר. דמון ה-VPN בשרת אמור להאזין רק על loopback, כי שום דבר מחוץ לעטיפה לא צריך להגיע אליו.

שלושה דברים נפרדים חייבים להסתדר יחד בתכנון הזה. פרופיל הלקוח מצביע על המאזין המקומי, תעודת השרת תואמת לשם שהלקוח מאמת, וההעברה בצד השרת מכוונת לפורט שהדמון באמת משתמש בו. טעות באחד מהם והחיבור מת לפני שמגיעים לשכבת ה-VPN. אז אי-התאמה בתעודה מופיעה כשגיאת עטיפה ולא כשגיאת VPN, ולכן שווה לקרוא את שני הלוגים זה לצד זה.

המסלול אל העטיפה הוא המלכודת

ברגע שהמנהרה עולה, מסלול ברירת המחדל מצביע לתוכה, ולהפעלת ה-TLS החיצונית דרוש נתיב שלא נכנס למנהרה שהיא נושאת. לקוח VPN רגיל מגן על הכתובת שאליה הוא מחייג; לקוח עטוף מחייג ל-loopback שלו עצמו, ולכן כתובת היעד של העטיפה בלתי נראית להגנה הזאת.

sudo ip route add 198.51.100.20 via 192.168.0.1
sudo openvpn --config client.ovpn
sudo ip route del 198.51.100.20

הכתובות המדויקות הן למלא על ידכם, והמסלול חייב להתקיים לאורך כל חיי החיבור, לא רק בהפעלה. סקריפט עטיפה קטן שמוסיף את המסלול לפני הלקוח ומסיר אותו אחריו אמין יותר מפקודה זכורה.

ב-Android המקבילה לחריגה הזאת היא הגדרה לכל אפליקציה: הוציאו את אפליקציית העטיפה מהמנהרה כדי שהתעבורה שלה תצא דרך החיבור הסלולרי. בלי ההוצאה העטיפה מנותבת לתוך המנהרה שהיא מנסה לבנות, ולולאת ההתחברות מחדש נראית כמו בעיית שרת.

קראו את התזמון לפני שמשנים משהו

הפעלה שמתה אחרי אותו מרווח בכל פעם היא חתימת מדיניות ולא כשל הצפנה, ומגבלות זרימה ארוכות טווח יוצרות בדיוק את הדפוס הזה. חיבור שמאופס מיד אחרי לחיצת היד מרמז על פרוקסי שלא אהב את שרשרת התעודות.

השוו את מנפיק התעודה של אתר HTTPS רגיל משתי הרשתות. אם המנפיק שונה ברשת המוגבלת, משהו מסיים TLS באמצע, ושום עטיפה לא תשרוד את היירוט הזה בלי שינוי. אותה השוואה אומרת לכם אם החסימה מכוונת לשם השרת שלכם או לכל הפעלת TLS בכתובת הזאת.

רשמו את ההתנהגות שנצפתה: כמה זמן ההפעלה החזיקה, אם הסוקט נפתח, אם העטיפה תיעדה לחיצת יד. כל אחד מאלה מצמצם את המבחן הבא.

בדקו משתנה אחד בכל פעם

בדקו קודם UDP, כי כמה רשתות מפילות אותו לגמרי וכשל UDP לא אומר דבר על 443. אחר כך נסו TCP 443 בלי העטיפה, ואחר כך את העטיפה בפורט 443. קראו את הלוג של הלקוח בכל שלב והפסיקו ברגע שההתנהגות משתנה.

שנו רכיב אחד בכל ניסיון. פורט חדש, עטיפה חדשה וצופן חדש באותה ריצה משאירים אתכם בלי יכולת לומר איזה מהשלושה היה חשוב.

מאמרים קשורים