VPN par application sous Android : exclure une application ne la bloque pas
La liste par application affichée appartient à un seul propriétaire de tunnel, et exclure une application la détourne autour de ce tunnel plutôt que de la sortir du réseau. Commencez par là.
Deux personnes posent la même question et obtiennent des réponses incompatibles, parce qu’elles se tiennent à des endroits différents. L’une a l’écran des réglages VPN du système ouvert et modifie une liste d’applications. L’autre écrit VpnService.Builder.addDisallowedApplication() dans un éditeur. Toutes deux appellent cela un filtre VPN par application. Une seule possède le contrôle qu’elle décrit, et aucune des deux ne bloque quoi que ce soit.
Commencez par l’écran que voit l’utilisateur
Ouvrez les Réglages, trouvez l’entrée VPN et regardez la connexion réellement active. Si le client propose une liste par application, cette liste appartient au tunnel du client lui-même. La plateforme ne publie pas d’API générale permettant à une application tierce de lire ou de modifier la sélection d’applications d’un autre VPN ; une seconde application ne peut donc pas réparer cette liste à la place de l’utilisateur.
C’est la première bifurcation du parcours. Si le VPN installé n’a pas ce réglage, il n’y a rien à contourner par du code : la fonction est absente du produit qui possède le tunnel. S’il l’a, la bonne correction se fait dans cet écran, par la personne capable de l’ouvrir.
Suivez le paquet dans un tunnel
Quand votre propre application construit un tunnel, elle crée une interface TUN et déclare quelles applications voient leur trafic y entrer. Les appels d’adhésion ont lieu avant l’établissement de l’interface, et ensuite le jeu de règles est figé pour cette session :
val builder = VpnService.Builder()
builder.addAddress("10.8.0.2", 32)
builder.addRoute("0.0.0.0", 0)
builder.addDisallowedApplication("com.example.bypass")
val tun = builder.establish() // membership decided hereCes appels s’appliquent au tunnel que votre application vient de créer et à rien d’autre. Ce n’est pas une politique à l’échelle de l’appareil, ils ne persistent pas pour d’autres clients et ils ne peuvent pas atteindre le VPN de quelqu’un d’autre. Quand un appel du constructeur échoue parce que le paquet ne peut pas être résolu, l’interface n’est jamais établie, ce qui est un échec propre plutôt que silencieux.
Pourquoi l’exclusion ressemblait à un blocage
Une application exclue est routée autour de votre tunnel vers le réseau sous-jacent. C’est l’inverse d’un blocage : le trafic quitte toujours l’appareil, simplement en dehors de l’interface que vous contrôlez. Une application de type pare-feu fait l’inverse. Elle admet le trafic de l’application dans son tunnel puis jette les paquets, ou refuse de les transmettre, si bien que l’interface est la même et le sens de la politique inversé.
Le travail derrière cette inversion n’est pas un drapeau de configuration. Vous lisez des paquets IP depuis le descripteur du tunnel, décidez par flux, puis les transmettez via une socket protégée ou les abandonnez. Tout ce que vous ne traitez pas s’arrête simplement, et c’est pourquoi un tunnel à moitié terminé ressemble à un réseau cassé plutôt qu’à un filtre qui fonctionne. Si votre objectif est un blocage, prévoyez le traitement des paquets, un service de premier plan et une politique écrite pour le trafic que vous ne savez pas classer.
Ce qui casse quand vous le construisez vous-même
Android n’autorise en général qu’un seul VPN actif à la fois, donc votre tunnel de filtrage et un tunnel de confidentialité se disputent la même place, sauf si les produits prennent en charge le chaînage. Le VPN toujours actif avec blocage des connexions change le mode d’échec d’une manière qui compte ici : le trafic qui ne peut pas entrer dans le tunnel est abandonné au lieu d’être envoyé directement, ce que veut une conception anti-fuite et ce qu’une session de débogage attend rarement.
La visibilité des paquets est le second piège. Résoudre le nom de paquet d’une application peut échouer avec NameNotFoundException, et sur les versions récentes d’Android l’ensemble des paquets visibles dépend des requêtes que vous avez déclarées. Gérez l’exception au lieu de supposer que chaque nom se résout, et relisez la liste quand des applications sont installées ou supprimées plutôt que de la mettre en cache pour toujours.
Les appareils gérés ajoutent un troisième propriétaire. Une politique de mobilité d’entreprise peut définir un VPN par application ou un profil toujours actif, et une application ordinaire ne peut pas la contourner. Vérifiez si l’appareil est géré avant de déboguer votre propre code, car dans ce cas la liste que vous essayez de changer n’est peut-être modifiable par personne tenant le téléphone.
Testez avec une application que vous contrôlez
Ne testez pas avec l’application que vous cherchez à filtrer. Utilisez une seconde application dont vous pouvez observer le comportement réseau, et vérifiez si son trafic sort par votre tunnel alors que celui de la cible ne le fait pas. Si les deux restent à l’intérieur, la politique fonctionne et la cible est exclue ; si aucune ne sort, le tunnel lui-même est faux et la liste d’applications n’est pas le problème.
Décidez ensuite laquelle de trois choses vous construisez réellement. Un tunnel par application, c’est l’API du constructeur, avec la liste dans votre profil. Un pare-feu d’appareil, c’est du traitement de paquets plus un cycle de vie défendable. Modifier le VPN de quelqu’un d’autre n’est pas un chemin pris en charge du tout, et la réponse honnête y est que le réglage appartient à ce produit.