Il root non è ciò che permette a un'app VPN Android di trasportare traffico, bloccare fughe o sopravvivere a un riavvio. Le persone riassumono tutto questo come «l'app ha il permesso VPN», il che nasconde tre meccanismi distinti: un consenso concesso dall'utente, un'interfaccia di pacchetti stabilita dal sistema e una politica di blocco della piattaforma che non spetta all'app definire. Esaminare un progetto VPN Android significa chiedere su quale dei tre si basi davvero un'affermazione, perché ognuno ha un proprietario e una modalità di guasto diversi.

Il consenso arriva tramite un'attività di sistema

VpnService.prepare() non concede nulla. Restituisce un intent all'attività di consenso del sistema quando manca il consenso, e l'app avvia quel dialogo affinché l'utente approvi il servizio. Avviare il processo dell'app stessa, aggiungere un permesso al manifest o mostrare una schermata personalizzata «attiva VPN» non crea l'autorizzazione.

L'autorizzazione è anche circoscritta. Appartiene a un pacchetto in un profilo utente, quindi la copia personale e la copia di lavoro sono decisioni separate, e il proprietario di un dispositivo può preparare un profilo gestito in modo diverso da uno personale. Se il dialogo non compare mai e prepare() restituisce null, il consenso esiste già per quel pacchetto in quel profilo; non è prova che l'app sia affidabile, solo che l'autorizzazione c'è.

L'interfaccia è una richiesta che il sistema soddisfa

Dopo il consenso, l'app descrive ciò che vuole con VpnService.Builder: indirizzi, rotte, server DNS, MTU e, dove supportato, le applicazioni da includere o escludere. establish() chiede al sistema di creare l'interfaccia del tunnel e di instradarvi il traffico corrispondente. Il sistema possiede la decisione di instradamento; l'app riceve il descrittore di file e poi deve fare qualcosa di utile con i pacchetti.

What you observeWho actually owns it
VPN consent dialogThe system, triggered by prepare()
Routes, DNS and app listsThe app requests them; the system applies them
One active VPN per profileThe platform; a new service replaces the old one
Always-on and block-without-VPNDevice policy enforced by the platform

Quella tabella è l'architettura in un solo posto. L'app partecipa alla gestione dei pacchetti; non possiede l'interfaccia, la tabella di instradamento o il numero di servizi che possono essere eseguiti.

Il socket del tunnel deve sfuggire al proprio tunnel

La connessione che trasporta il traffico cifrato è essa stessa un socket. Se viene instradata di nuovo nell'interfaccia appena creata dall'app, il tunnel dipende dal tunnel e si blocca. VpnService.protect() lega quel socket alla rete sottostante perché aggiri la cattura, ed è per questo che un client corretto protegge il proprio socket esterno prima del primo handshake.

adb shell dumpsys connectivity | grep -i -A5 vpn
adb shell settings get global always_on_vpn_app
adb shell settings get global always_on_vpn_lockdown

Questi comandi mostrano la rete VPN installata, il pacchetto di attivazione permanente e se il blocco è impostato. Sono osservazioni di sola lettura: se i valori non corrispondono a ciò che il progetto afferma, l'affermazione riguarda l'interfaccia dell'app e non lo stato del sistema.

Il blocco può appartenere alla piattaforma

Android documenta una politica che blocca le connessioni che non usano la VPN. Quell'applicazione è un contratto della piattaforma, non un'app che ritenta le connessioni in un ciclo. L'interruttore si trova nelle impostazioni VPN del dispositivo come Blocca connessioni senza VPN, e su un dispositivo gestito il proprietario può attivarlo per l'intero profilo. La distinzione conta quando valuti un'affermazione di marketing: un client può mostrare un'icona a lucchetto e riconnettersi in modo aggressivo mentre il traffico diretto resta possibile, oppure le app coperte possono restare offline perché il sistema applica il blocco.

L'icona a lucchetto è disegnata dall'app, quindi dimostra solo che l'app crede di essere connessa. Se un'altra app perde l'accesso alla rete lo decide la piattaforma, quindi il controllo utile è vedere quell'app fallire mentre il tunnel è attivo.

Nemmeno l'etichetta «sempre attivo» di un app store sostituisce quel contratto. L'attivazione permanente e il blocco sono impostazioni del dispositivo, spesso applicate dal proprietario, e il loro comportamento per le app escluse è definito dalla piattaforma. Leggi l'impostazione, non il badge.

Quattro domande per una revisione del progetto

Primo, chi ha acconsentito: quale pacchetto, quale profilo, e se è stato l'utente o una politica di dispositivo gestito. Secondo, che cosa ha richiesto l'app: quali rotte, quali famiglie di indirizzi, quali app incluse o escluse. Terzo, che cosa succede quando il tunnel non è disponibile: il sistema blocca o il traffico ricade sulla rete sottostante? Quarto, che cosa fa l'app con i pacchetti che riceve.

La quarta domanda è quella a cui il modello dei permessi non può rispondere. Il consenso e un'interfaccia TUN dimostrano che l'app può ricevere traffico, non che lo cifri, autentichi un pari o si riprenda in modo pulito. Sono proprietà dell'implementazione, ed è lì che una revisione onesta passa il suo tempo.

Una richiesta di root superflua non diventa legittima perché si chiama il risultato interruttore di sicurezza, e un dialogo di consenso non è un audit di sicurezza. Tieni separate le tre autorizzazioni e ogni affermazione diventa verificabile.

Articoli correlati