Какво може да създаде NEVPNManager в iOS (и какво не може)
VPN API в iOS изгражда една конфигурация, притежавана от приложението, от три класа протоколи. L2TP, PPTP и подписаните профили не са част от тази повърхност.
Изградете екран за VPN в приложение за iOS и първата изненада е, че списъкът с протоколи в приложението Настройки не е списъкът на API. Рамката Network Extension позволява на приложението ви да създаде една лична VPN конфигурация, притежавана от това приложение, и приема само няколко обекта за протокол. Всичко останало, което хората очакват, от L2TP до изтеглен профил, стои извън тази повърхност или е частно за Apple. Провалите, които следват, обикновено не са грешки, а API, който отказва задача, която никога не му е била възлагана.
Митът: API не е редактор на настройки
Вярването е, че щом iOS може да конфигурира профили IKEv1, IKEv2, L2TP и IPsec, приложение може да създаде всеки от тях програмно. Не може. Рамката предоставя точно един слот за конфигурация на извикващото приложение и този слот приема малък набор от публични класове за протокол. Всичко останало, което хората очакват, от L2TP до изтеглен профил, стои извън тази повърхност или е частно за Apple.
Провалите, които следват, обикновено не са грешки. Те са API, който отказва задача, която никога не му е била възлагана, и решението е екранът да се проектира около това, което API притежава.
Три обекта за протокол и тези, които не съществуват
Възможностите ви са IKEv1 чрез NEVPNProtocolIPSec, IKEv2 чрез NEVPNProtocolIKEv2 и NETunnelProviderProtocol, ако доставяте собствено разширение за пакетен тунел. Справката за NEVPNManager изброява приеманите обекти за протокол. L2TP и PPTP никога не се появяват в този списък, защото Apple не е публикувала класове за тях. Опитът с който и да е от двата завършва при запазване с грешка или, по-лошо, с конфигурация, която системата тихо отказва да използва.
Кодът за настолни системи следва други правила. В macOS SCNetworkInterfaceCreateWithInterface подрежда тип интерфейс, например L2TP върху IPv4, и го прикача към мрежова услуга, а networksetup -connectpppoeservice стартира резултата. Нужни са администраторски права и помощен инструмент, защото споделената тайна и паролата отиват в системния ключодържател. Пренесете този дизайн в iOS и нищо не се компилира.
Подайте препратка към ключодържателя, не паролата
Нито един от класовете IKE не приема парола като текст. Двете свойства passwordReference и sharedSecretReference искат постоянна препратка към ключодържател, която получавате от SecItemCopyMatching, като поискате kSecReturnPersistentRef. Подаването на данните на елемента или насилственото вмъкване на низ в полето дава провал при запазване или връзка с празни идентификационни данни. Препратката е толкова трайна, колкото елементът в ключодържателя зад нея, затова елементът трябва да съществува, преди конфигурацията да бъде сглобена. Създайте го в същата транзакция като запазването и премахвате цял клас грешки в подредбата.
Удостоверяването със сертификат поема друг път: identityData плюс identityDataPassword за blob по PKCS#12. Доставянето на този blob вътре в пакета на приложението е навик, наследен от примерен код, а не решение за пускане, защото паролата пътува с него и всяко копие на приложението носи същата идентичност.
Правото и наличността определят всичко
Мениджърът може изобщо да не съществува и причината е осигуряването. Идентификаторът на приложението ви се нуждае от възможността Network Extension заедно с правото за личен VPN и профилът, който подписва сборката, трябва да носи и двете.
Пропуснете това и споделеният екземпляр връща nil, или запазването се проваля с грешка, която никога не споменава право. Наличността е другата порта. Насочете се към нещо по-старо от iOS 8 и символът липсва по време на изпълнение, така че провалът е срив или мениджър със стойност nil, а не мениджър без конфигурация. Проверете средата за изпълнение и правото, преди да отстранявате грешки в графа на обектите.
Заредете, променете, запазете, после следете реда при поискване
Третирайте жизнения цикъл като зареждане, промяна, запазване и никога не пропускайте зареждането. Докато loadFromPreferences не завърши, мениджърът не държи нищо и обектът за протокол не може да бъде прочетен или заменен.
Второ запазване заменя конфигурацията, вместо да добави още една, така че недовършено запазване може да повреди профил, който е работил. Правилата при поискване образуват подреден масив и този ред е политиката. Поставете правило за свързване отвсякъде преди правилото за прекъсване и ръчното прекъсване се следва от незабавно повторно свързване, което изглежда като дефект, но следва документираната оценка.
Преместете правилото за прекъсване отпред, когато действието на потребителя трябва да надделее. Това, което остава извън контрола на приложението, е също толкова важно. Маршрутите идват от тунела или от политиката на сървъра, а не от предпочитание, което задавате, като доставчикът на пакетен тунел ги докладва при стартиране. Приложението не може да изброява или редактира профили, инсталирани от други приложения или конфигурационни профили, затова не обещавайте екран, който показва всеки VPN на устройството.