API:er för VPN i iOS: NEVPNManager, tunnelleverantör eller profil?
Välj API efter transporten du måste tala med, bevisa sedan att tunneln bär trafik: ordningen save-load-start, provider-entitlements och on-demand-regler.
Tre olika produkter svarar på namnet iOS VPN och de delar inte ett API. Personal VPN använder systemets inbyggda IPsec- och IKEv2-transporter. Custom tunnel kör din egen protokoll inne i en network extension. Configuration profile konfigurerar endera och kan lägga till on-demand-beteende. Att välja efter transporten du måste tala med är snabbare än att välja efter vilken handledning som kompilerades först.
Kör kontrollerna nedan i ordning, eftersom varje steg förutsätter att det föregående gav en giltig konfiguration.
Steg 1: välj efter transport
Om servern är IKEv2 eller IPsec i Cisco-stil räcker NEVPNManager och systemets transporter ingår gratis. Om servern talar OpenVPN, WireGuard eller något annat kan NEVPNManager inte hjälpa: den har ingen krok för ett protokoll från tredje part. Det fallet kräver NETunnelProviderManager med en packet tunnel provider som implementerar protokollet. En profil distribuerar bara konfiguration och kan inte lägga till en transport som operativsystemet saknar.
PPTP är inte ett mål på nuvarande system. IPsec med delad hemlighet förväntar sig fortfarande gruppnamnet i remoteIdentifier, ett keychain-objekt som håller hemligheten och utökad autentisering när servern frågar efter ett användarnamn. Varje saknad del dyker upp som samma generiska konfigurationsfel, så lägg till alla innan du felsöker något annat.
Steg 2: respektera ordningen spara, ladda, starta
NEVPNManager skriver till preferences, läser tillbaka dem och startar först då. Fyll i protokoll- och manager-objekten, anropa saveToPreferences, anropa loadFromPreferences och anropa startVPNTunnel från load completion handler. Att starta innan laddningen återvänder ger ett configuration-invalid-fel, NEVPNErrorDomain code 1, på en konfiguration som annars är korrekt.
Formen är kort nog att hålla på ett ställe:
manager.protocolConfiguration = proto
manager.isEnabled = true
manager.saveToPreferences { }
manager.loadFromPreferences { manager.connection.startVPNTunnel() }startVPNTunnel återvänder när begäran accepteras, inte när tunneln är uppe. Observera NEVPNStatusDidChange och läs connection.status för det verkliga läget. En app som antar framgång vid anropet rapporterar en ansluten VPN medan extensionen fortfarande förhandlar. Statusen connecting är normal ett ögonblick; en status som aldrig lämnar den är felet som är värt att logga.
Steg 3: ge provider-processen vad den behöver
Custom transport körs i en separat process med egen bundle identifier och egen entitlement. Både container-appen och providern behöver network-extension-entitlementen vid signering, och en Developer ID-build utanför App Store måste fortfarande bära den i provisioning profile. En saknad entitlement ser ut som en protokollbugg eftersom extensionen helt enkelt inte startar.
Det finns ingen offentlig socket descriptor att låna. NEPacketTunnelProvider ger dig NEPacketTunnelFlow med read, write och cancel, och kod som sträcker sig efter privata nyckelsökvägar går sönder mellan utgåvor. Providern fortsätter att köra medan appen är i bakgrunden, så container-appen behöver inget bakgrundsläge för det.
Steg 4: on-demand är en regeluppsättning, inte en strömbrytare
isOnDemandEnabled beväpnar bara reglerna; NEOnDemandRuleConnect och dess syskon avgör när tunneln kommer upp. En evaluate-connection-regel med en probe-URL är bara så bra som den URL:en. Om probe svarar utan tunneln drar regeln slutsatsen att det privata nätet redan är nåbart och ansluter aldrig, så rikta den mot något som bara svarar inifrån.
Always-on är ett separat löfte. Det kräver en övervakad enhet och en hanterad profil, och en icke övervakad användare kan ta bort en profil när som helst. Leverera inte en design som beror på always-on om inte flottan är övervakad.
Steg 5: bevisa vägen, inte etiketten
Att skanna efter tun-, tap-, ppp- eller ipsec-gränssnitt bevisar att en VPN är konfigurerad, inte att din begäran använde den. NWPathMonitor med usesInterfaceType(.other) säger att ett virtuellt gränssnitt är tillgängligt, och en viability handler kan testa en värd. Ingen av dem bevisar utvägen, så kombinera dem med en begäran till en resurs som bara tunneln når. Gränssnittsnamn är en diagnostisk hjälp, aldrig en port som applikationslogik bör förgrena sig på.
För en fältkontroll, jämför den offentliga adressen med och utan tunneln och hämta en endast-intern sida. Ett statusanrop kan rapportera ansluten medan providern förhandlar, så låt resultatet från resursen avgöra och behandla statusen som stödjande bevis.