Twee foutcodes verklaren de meeste eerste pogingen met een Network Extension VPN op iOS: NEVPNErrorDomain Code=4 en Code=5. Geen van beide is een klacht van de server. De ene verschijnt wanneer de app instellingen schrijft in een object dat nooit van schijf is gelezen, de andere wanneer het schrijven zelf mislukt, meestal omdat het profiel wordt opgeslagen terwijl het nog uitgeschakeld is. Beide worden verholpen door de volgorde van vier aanroepen te wijzigen, niet door aan de IKEv2-parameters te komen.

Laad eerst, anders heeft het opslaan niets om mee te vergelijken

De manager houdt een kopie van het opgeslagen profiel, en het object dat je bewerkt is die kopie niet voordat je hem leest. Roep eerst loadFromPreferences aan, bewerk binnen de completion-handler en sla dan op. Sla je het lezen over, dan ziet het framework een verschil tussen wat het heeft en wat je schrijft. In Swift is de vorm bij elke stap hetzelfde, en elke stap hoort bij zijn eigen closure:

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
    }
}

De tunnel starten van binnenuit de opslag-closure is dezelfde fout op een andere plek. Het draait voordat het profiel opnieuw is gelezen, dus de startaanroep ziet de toestand die je hebt gebouwd en niet de toestand die is opgeslagen. De opslag-closure eindigt met een tweede loadFromPreferences, en alleen die completion-handler roept startVPNTunnel aan.

De activeringsvlag maakt deel uit van het opslaan

Een opgeslagen profiel is inactief tot het wordt aangezet. Stel isEnabled = true in dezelfde schrijfactie in, anders belandt het profiel uitgeschakeld op schijf en weigert startVPNTunnel zelfs als Instellingen een configuratie tonen die compleet lijkt.

Externe bewerkingen zijn de andere helft. Als de gebruiker iets in Instellingen wijzigt, of het apparaat tussen netwerken beweegt, lees dan opnieuw voordat je de waarden vertrouwt die je nog in het geheugen hebt. Het object observeert die wijzigingen niet voor je. Een verouderde kopie is de manier waarop een app een profiel schrijft dat de bewerking van de gebruiker stil terugdraait. Twee aangrenzende velden veroorzaken op hetzelfde moment stille problemen: on-demand-regels moeten een array van regelobjecten zijn en geen lege plaatshouder, en disconnectOnSleep moet het gedrag weerspiegelen dat je hebt gekozen en niet een gekopieerde standaardwaarde.

Slechts twee protocollen zijn beschikbaar voor apps van derden

Network Extension geeft apps IPsec en IKEv2. L2TP en PPTP blijven binnen het systeem, dus een app die ze nodig heeft kan ze niet krijgen, en de realistische antwoorden zijn een IKEv2-compatibele gateway of een beheerd configuratieprofiel.

Inloggegevens volgen hetzelfde patroon. Zet het wachtwoord in de Keychain en geef een blijvende referentie door in plaats van de tekenreeks. Een nulreferentie bij het opslaan betekent meestal dat de opzoeking liep voordat het item werd geschreven, niet dat de manager kapot is.

Beide zijn ontwerpbeslissingen en geen omwegen. Een app die het wachtwoord in zijn eigen voorkeuren houdt, kiest een pad dat het framework afraadt, en de fout die dat oplevert leest als een opslagfout.

Sluit de entitlement uit voordat je code herschrijft

Wanneer loadFromPreferences helemaal niet terugroept, is de waarschijnlijke oorzaak een ontbrekende Network Extension-mogelijkheid of een provisioning-profiel dat die niet draagt. Die fout blijft hangen in plaats van een fout te geven, en daarom wordt werkende code urenlang herschreven. Controleer de entitlement op de ondertekende build die je wilt leveren, want een simulatorrun en een run op een apparaat kunnen verschillen en het doel dat ertoe doet is het apparaat. Open de ondertekeningsinstellingen van het doel en bevestig dat de Network Extension-mogelijkheid voor precies die build aanwezig is.

Een provisioning-profiel zonder de entitlement faalt op dezelfde manier op hardware, terwijl dezelfde build in de simulator normaal kan laden. Test het ondertekende archief op een echt apparaat voordat je de volgorde van de aanroepen herschrijft.

Let op de statusveranderingen, niet op aannames

Observeer NEVPNStatusDidChangeNotification en log manager.connection.status na elke stap. Een status die nooit invalid verlaat, betekent dat het profiel niet is opgeslagen of dat de entitlement ontbreekt. Een verbinding die connecting bereikt en nooit verbindt, wijst op het voorstel of de inloggegevens, en dat is een ander onderzoek met ander bewijs.

Bevestig dat het profiel verschijnt onder Instellingen, Algemeen, VPN, en noteer de fout uit elke closure. Die twee feiten scheiden een volgordefout van een rechtenfout zonder giswerk.

Gerelateerde artikelen