כשבונים מסך VPN בתוך אפליקציית iOS, ההפתעה הראשונה היא זו: רשימת הפרוטוקולים של אפליקציית ההגדרות אינה רשימת ה-API. מסגרת Network Extension מאפשרת לאפליקציה שלך ליצור תצורת VPN אישית אחת, בבעלות אותה אפליקציה, והיא מקבלת רק כמה אובייקטי פרוטוקול. כל השאר שאנשים מצפים לו, מ-L2TP ועד פרופיל שהורד, נמצא מחוץ למשטח הזה או שייך לאפליקציה של אפל. הכשלים שבאים אחר כך בדרך כלל אינם באגים, זה ה-API שמסרב למשימה שמעולם לא ניתנה לו.

המיתוס: ה-API הוא עורך הגדרות

סבורים שאם iOS יכול להגדיר פרופילי IKEv1, IKEv2, L2TP ו-IPsec, אפליקציה יכולה ליצור כל אחד מהם בתוכנה. זה לא נכון. המסגרת חושפת בדיוק משבצת תצורה אחת לאפליקציה הקוראת, והמשבצת הזו מקבלת רק קבוצה קטנה של מחלקות פרוטוקול ציבוריות. כל השאר שאנשים מצפים לו, מ-L2TP ועד פרופיל שהורד, נמצא מחוץ למשטח הזה או שייך לאפל.

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

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

האפשרויות שלך הן IKEv1 דרך NEVPNProtocolIPSec, IKEv2 דרך NEVPNProtocolIKEv2, ו-NETunnelProviderProtocol אם אתה משלב הרחבת מנהרת מנות משלך. תיעוד NEVPNManager מפרט את אובייקטי הפרוטוקול המקובלים. L2TP ו-PPTP לא מופיעים ברשימה הזו כי אפל לא פרסמה עבורם מחלקות. ניסיון לעשות אחד מהם מסתיים בשמירה בשגיאה, או גרוע מכך, בתצורה שהמערכת מסרבת בשקט להשתמש בה.

קוד שולחני עוקב אחר כללים אחרים. ב-macOS, SCNetworkInterfaceCreateWithInterface מערים סוג ממשק כגון L2TP מעל IPv4 ומצמיד אותו לשירות רשת, ו-networksetup -connectpppoeservice מפעיל את התוצאה. נדרשים הרשאות מנהל וכלי עזר, כי הסוד המשותף והסיסמה נכנסים למחזיק המפתחות של המערכת. העתק את העיצוב הזה ל-iOS ושום דבר לא יתקמפל.

העבר הפניה למחזיק מפתחות, לא את הסיסמה

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

אימות תעודות הולך במסלול אחר: identityData בתוספת identityDataPassword עבור בלוב PKCS#12. שליחת הבלוב הזה בתוך חבילת האפליקציה היא הרגל שהגיע מקוד הדוגמה ולא החלטת הפצה, כי הסיסמה נוסעת איתו וכל עותק של האפליקציה נושא את אותה זהות.

ההרשאה והזמינות קובעות הכול

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

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

טען, שנה, שמור ואז עקוב אחר סדר הביקוש

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

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

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

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