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

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

הפרופיל מאחסן ידית, לא את הסוד

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

אתם בונים את ההפניה הזו בכך שאתם מבקשים אותה ממחזיק המפתחות, וזו בקשה שונה מהבקשה של הנתונים:

let query: [String: Any] = [
  kSecClass as String: kSecClassGenericPassword,
  kSecAttrService as String: "vpn-credentials",
  kSecAttrAccount as String: "user",
  kSecReturnPersistentRef as String: true,
  kSecMatchLimit as String: kSecMatchLimitOne
]

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

למה ה-API עונה -50

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

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

אותו חוסר התאמה מסביר פרופיל שנשמר בלי תלונה ואז לא מתחבר: מה שנשמר הוא blob, לא ידית, ולדמון אין מה לפתור.

נשמר היטב, נכשל בזמן החיבור

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

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

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

הנגישות קובעת אם אתחול יעבוד

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

בחירת המחלקה המחמירה יותר מפתה, והיא בדיוק מה ששובר פרופיל on-demand בטלפון נעול.

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

רוטציה היא המקום שבו פרופילים שמורים נרקבים

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

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

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