Chiedete a un'app iOS se il telefono è su una VPN e la risposta onesta è che non può saperlo nel senso che intendete. L'SDK non espone alcun flag per «il dispositivo è in un tunnel», e le interfacce private che potrebbero avvicinarsi sono chiuse alle app pubblicate. Potete osservare la configurazione della vostra app, lo stato a essa collegato e uno o due indizi indiretti dalla pila di rete. Ciascuno risponde a una domanda diversa, e la maggior parte dei controlli rotti nasce dal prendere uno di essi come risposta completa.

Il mito del flag VPN unico

La convinzione è che da qualche parte nell'SDK ci sia una proprietà che riporta se il dispositivo è in un tunnel, come un flag di raggiungibilità riporta se un host risponde. Una tale proprietà pubblica non esiste. E anche se esistesse, «esiste un tunnel» e «il mio traffico lo usa» sono affermazioni diverse, e solo la seconda conta per la maggior parte delle app.

Proprio questo divario è il motivo per cui le librerie che pubblicizzano un rilevatore di VPN in una riga tendono a leggere qualcosa di fragile, come un nome di interfaccia o una chiave proxy, e a presentarlo come verdetto.

Caricate le preferenze prima di fidarvi di un nil

L'istanza condivisa del gestore esiste appena la richiedete, ma la sua proprietà di protocollo resta nil finché non termina il callback di caricamento. Quindi un protocollo nil significa «non ancora caricato» almeno tanto spesso quanto «non installato». Fate la lettura dentro il blocco di completamento, e solo allora decidete: un oggetto di protocollo che esiste, con il flag di abilitazione attivo, è l'aspetto di «installato».

Un secondo segnale sta sull'oggetto di connessione: lo stato non valido, che il sistema segnala quando questa app non ha alcuna configurazione installata. Uno stato non valido insieme a un protocollo nil dopo un caricamento completato è un'assenza reale, non una corsa di tempi.

I cambi di connessione arrivano come notifiche

I gestori passati a load e save riportano cosa è successo alla configurazione, non cosa sta facendo il tunnel. Aspettare che uno di essi scatti al momento della connessione è una corsa che non si risolve mai. Osservate invece la notifica di cambio di stato e leggete il valore corrente dell'oggetto di connessione quando arriva.

Una volta installata una configurazione, lo stato di connessione percorre una breve sequenza: disconnesso, in connessione, connesso, riaffermazione, disconnessione. «Connesso» descrive il tunnel e non il server dietro di esso, quindi non è prova che il traffico scorra. On-demand può anche alzare un tunnel mentre l'app è sospesa, e allora la notifica arriva prima che abbiate qualcosa da aggiornare.

L'istantanea proxy limitata è un indizio, non un verdetto

CFNetwork può fornire all'app le impostazioni proxy correnti del sistema, e dentro quel risultato c'è un dizionario limitato con chiave per nome di interfaccia. Vedere un nome che inizia con tun, utun, ppp, ipsec o tap è un indizio che un tunnel è presente. Resta un'istantanea di ciò che questa app può vedere, non un'affermazione su dove viaggiano i pacchetti.

I fornitori non concordano sui nomi, quindi un prefisso assente non dimostra nulla, e un'interfaccia presente può esistere senza portare traffico. La raggiungibilità è ancora più debole: una richiesta riuscita verso un indirizzo privato mostra che il percorso ha funzionato per quella richiesta in quel momento, non che una VPN sia installata.

Il simulatore prende in prestito il Mac, e le altre app restano invisibili

Il simulatore non ha una pila di rete propria; ogni connessione che fa è quella del Mac. Una VPN in esecuzione sul Mac host è quindi già in vigore per l'app simulata, e le impostazioni del simulatore stesso non mostrano nulla. Se il tunnel è salito dopo l'avvio del simulatore, riavviarlo è di solito più rapido che fare debug dell'app. Un host su una porta non standard ha bisogno di quella porta nell'URL, o di un inoltro locale come socat TCP-LISTEN:12345,fork TCP:host:12345.

Le API pubbliche non elencheranno profili VPN che appartengono ad altre app o a profili di configurazione. Per un'app nota, la sonda di schema URL tramite canOpenURL è il trucco portabile, e da iOS 9 lo schema interrogato deve essere dichiarato nel vostro Info.plist; se lo omettete, la chiamata restituisce false. OpenVPN Connect risponde su openvpn://, il che lo rende un buon esempio e un cattivo rilevatore generale.

Combinate tre osservazioni e dite cosa significano

Nella pratica impilate tre risultati: una configurazione caricata e abilitata, uno stato di connessione che non è non valido, e una richiesta verso un indirizzo raggiungibile solo dal tunnel. Ciascuno inganna da solo; insieme dicono ciò che l'app può sapere invece di ciò che l'utente presume.

Scrivete il risultato come tre righe nella diagnostica, non come un solo booleano. Quando un utente dice che la VPN è spenta mentre la vostra app non è d'accordo, le tre righe mostrano quale osservazione ha divergito, e questa è la differenza tra un ticket di supporto su cui potete agire e uno che finisce con «a me funziona».

Articoli correlati