NEVPNManager לא שומר? הסדר הוא טעינה, הפעלה, שמירה, התחברות
קוד 4 וקוד 5 בדרך כלל אומרים שהפרופיל נערך לפני הטעינה או נשמר כשהוא מושבת. תקנו את סדר הקריאות ואז בדקו את ההרשאה.
שני קודי שגיאה מסבירים את רוב הניסיונות הראשונים ב-VPN מסוג Network Extension ב-iOS: NEVPNErrorDomain Code=4 ו-Code=5. אף אחד מהם אינו תלונה של השרת. האחד מופיע כשהאפליקציה כותבת הגדרות לאובייקט שמעולם לא נקרא מהדיסק, והשני כשהכתיבה עצמה נכשלת, לרוב מפני שהפרופיל נשמר כשהוא עדיין מושבת. את שניהם מתקנים בשינוי סדר ארבע קריאות, לא בנגיעה בפרמטרים של IKEv2.
טענו קודם, אחרת אין לשמירה במה להשוות
המנהל מחזיק עותק של הפרופיל השמור, והאובייקט שאתם עורכים אינו העותק הזה עד שתקראו אותו. קראו תחילה ל-loadFromPreferences, ערכו בתוך מטפל ההשלמה שלו ואז שמרו. אם תדלגו על הקריאה, התשתית רואה אי-התאמה בין מה שיש לה לבין מה שאתם כותבים. ב-Swift הצורה זהה בכל שלב, וכל שלב שייך לסגור משלו:
let mgr = NEVPNManager.shared()
mgr.loadFromPreferences { loadErr in
guard loadErr == nil else { return }
let proto = NEVPNProtocolIKEv2()
proto.serverAddress = "vpn.example.net"
proto.username = "alice"
proto.useExtendedAuthentication = true
mgr.protocolConfiguration = proto
mgr.isEnabled = true
mgr.saveToPreferences { saveErr in
// do not start here; reload, then connect
}
}
התחלת המנהרה מתוך סגור השמירה היא אותה טעות במקום אחר. היא רצה לפני שהפרופיל נקרא שוב, כך שקראת ההתחלה רואה את המצב שבניתם ולא את המצב שנשמר. סגור השמירה מסתיים בקריאה שנייה ל-loadFromPreferences, ורק מטפל ההשלמה הזה קורא ל-startVPNTunnel.
דגל ההפעלה הוא חלק מהשמירה
פרופיל שמור אינו פעיל עד שמדליקים אותו. הגדירו isEnabled = true באותה כתיבה, אחרת הפרופיל נוחת על הדיסק מושבת ו-startVPNTunnel מסרב גם כשההגדרות מציגות תצורה שנראית שלמה.
עריכות חיצוניות הן החצי השני. אם המשתמש משנה משהו בהגדרות, או שהמכשיר עובר בין רשתות, קראו שוב לפני שתסמכו על הערכים שאתם עדיין מחזיקים בזיכרון. האובייקט לא מתבונן בשינויים האלה עבורכם. עותק מיושן הוא הדרך שבה אפליקציה כותבת פרופיל שמחזיר בשקט את עריכת המשתמש. שני שדות סמוכים יוצרים צרה שקטה באותו רגע: חוקי on-demand חייבים להיות מערך של אובייקטי חוק ולא ממלא מקום ריק, ו-disconnectOnSleep צריך לשקף את ההתנהגות שבחרתם ולא ברירת מחדל מועתקת.
רק שני פרוטוקולים זמינים לאפליקציות צד שלישי
Network Extension נותן לאפליקציות IPsec ו-IKEv2. L2TP ו-PPTP נשארים בתוך המערכת, ולכן אפליקציה שזקוקה להם לא יכולה לקבל אותם, והתשובות הריאליות הן שער עם תמיכת IKEv2 או פרופיל תצורה מנוהל.
פרטי הזדהות הולכים באותו דפוס. שימו את הסיסמה ב-Keychain והעבירו הפניה מתמשכת במקום המחרוזת. הפניה ריקה בזמן שמירה בדרך כלל אומרת שהחיפוש רץ לפני שהפריט נכתב, ולא שהמנהל שבור.
שניהם החלטות תכנון ולא עקיפות. אפליקציה ששומרת את הסיסמה בהעדפות שלה בוחרת נתיב שהתשתית אינה ממליצה עליו, והכשל שהיא מייצרת נקרא כשגיאת שמירה.
שללו את ההרשאה לפני שתכתבו מחדש קוד
כאשר loadFromPreferences אינו חוזר כלל, הסיבה הסבירה היא יכולת Network Extension חסרה או פרופיל אספקה שאינו נושא אותה. הכשל הזה תלוי במקום להחזיר שגיאה, ולכן קוד עובד נכתב מחדש שעות. בדקו את ההרשאה בגרסה החתומה שאתם מתכוונים לשלוח, כי הרצה בסימולטור והרצה במכשיר יכולות להיות שונות והמטרה שחשובה היא המכשיר. פתחו את הגדרות החתימה של המטרה ואשרו שיכולת Network Extension קיימת בדיוק עבור אותה גרסה.
פרופיל אספקה בלי ההרשאה נכשל באותה צורה בחומרה, בעוד שאותה גרסה עשויה להיטען כרגיל בסימולטור. בדקו את הארכיון החתום במכשיר אמיתי לפני שתכתבו מחדש את סדר הקריאות.
הביטו בשינויי המצב, לא בהנחות
התבוננו ב-NEVPNStatusDidChangeNotification ורשמו את manager.connection.status אחרי כל שלב. מצב שלעולם לא יוצא מ-invalid אומר שהפרופיל לא נשמר או שההרשאה חסרה. חיבור שמגיע ל-connecting ולעולם לא מתחבר מצביע על ההצעה או על פרטי הזדהות, וזו חקירה אחרת עם ראיות אחרות.
אשרו שהפרופיל מופיע תחת הגדרות, כללי, VPN, ורשמו את השגיאה מכל סגור. שתי העובדות האלה מפרידות בין באג סדר לבאג הרשאות בלי ניחושים.