Jou app sê ontkoppel, die kieslysbalk sê gekoppel, en verkeer vloei duidelik. Daardie gaping is nie 'n wedlooptoestand wat jy met 'n herprobeer kan regmaak nie: die app en die tonnel is aparte prosesse, en die objek wat jou kode lees is 'n gekasde weergawe van 'n konfigurasie wat die stelsel stoor. Apple se Personal VPN-oppervlak is 'n beheer-API, nie 'n datapad nie, en die meeste van sy vreemde gedrag volg uit daardie een feit. Hier is wat werklik onder elke oproep gebeur.

Die bestuurder-object is 'n gekasde weergawe, nie die tonnel nie

NETunnelProviderManager word gevul uit 'n voorkeure-stoor wat die stelsel besit, so sy eienskappe beteken niks totdat loadFromPreferences voltooi. Lees connection.status voor dit en jy kry 'n verstekwaarde; daarom rapporteer die eerste statusverfrissing na 'n herbegin ontkoppel terwyl die tonnel werk. Laai eers, lees dan die status en die protokol-konfigurasie uit dieselfde voltooiingshandler. Let later op veranderinge deur NEVPNStatusDidChange eerder as om te pols, en let op dat die kennisgewing ook vuur vir verbindings wat deur On Demand begin is, waar geen app-oproep bestaan om enigiets terug te gee nie. Dieselfde geld vir protokol-instellings: hulle word uit die gelaaide konfigurasie gelees, nie uit wat die app ingegee het nie.

Die tonnel self leef in 'n Network Extension-verskafferproses, so die app kan sy eie toestand verloor sonder om die verbinding te verloor. Enigiets wat die koppelvlak wys, moet uit die bestuurder herbou word, nie uit die vorige sessie onthou nie.

Beginvolgorde: stoor, laai, begin dan

'n Verskaffer-gebaseerde verbinding het drie stappe in volgorde nodig. Skryf die verskaffer-konfigurasie en roep saveToPreferences, laai die bestuurder sodat die gestoorde konfigurasie die een is wat jy vashou, en begin dan deur NETunnelProviderSession.startVPNTunnel(). Slaan die stoor oor en die begin het niks om te lanseer nie; laai voor die stoor en die bestuurder weerspieël steeds die ou konfigurasie.

startVPNTunnel gee 'n Boole-waarde terug wat net sê dat die versoek aanvaar is. Verskaffer-vlak foute kom later as 'n statusverandering na ontkoppel, wat jy deur die NEVPNStatusDidChange-kennisgewing sien, en die kennisgewing-hanterder moet connection.status herlees ná loadFromPreferences, want die gekasde waarde is dalk nog die ou een. Versoek-vlak foute kom dadelik terug uit die gooi-vorm van die oproep, of deur die fout-uit-parameter van startVPNTunnelAndReturnError:. Kode wat die terugkeerwaarde as die uitkoms beskou, rapporteer 'n verbinding wat nooit tot stand gekom het nie. Die ander stille fout is 'n verskaffer-bundelidentifiseerder wat nie by die geïnstalleerde uitbreiding pas nie: die versoek word verwerp, en niks in die boodskap wys na die identifiseerder nie. As die identifiseerder verkeerd is, misluk die versoek gewoonlik dadelik, voordat enige verskaffer-loglyn verskyn.

Om voorkeure na 'n begin te herlaai, is wat statusskerms korrek maak. Die bestuurder stoot nie vir jou 'n nuwe konfigurasie wanneer die stelsel dit verander nie.

Vertrouensmateriaal kom per profiel, nooit uit app-kode nie

'n App het geen ondersteunde manier om 'n wortelsertifikaat by die iOS-vertrouensstoor te voeg nie, so 'n Personal VPN-konfigurasie kan slegs verwys na materieel wat die toestel reeds vertrou: 'n ketting wat deur 'n geïnstalleerde profiel, deur toestelbestuur, of deur 'n CA wat die stelsel om ander redes vertrou, gevestig is. 'n App wat by die eerste bekendstelling sy eie CA munt en verwag dat die stelsel dit eerbiedig, sal binne die verskaffer misluk met validering, waar die app se koppelvlak nie die rede kan sien nie.

Behandel daardie grens as die ontwerpbeperking wat dit is en lewer die vertrouensanker saam met die inskrywingsprofiel. Hou VPN-verifikasie apart van die vertrouensbesluit, want hulle misluk op verskillende plekke en word deur verskillende mense ontfout.

Tellers kom uit die koppelvlak, nie uit die VPN-API nie

Die bestuurder bied status en konfigurasie, en niks wat grepe per tonnel tel nie. As jy gebruiksyfers nodig het, roep getifaddrs() en lees if_data vir die betrokke koppelvlak: en0 vir Wi-Fi, die pdp_ip-koppelvlakke vir sellulêr, en 'n utun-toestel vir die tonnel self. Die utun-tellers beskryf binneste verkeer en sluit protokol-oorhoof in.

Daardie syfers is skattings, nie per-app-boekhouding nie, en hulle stel terug wanneer die koppelvlak herskep word. Noem hulle so in die koppelvlak, anders sal iemand hulle gebruik om 'n kliënt te faktureer. As jy per-app-syfers nodig het, het jy 'n heeltemal ander meganisme nodig, nie 'n beter lesing van hierdie velde nie.

Opruiming hoort in stopVPNTunnel, nie in beëindiging nie

applicationWillTerminate gee jou 'n handvol sekondes voordat die stelsel die proses moontlik doodmaak, wat nie 'n betroubare plek is om 'n verbinding af te breek nie. Stuur die stop na stopVPNTunnel() of hanteer dit in die verskaffer se stop-terugroep, en hou die bestuurder of konfigurasie-identifiseerder wat jy begin het, sodat die stop daardie verbinding teiken eerder as elke konfigurasie op die toestel.

Stoor daardie identifiseerder saam met die profiel waaraan dit behoort, want 'n bestuurder-object teken nie aan watter konfigurasie die gebruiker gekies het nie. En onthou dat 'n verbinding wat deur On Demand opgebring is, glad geen app-oproep agter hom het nie, so 'n statusskerm moet steeds voorkeure laai voordat dit enigiets teken.

Verwante artikels