Une application Linux ordinaire utilise le VPN sans toucher à TUN
Le démon possède le périphérique TUN et le tunnel ; les applications ne font qu'ouvrir des sockets. Gardez le privilège de configuration et l'accès réseau comme deux frontières distinctes.
Un navigateur qui utilise un VPN Linux déjà établi n'ouvre pas /dev/net/tun. Il ouvre une socket, et le noyau décide par quelle interface sortent les paquets de cette socket. Le processus qui a créé le tunnel fait un autre travail que le processus dont il transporte le trafic. Garder ces deux rôles séparés répond à la plupart des questions de permission avant qu'elles ne soient posées.
Suivez un paquet de la socket au tunnel
Une application ordinaire appelle connect ou send, et le noyau cherche une route pour la destination. Si la route choisie pointe vers l'interface du tunnel, le paquet est mis en file sur le périphérique que le démon VPN lit. Le démon le chiffre et l'envoie par l'interface physique. Chaque flèche de cette description est un endroit où une question de permission peut recevoir une réponse.
Rien dans ce chemin n'exige que l'application connaisse le périphérique. Le démon détient le descripteur de fichier et effectue les opérations d'interface, tandis que l'application ne voit qu'une API réseau normale.
Dessinez les deux moitiés une fois, et les questions de permission deviennent plus faciles à placer. La moitié supérieure est le monde des applications, et la moitié inférieure appartient au démon.
Décidez qui a besoin du périphérique et qui n'en a pas besoin
Créer ou se rattacher à une interface TUN exige l'accès au périphérique et en plus la capacité de la configurer, c'est pourquoi un service VPN pris en charge commence avec l'autorité d'administration réseau ou utilise un assistant privilégié. Cette exigence appartient au démon. Elle ne dit rien du navigateur, du client de base de données ou de l'outil de transfert de fichiers. Un service qui a besoin de la capacité en a besoin pour sa propre étape de configuration, pas pour ses clients.
Une fois la route et la politique en place, un processus ordinaire utilise le chemin résultant via ses appels de socket habituels. Il n'a pas besoin du nœud de périphérique et n'a pas besoin de root.
Changer les permissions du périphérique n'est pas un moyen d'accorder à une application l'accès à la destination. Cela ne fait que déplacer la frontière du périphérique ailleurs.
Vérifiez l'espace de noms dans lequel l'application s'exécute réellement
Un conteneur, ou un second espace de noms réseau, donne à ses processus un ensemble d'interfaces et une table de routage distincts. Un tunnel sur l'hôte n'y apparaît pas automatiquement, et aucun changement de permission du périphérique n'y change quoi que ce soit. L'application se contentera de router via ce que cet espace de noms fournit. C'est pourquoi une image de conteneur ne peut pas hériter d'un tunnel de l'hôte par accident.
Vérifiez avec ip netns list et ip -n NAME route, ou en inspectant le lien de l'espace de noms du processus. La réponse est généralement visible en une seule commande.
Deux utilisateurs du même hôte peuvent aussi recevoir des chemins différents par politique. C'est une décision de réseau plutôt qu'une preuve de propriété du périphérique.
Séparez les capacités de la politique réseau
Certains outils ont besoin de plus qu'une socket. Capturer des paquets nécessite une socket brute, et modifier les routes nécessite l'autorité d'administration. Ce sont des opérations distinctes avec des autorisations distinctes, et en accorder une ne doit pas être lu comme une exigence générale pour utiliser le VPN.
Un programme qui implémente son propre tunnel est un troisième cas. Il ouvre réellement TUN parce qu'il assume le rôle du démon, c'est pourquoi il a besoin des privilèges du démon.
Nommez l'opération avant de nommer le privilège. Les deux sont généralement plus faciles à séparer qu'ils n'en ont l'air.
Vérifiez la séparation avec deux comptes
Connectez le tunnel en tant que service, puis exécutez l'application en tant qu'utilisateur ordinaire et confirmez qu'elle atteint la ressource privée. Vérifiez ip route get pour la destination depuis le shell de cet utilisateur afin de voir quelle interface a été sélectionnée. Si la route est correcte et que la connexion échoue encore, le problème est la politique plutôt que le privilège.
La conception qui en résulte est le moindre privilège avec une frontière explicite : un composant possède la configuration et les ressources du tunnel, les charges de travail conservent leurs comptes normaux, et la politique réseau décide de ce qui peut passer. Tout exécuter en root effondre ces rôles sans rien expliquer.