כיצד לבדוק את מצב ה-VPN בלי פינג ב-Android, iOS ו-Windows
פינג מוכיח שמארח אחד ענה, ולא שהמנהרה פעילה. שאלו את ה-API למצב ב-Android, ב-iOS וב-Windows, ואחר כך אמתו את המסלול שהאפליקציה שלכם באמת צריכה.
פינג אל 192.0.2.10 אומר רק שכתובת אחת השיבה להד ICMP, וזה הכול. ברשת בלי מנהרה הוא יכול להצליח בכל זאת, כי הכתובת עשויה לשבת ברשת המשנה המקומית; עם מנהרה תקינה הוא יכול להיכשל, כי השרת מפיל ICMP בזמן שהוא מגיש HTTPS. הבדיקה שהסקריפט שלכם צריך היא שאילתת מצב של הפלטפורמה בתוספת בדיקת מסלול אל היעד שהאפליקציה משתמשת בו. התייחסו אליהן כשני שדות נפרדים, ולעולם לא כבוליאני אחד.
מה באמת מוכיח מענה להד
ICMP הוא פרוטוקול נגישות שאין לו מושג של ממשקים או מנהרות. כשמגיע מענה, הגרעין מדווח שמארח השיב; הוא אינו מדווח איזה מסלול נשא את הבקשה ואיזה נשא את התשובה. סינון הופך את האות לרועש עוד יותר, כי חומת אש שחוסמת בקשות הד אינה אומרת דבר על הפורטים שמאחוריה. ופרופיל של מנהרה מפוצלת יכול להוציא את הכתובת הנבדקת בכוונה בזמן שכל יעד אחר עובד.
מה שאתם באמת רוצים לדעת הוא אם שירות מסוים שמיש במסלול שהאפליקציה עוברת בו. בחרו את המארח והפורט שהאפליקציה קוראת להם, ואז דרשו מענה בשכבת האפליקציה.
נגישות ומצב מנהרה הם שני עובדות שונות, וכל אחד מהם יכול להיות אמיתי בעוד השני שקרי. הפרדה ביניהם אומרת לכם למי שייכת התקלה. איחודם לבדיקה אחת מייצר קריאה שאיש לא יכול לנתב.
שאלו את Android על התעבורה, לא על פינג
Android עונה על שאלת המצב ישירות דרך ConnectivityManager. היכולות של הרשת הפעילה נושאות דגל תעבורת VPN, שנקבע כשהתעבורה מנותבת דרך ממשק VPN. הקריאה מקומית, זולה ובלתי תלויה בשאלה אם מארח מרוחק כלשהו משיב.
גרסת ה-Java הזאת מחזירה false במקום לזרוק חריגה כשאין רשת פעילה. מכיוון שהיא קוראת את הרשת הפעילה, היא משקפת את הפרופיל שהמשתמש בחר בהגדרות.
ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
NetworkCapabilities caps = cm.getNetworkCapabilities(cm.getActiveNetwork());
boolean tunnel = caps != null && caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
עבור התראות על שינוי, רשמו NetworkCallback במקום לסקור לפי טיימר. אל תבלבלו זאת עם VpnService.prepare, שמדווח רק אם המשתמש נתן הרשאה ל-VPN, ולא אם מנות זורמות. ביטול ההרשאה מגיע דרך VpnService.onRevoke, אך שכחת פרופיל בהגדרות אינה מייצרת שידור כלל.
iOS: שמות ממשקים הם היוריסטיקה, לא חוזה
קטעי קוד רבים ל-iOS בודקים את הגדרות הפרוקסי, מוצאים את המילון __SCOPED__ ומחפשים מפתחות ממשק כמו tap, tun, utun2, ppp או ipsec. הגישה הזאת היא מוסכמת שמות, לא ערובה מתועדת, ולכן עדכון מערכת שמשנה שם של ממשק יכול לשבור אותה. היא גם נוטה לדווח true על רשומות ישנות ששורדות את המנהרה.
כשהאפליקציה שלכם מחזיקה בתצורה, NEVPNManager נותן מצב אמיתי במקום. הוא מתאר את המנהרה שהאפליקציה שלכם הפעילה; עם VPN לכל אפליקציה, אפליקציות אחרות עשויות לעמוד לגמרי מחוץ לאותה מנהרה.
טענו מחדש את ההעדפות לפני קריאת המצב, כי הערך משתנה כשהמנהרה עולה ויורדת:
let manager = NEVPNManager.shared()
manager.loadFromPreferences { error in
let up = manager.connection.status == .connected
print(up)
}
דגל מצב של הפלטפורמה עדיין אינו מוכיח שהתעבורה מגיעה לעמית. הפער הזה הוא מה שבדיקת המסלול מכסה, ולכן בוליאני אחד אינו מספיק לתמיכה.
פרופילי Windows חושפים שדה מצב אמיתי
Windows עוקב אחר פרופילי VPN בנפרד מהמתאמים, ו-Get-VpnConnection חושף ConnectionStatus לכל פרופיל שהוא מכיר. פרופילים שנוצרו דרך לקוח Windows או חבילת אספקה מופיעים כאן. ה-cmdlet אינו גלאי מנהרות כללי.
קראו את השדה עבור פרופיל בשם, והוסיפו -AllUserConnection כשהפרופיל שייך לכל המשתמשים:
Get-VpnConnection -Name "Fabrikam" | Select-Object Name, ConnectionStatus, ServerAddress
לקוחות של צד שלישי לרוב נשארים בלתי נראים ל-cmdlet הזה גם כשהמנהרה שלהם פעילה, ולכן תוצאה ריקה פירושה לא ידוע, לא מנותק. גם רשימות מתאמים מטעות באותה מידה: מתאם של ספק יכול להישאר קיים כשהוא אינו פעיל, וחלק מהמתאמים קיימים רק במהלך הפעלה. עבור פרופיל ש-Windows מנהל, rasdial מדווח קוד יציאה שאפשר להסתעף עליו. כל אלה מתארים אמונה מקומית, לא נגישות של העמית.
מצב ועוד מסלול: הבדיקה בשני חלקים
פרופיל מחובר אינו אומר דבר על לאן המנות הולכות. מנהרה מפוצלת יכולה להשאיר את המנהרה פעילה תוך הוצאת היעד שאכפת לכם ממנו. פרופילי always-on נשארים מחוברים עם שרת מת, ומתג הרג חוסם תעבורה בכוונה כשהמנהרה נופלת.
בדקו את שתי השכבות: אשרו שתעבורת VPN או פרופיל פעילים, ואז אשרו שהיעד נפתר ועונה לאורך אותו מסלול. ב-Linux, שאלו את הגרעין באיזה ממשק הוא ישתמש:
ip route get 192.0.2.10
resolvectl query intranet.example.test
כשהלקוח מחוץ לשליטתכם, תעדו את שתי התוצאות ותנו לתבנית להצביע על השכבה. מחובר ועוד בדיקת מסלול שנכשלה מרמז על מנהרה מפוצלת, DNS או מדיניות. מנותק ועוד בדיקת מסלול שעובד פירושו שמסלול אחר נושא את התעבורה.
בדיקה שאפשר להריץ לפי הסדר
תעדו את מצב הפלטפורמה קודם, לפני שאתם משנים מצב רשת כלשהו. פתרו את שם המארח וציינו את משפחת הכתובות, כי רשומת AAAA יכולה לעבור מסלול שונה מרשומת A. פתחו את פורט השירות ודרשו מענה של אפליקציה ולא לחיצת יד בלבד. שמרו כל תצפית בשדה יומן משלה.
על מכונת Linux עם dig ו-curl, שלוש פקודות מכסות פתרון שמות, מסלול והשירות עצמו. הריצו אותן כשהמנהרה פעילה ושוב כשהיא כבויה:
dig +short intranet.example.test
ip route get 198.51.100.20
curl -sS -o /dev/null -w "%{http_code}" --max-time 8 https://intranet.example.test/health
ארבעה שדות נפרדים עדיפים על בוליאני אחד, כי מצב, DNS, מסלול ומדיניות נכשלים בנפרד ומגיעים לצוותים שונים. פינג בטרמינל נשאר בדיקת שפיות ידנית טובה. הוא הגדרה גרועה של קישוריות לאוטומציה, שבה ה-API של הפלטפורמה ובדיקת מסלול עונים על השאלה האמיתית.