Ձեր հավելվածը ասում է անջատված, ընտրացանկի տողը՝ միացված, իսկ տրաֆիկը հստակ հոսում է։ Այդ բացը ռասսի վիճակ չէ, որը շտկվում է վերստին փորձով․ հավելվածն ու թունելը առանձին պրոցեսներ են, և այն օբյեկտը, որը կարդում է ձեր կոդը, համակարգի պահած կոնֆիգուրացիայի քեշավորված պատկերն է։ Apple-ի Personal VPN մակերեսը կառավարման API է, ոչ տվյալների ուղի, և դրա տարօրինակ վարքի մեծ մասը բխում է հենց այդ մեկ փաստից։ Ահա թե ինչ է իրականում տեղի ունենում յուրաքանչյուր կանչի ժամանակ։

Կառավարչի օբյեկտը քեշավորված պատկեր է, ոչ թունելը

NETunnelProviderManager լցվում է համակարգին պատկանող նախապատվությունների պահոցից, ուստի նրա հատկությունները ոչինչ չեն նշանակում, մինչև loadFromPreferences չավարտվի։ Եթե դրանից առաջ կարդաք connection.status-ը, կստանաք լռելյայն արժեք, և դրա համար է, որ վերագործարկումից հետո առաջին կարգավիճակի թարմացումը հայտնում է անջատված, երբ թունելը միացած է։ Նախ բեռնեք, ապա կարդացեք կարգավիճակը և արձանագրության կոնֆիգուրացիան նույն ավարտի մշակիչից։ Հետագա փոփոխությունները դիտեք NEVPNStatusDidChange-ի միջոցով՝ պարբերական հարցումների փոխարեն, և նկատեք, որ ծանուցումը գործարկվում է նաև On Demand-ով սկսված միացումների համար, որտեղ ընդհանրապես հավելվածի կանչ չկա, որ ինչ-որ բան վերադարձնի։ Նույնը վերաբերում է արձանագրության կարգավորումներին․ դրանք կարդացվում են բեռնված կոնֆիգուրացիայից, ոչ թե այն բանից, ինչ հավելվածը փոխանցել է։

Թունելն ինքը ապրում է Network Extension մատակարարի պրոցեսում, ուստի հավելվածը կարող է կորցնել իր վիճակը՝ չկորցնելով միացումը։ Այն ամենը, ինչ ցույց է տալիս ինտերֆեյսը, պետք է վերակառուցվի կառավարչից, ոչ թե հիշվի նախորդ նստաշրջանից։

Մեկնարկի հերթականությունը․ պահել, բեռնել, ապա մեկնարկել

Մատակարարի վրա հիմնված միացումը պահանջում է երեք քայլ հերթականությամբ։ Գրեք մատակարարի կոնֆիգուրացիան և կանչեք saveToPreferences-ը, բեռնեք կառավարիչը, որպեսզի պահված կոնֆիգուրացիան լինի ձեր ձեռքի տակինը, ապա մեկնարկեք NETunnelProviderSession.startVPNTunnel()-ի միջոցով։ Եթե բաց թողնեք պահելը, մեկնարկին մեկնարկելու բան չի մնա․ եթե բեռնեք պահելուց առաջ, կառավարիչը դեռ արտացոլում է հին կոնֆիգուրացիան։

startVPNTunnel-ի վերադարձրած տրամաբանական արժեքը միայն ասում է, որ հարցումն ընդունվել է։ Մատակարարի մակարդակի խափանումները գալիս են ավելի ուշ՝ որպես կարգավիճակի փոփոխություն դեպի անջատված, որը դիտում եք NEVPNStatusDidChange ծանուցման միջոցով, և ծանուցման մշակիչը պետք է նորից կարդա connection.status-ը loadFromPreferences-ից հետո, որովհետև քեշավորված արժեքը կարող է դեռ հինը լինել։ Հարցման մակարդակի խափանումները անմիջապես վերադառնում են կանչի բացառություն նետող ձևից կամ startVPNTunnelAndReturnError:-ի սխալի ելքային պարամետրից։ Կոդը, որը վերադարձվող արժեքը ընդունում է որպես արդյունք, հայտնում է միացում, որը երբեք չի հաստատվել։ Մյուս լուռ խափանումը մատակարարի փաթեթի նույնացուցիչն է, որը չի համապատասխանում տեղադրված ընդլայնմանը․ հարցումը մերժվում է, և հաղորդագրության մեջ ոչինչ չի մատնանշում նույնացուցիչը։ Եթե նույնացուցիչը սխալ է, հարցումը սովորաբար անմիջապես ձախողվում է, նախքան մատակարարի որևէ մատյան տող կհայտնվի։

Մեկնարկից հետո նախապատվությունների վերաբեռնումն է, որ կարգավիճակի էկրանները ճիշտ է դարձնում։ Կառավարիչը ձեզ նոր կոնֆիգուրացիա չի հրում, երբ համակարգը փոխում է այն։

Վստահության նյութը գալիս է պրոֆիլով, երբեք՝ հավելվածի կոդից

Հավելվածը չունի աջակցվող եղանակ արմատային վկայական ավելացնելու iOS-ի վստահության պահոցին, ուստի Personal VPN կոնֆիգուրացիան կարող է հղում անել միայն այն նյութին, որին սարքն արդեն վստահում է․ տեղադրված պրոֆիլի, սարքի կառավարման կամ համակարգի կողմից այլ պատճառներով վստահված CA-ի ստեղծած շղթային։ Հավելվածը, որը առաջին մեկնարկին ստեղծում է իր սեփական CA-ն և ակնկալում, որ համակարգը կընդունի այն, կձախողվի մատակարարի ներսում վավերացման ժամանակ, որտեղ հավելվածի ինտերֆեյսը չի կարող տեսնել պատճառը։

Վերաբերվեք այդ սահմանին որպես այն դիզայնական սահմանափակումը, որ կա, և առաքեք վստահության խարիսխը գրանցման պրոֆիլի հետ միասին։ VPN նույնականացումը առանձին պահեք վստահության որոշումից, որովհետև դրանք ձախողվում են տարբեր տեղերում, և տարբեր մարդիկ են դրանք վրիպազերծում։

Հաշվիչները գալիս են ինտերֆեյսից, ոչ VPN API-ից

Կառավարիչը բացահայտում է կարգավիճակ և կոնֆիգուրացիա, և ոչինչ, որ բայթեր հաշվի յուրաքանչյուր թունելի համար։ Եթե օգտագործման թվեր են պետք, կանչեք getifaddrs()-ը և կարդացեք if_data-ը համապատասխան ինտերֆեյսի համար․ en0-ը Wi-Fi-ի համար, pdp_ip ինտերֆեյսները բջջայինի համար, և utun սարքը հենց թունելի համար։ utun հաշվիչները նկարագրում են ներքին տրաֆիկը և ներառում են արձանագրության վերածախսը։

Այդ թվերը գնահատականներ են, ոչ հավելվածով հաշվառում, և դրանք զրոյանում են, երբ ինտերֆեյսը նորից ստեղծվի։ Նշեք դրանք այդպես ինտերֆեյսում, այլապես ինչ-որ մեկը կօգտագործի դրանք հաճախորդին հաշիվ տալու համար։ Եթե հավելվածով թվեր են պետք, բոլորովին այլ մեխանիզմ է պետք, ոչ թե այս դաշտերի ավելի լավ ընթերցում։

Մաքրումը պատկանում է stopVPNTunnel-ին, ոչ ավարտին

applicationWillTerminate-ը ձեզ մի քանի վայրկյան է տալիս, նախքան համակարգը կարող է սպանել պրոցեսը, ինչը հուսալի տեղ չէ միացումը քանդելու համար։ Ուղարկեք կանգը stopVPNTunnel()-ին կամ մշակեք այն մատակարարի կանգի հետկանչում, և պահեք այն կառավարչի կամ կոնֆիգուրացիայի նույնացուցիչը, որով սկսել եք, որպեսզի կանգը թիրախավորի այդ միացումը, այլ ոչ սարքի բոլոր կոնֆիգուրացիաները։

Պահեք այդ նույնացուցիչը այն պրոֆիլի կողքին, որին պատկանում է, քանի որ կառավարչի օբյեկտը չի գրանցում, թե որ կոնֆիգուրացիան է ընտրել օգտատերը։ Եվ հիշեք, որ On Demand-ի բարձրացրած միացման հետևում ընդհանրապես հավելվածի կանչ չկա, ուստի կարգավիճակի էկրանը դեռ պետք է բեռնի նախապատվությունները, նախքան ինչ-որ բան նկարելը։

Առնչվող հոդվածներ