Trzy różne produkty odpowiadają na nazwę iOS VPN i nie dzielą jednego API. Personal VPN korzysta z wbudowanych w system transportów IPsec i IKEv2. Custom tunnel uruchamia własny protokół wewnątrz network extension. Configuration profile konfiguruje jeden z nich i może dodać zachowanie on-demand. Wybór według transportu, z którym trzeba rozmawiać, jest szybszy niż wybór według tego samouczka, który skompilował się pierwszy.

Wykonaj poniższe kontrole po kolei, ponieważ każdy krok zakłada, że poprzedni dał poprawną konfigurację.

Krok 1: wybierz według transportu

Jeśli serwer to IKEv2 lub IPsec w stylu Cisco, NEVPNManager wystarcza, a transporty systemowe dostajesz za darmo. Jeśli serwer mówi OpenVPN, WireGuard albo czymkolwiek innym, NEVPNManager nie pomoże: nie ma haka dla protokołu strony trzeciej. Ten przypadek wymaga NETunnelProviderManager z packet tunnel provider, który implementuje protokół. Profil tylko rozprowadza konfigurację i nie może dodać transportu, którego nie ma system operacyjny.

PPTP nie jest celem w obecnych systemach. IPsec ze wspólnym sekretem nadal oczekuje nazwy grupy w remoteIdentifier, elementu keychain przechowującego sekret i uwierzytelniania rozszerzonego, gdy serwer prosi o nazwę użytkownika. Każdy brakujący element objawia się tym samym ogólnym błędem konfiguracji, więc dodaj je wszystkie, zanim zaczniesz debugować cokolwiek innego.

Krok 2: uszanuj kolejność zapisu, wczytania i uruchomienia

NEVPNManager zapisuje do preferences, odczytuje je z powrotem i dopiero wtedy startuje. Wypełnij obiekty protokołu i menedżera, wywołaj saveToPreferences, wywołaj loadFromPreferences i wywołaj startVPNTunnel z load completion handler. Uruchomienie przed powrotem wczytywania daje błąd configuration-invalid, NEVPNErrorDomain code 1, na konfiguracji, która poza tym jest poprawna.

Kształt jest dość krótki, by trzymać go w jednym miejscu:

manager.protocolConfiguration = proto
manager.isEnabled = true
manager.saveToPreferences { }
manager.loadFromPreferences { manager.connection.startVPNTunnel() }

startVPNTunnel wraca, gdy żądanie zostanie przyjęte, a nie gdy tunel jest podniesiony. Obserwuj NEVPNStatusDidChange i czytaj connection.status, by poznać rzeczywisty stan. Aplikacja, która zakłada sukces w miejscu wywołania, zgłasza podłączony VPN, podczas gdy extension wciąż negocjuje. Stan connecting jest przez chwilę normalny; stan, z którego nigdy nie wychodzi, to awaria warta zalogowania.

Krok 3: daj procesowi provider to, czego potrzebuje

Custom transport działa w osobnym procesie z własnym bundle identifier i własnym entitlement. Zarówno aplikacja container, jak i provider potrzebują w czasie podpisywania entitlement network-extension, a build Developer ID poza App Store nadal musi go nosić w provisioning profile. Brakujący entitlement wygląda jak błąd protokołu, bo extension po prostu nie startuje.

Nie ma publicznego socket descriptora do pożyczenia. NEPacketTunnelProvider daje ci NEPacketTunnelFlow z read, write i cancel, a kod sięgający po prywatne ścieżki kluczy psuje się między wydaniami. Provider działa dalej, gdy aplikacja jest w tle, więc aplikacja container nie potrzebuje do tego trybu tła.

Krok 4: on-demand to zbiór reguł, nie przełącznik

isOnDemandEnabled tylko uzbraja reguły; NEOnDemandRuleConnect i jego rodzeństwo decydują, kiedy tunel się podnosi. Reguła evaluate-connection z probe URL jest tyle warta, ile ten URL. Jeśli probe odpowiada bez tunelu, reguła uznaje, że sieć prywatna jest już osiągalna, i nigdy się nie łączy, więc skieruj ją na coś, co odpowiada tylko od środka.

Always-on to osobna obietnica. Wymaga nadzorowanego urządzenia i zarządzanego profilu, a użytkownik bez nadzoru może usunąć profil, kiedy chce. Nie wysyłaj projektu, który zależy od always-on, chyba że flota jest nadzorowana.

Krok 5: udowodnij ścieżkę, nie etykietę

Skanowanie interfejsów tun, tap, ppp lub ipsec dowodzi, że VPN jest skonfigurowany, a nie że twoje żądanie go użyło. NWPathMonitor z usesInterfaceType(.other) mówi, że interfejs wirtualny jest dostępny, a viability handler może przetestować jeden host. Żadne z nich nie dowodzi ścieżki wyjścia, więc połącz je z żądaniem do zasobu, do którego dotrze tylko tunel. Nazwy interfejsów są pomocą diagnostyczną, nigdy bramą, na której logika aplikacji miałaby się rozgałęziać.

Do kontroli w terenie porównaj adres publiczny z tunelem i bez niego oraz pobierz stronę tylko wewnętrzną. Wywołanie statusu może zgłosić połączenie, podczas gdy provider negocjuje, więc pozwól zadecydować wynikowi zasobu, a status traktuj jako dowód pomocniczy.

Powiązane artykuły