När du bygger en VPN-skärm i en iOS-app är den första överraskningen att protokolllistan i Inställningar-appen inte är API-listan. Network Extension-ramverket låter din app skapa en personlig VPN-konfiguration, ägd av den appen, och den accepterar bara några få protokollobjekt. Allt annat folk förväntar sig, från L2TP till en nedladdad profil, ligger utanför den ytan eller är Apples privata. Felen som följer är oftast inte buggar, det är API:t som nekar ett jobb det aldrig fick.

Myten: API:t är en Inställningar-redigerare

Man tror att eftersom iOS kan konfigurera IKEv1-, IKEv2-, L2TP- och IPsec-profiler kan en app skapa vilken som helst av dem programmatiskt. Det kan den inte. Ramverket exponerar exakt en konfigurationsplats för den anropande appen, och den platsen accepterar bara en liten uppsättning offentliga protokollklasser. Allt annat folk förväntar sig, från L2TP till en nedladdad profil, ligger utanför den ytan eller är Apples privata.

Felen som följer är oftast inte buggar. Det är API:t som nekar ett jobb det aldrig fick, och lösningen är att utforma skärmen kring det API:t äger.

Tre protokollobjekt och de som inte finns

Dina alternativ är IKEv1 via NEVPNProtocolIPSec, IKEv2 via NEVPNProtocolIKEv2, och NETunnelProviderProtocol om du levererar ett eget pakettunnel-tillägg. NEVPNManager-referensen listar de accepterade protokollobjekten. L2TP och PPTP förekommer aldrig i den listan eftersom Apple inte publicerade klasser för dem. Att försöka med någon av dem slutar vid sparning med ett fel, eller värre, med en konfiguration som systemet tyst vägrar använda.

Skrivbordskod följer andra regler. På macOS staplar SCNetworkInterfaceCreateWithInterface en gränssnittstyp som L2TP över IPv4 och kopplar den till en nätverkstjänst, och networksetup -connectpppoeservice startar resultatet. Administratörsrättigheter och ett hjälpverktyg krävs, eftersom den delade hemligheten och lösenordet hamnar i systemets nyckelring. Kopiera den designen till iOS och ingenting kompileras.

Skicka en nyckelringsreferens, inte lösenordet

Ingen av de två IKE-klasserna accepterar ett lösenord som text. De två egenskaperna passwordReference och sharedSecretReference vill ha en beständig nyckelringsreferens, som du hämtar från SecItemCopyMatching genom att begära kSecReturnPersistentRef. Att skicka objektets data, eller att trycka in en sträng i fältet, ger ett sparningsfel eller en anslutning med tomma uppgifter. Referensen är bara så hållbar som nyckelringsobjektet bakom den, därför måste objektet finnas innan konfigurationen sätts ihop. Skapa det i samma transaktion som sparningen och du tar bort en hel klass ordningsbuggar.

Certifikatautentisering tar en annan väg: identityData plus identityDataPassword för en PKCS#12-blob. Att leverera den blobben i app-paketet är en vana ärvd från exempelkoden, inte ett utgivningsbeslut, eftersom lösenordet reser med den och varje kopia av appen bär samma identitet.

Rättighet och tillgänglighet grindar allt

Hanteraren kanske inte finns alls, och orsaken är provisionering. Din app-identifierare behöver Network Extension-förmågan tillsammans med rättigheten för personlig VPN, och profilen som signerar bygget måste bära båda.

Hoppa över det och den delade instansen returnerar nil, eller så misslyckas sparningen med ett fel som aldrig nämner rättigheten. Tillgänglighet är den andra porten. Rikta in dig på något äldre än iOS 8 och symbolen saknas vid körning, så felet är en krasch eller en nil-hanterare, inte en hanterare utan konfiguration. Kontrollera körmiljön och rättigheten innan du felsöker din objektgraf.

Läs in, ändra, spara och se sedan på ordningen vid begäran

Behandla livscykeln som inläsning, ändring och sparning, och hoppa aldrig över inläsningen. Tills loadFromPreferences är klart håller hanteraren ingenting och protokollobjektet kan inte läsas eller bytas ut.

En andra sparning ersätter konfigurationen i stället för att lägga till en annan, så en halvfärdig sparning kan skada en profil som fungerade. Regler vid begäran bildar en ordnad array, och den ordningen är policyn. Sätt en anslut-var-som-helst-regel före frånkopplingsregeln och en manuell frånkoppling följs av omedelbar återanslutning, vilket ser ut som en defekt men följer den dokumenterade utvärderingen.

Flytta frånkopplingsregeln framåt när användarens åtgärd måste vinna. Det som ligger utanför appens kontroll spelar lika stor roll. Rutter kommer från tunneln eller serverpolicyn i stället för från en inställning du anger, och en pakettunnel-leverantör rapporterar dem när den startar. Appen kan inte lista eller redigera profiler som installerats av andra appar eller konfigurationsprofiler, så lova inte en skärm som visar varje VPN på enheten.

Relaterade artiklar