Per què la teva aplicació VPN per a iOS mostra desconnectat si el túnel està actiu
La teva aplicació per a iOS controla el túnel però no en és propietària, i l’estat del gestor està a la memòria cau. Carrega primer les preferències i després llegeix l’estat i els comptadors de la interfície.
La teva aplicació diu desconnectat, la barra de menús diu connectat i el trànsit clarament flueix. Aquest desfasament no és una condició de cursa que puguis arreglar amb un reintent: l’aplicació i el túnel són processos separats, i l’objecte que llegeix el teu codi és una vista emmagatzemada en memòria cau d’una configuració que guarda el sistema. La superfície Personal VPN d’Apple és una API de control, no un camí de dades, i la major part del seu comportament estrany es deriva d’aquest sol fet. Aquí tens què passa realment a cada crida.
L’objecte gestor és una vista en memòria cau, no el túnel
NETunnelProviderManager es omple des d’un magatzem de preferències que posseeix el sistema, així que les seves propietats no signifiquen res fins que loadFromPreferences no acaba. Llegeix connection.status abans d’això i obtindràs un valor per defecte, i per això la primera actualització d’estat després de tornar a engegar informa desconnectat mentre el túnel està actiu. Carrega primer i després llegeix l’estat i la configuració del protocol des del mateix gestor de compleció. Observa els canvis posteriors mitjançant NEVPNStatusDidChange en lloc de fer sondejos periòdics, i tingues en compte que la notificació també s’activa per a connexions iniciades per On Demand, on no hi ha cap crida de l’aplicació que pugui retornar res. El mateix val per a la configuració del protocol: es llegeix de la configuració carregada, no del que l’aplicació hi va passar.
El túnel mateix viu en un procés proveïdor de Network Extension, així que l’aplicació pot perdre el seu propi estat sense perdre la connexió. Tot el que mostra la interfície s’ha de reconstruir a partir del gestor, no recordar de la sessió anterior.
Ordre d’inici: desa, carrega i després inicia
Una connexió basada en proveïdor necessita tres passos en ordre. Escriu la configuració del proveïdor i crida saveToPreferences, carrega el gestor perquè la configuració desada sigui la que tens a les mans i després inicia mitjançant NETunnelProviderSession.startVPNTunnel(). Si t’estalvies el desament, l’inici no té res a engegar; si carregues abans de desar, el gestor encara reflecteix la configuració antiga.
El booleà que retorna startVPNTunnel només diu que la sol·licitud ha estat acceptada. Les fallades a nivell de proveïdor arriben més tard com un canvi d’estat a desconnectat, que observes mitjançant la notificació NEVPNStatusDidChange, i el gestor de notificacions ha de tornar a llegir connection.status després de loadFromPreferences perquè el valor en memòria cau pot ser encara l’antic. Les fallades a nivell de sol·licitud tornen immediatament de la forma que llança excepcions de la crida, o pel paràmetre de sortida d’error de startVPNTunnelAndReturnError:. El codi que tracta el valor de retorn com a resultat informa d’una connexió que mai no es va establir. L’altra fallada silenciosa és un identificador de paquet del proveïdor que no coincideix amb l’extensió instal·lada: la sol·licitud es rebutja i res del missatge apunta a l’identificador. Si l’identificador és incorrecte, la sol·licitud normalment falla de seguida, abans que aparegui cap línia de registre del proveïdor.
Recarregar les preferències després d’un inici és el que fa correctes les pantalles d’estat. El gestor no t’envia una configuració nova quan el sistema la canvia.
El material de confiança arriba pel perfil, mai des del codi de l’aplicació
Una aplicació no té cap manera suportada d’afegir un certificat arrel al magatzem de confiança d’iOS, així que una configuració de Personal VPN només pot referenciar material en què el dispositiu ja confia: una cadena establerta per un perfil instal·lat, per la gestió del dispositiu o per una CA en què el sistema confia per altres motius. Una aplicació que crea la seva pròpia CA al primer engegament i espera que el sistema l’honori fallarà la validació dins del proveïdor, on la interfície de l’aplicació no pot veure el motiu.
Tracta aquesta frontera com la restricció de disseny que és i lliura l’àncora de confiança amb el perfil d’inscripció. Mantén l’autenticació VPN separada de la decisió de confiança, perquè fallen en llocs diferents i les depuren persones diferents.
Els comptadors venen de la interfície, no de l’API de VPN
El gestor exposa estat i configuració, i res que compti bytes per túnel. Si necessites xifres d’ús, crida getifaddrs() i llegeix if_data de la interfície corresponent: en0 per al Wi-Fi, les interfícies pdp_ip per al mòbil i un dispositiu utun per al túnel mateix. Els comptadors de utun descriuen el trànsit interior i inclouen la sobrecàrrega del protocol.
Aquestes xifres són estimacions, no comptabilitat per aplicació, i es reinicien quan es recrea la interfície. Etiqueta-les així a la interfície, o algú les farà servir per facturar un client. Si necessites xifres per aplicació, necessites un mecanisme completament diferent, no una lectura millor d’aquests camps.
La neteja pertany a stopVPNTunnel, no a la terminació
applicationWillTerminate et dona uns quants segons abans que el sistema pugui matar el procés, cosa que no és un lloc fiable per desmuntar una connexió. Envia l’aturada a stopVPNTunnel() o gestiona-la al callback d’aturada del proveïdor, i conserva l’identificador del gestor o de la configuració amb què vas iniciar perquè l’aturada apunti a aquella connexió i no a totes les configuracions del dispositiu.
Desa aquest identificador al costat del perfil al qual pertany, ja que un objecte gestor no registra quina configuració ha seleccionat l’usuari. I recorda que una connexió aixecada per On Demand no té cap crida d’aplicació al darrere, així que una pantalla d’estat encara ha de carregar les preferències abans de dibuixar res.