Aucun interrupteur « exclure cette application » : donnez au processus sa propre source
Le routage compare des adresses, pas des noms de processus. Donnez au programme exclu sa propre source et sa propre table, ou déplacez la décision vers le routeur, là où c’est honnête.
Un programme devrait utiliser la connexion ordinaire pendant que tout le reste reste dans le tunnel, et le client n’a aucun interrupteur pour cela. Il n’y a pas non plus de menu caché à trouver. Une route se choisit à partir de champs à l’intérieur du paquet, et le paquet transporte des adresses et des ports plutôt que l’identité du processus qui l’a créé, donc une exclusion doit s’exprimer dans l’un de ces champs. Suivez un paquet une fois et les options disponibles cessent d’être mystérieuses.
Pourquoi le client ne peut pas le proposer
Le routage par destination compare l’adresse de destination aux préfixes et garde la correspondance la plus longue. À cet instant, chaque paquet se ressemble, quel que soit ce qui l’a produit. Le routage par politique de source élargit la comparaison à l’adresse source, et c’est le crochet qu’utilise toute solution pratique : changez la source et une autre table devient éligible.
Les ports n’aident pas. Une exclusion par port devrait être évaluée avant la recherche de destination, et le port ne joue aucun rôle dans cette décision. Tout ce qui est annoncé comme exclusion par port exclut en réalité par un autre champ et le décrit avec laxisme.
Le vrai routage par application existe là où la plateforme a ajouté la machinerie nécessaire, comme les rappels de filtre sous Windows ou la liaison du service VPN sous Android. Une instance de bureau d’OpenVPN n’en embarque rien, et aucun indicateur de configuration ne l’invente.
Linux : marquez le processus, puis routez la marque
L’approche la plus propre lie la décision au processus qui possède la socket. La correspondance owner fonctionne pour le trafic généré localement dans la chaîne OUTPUT, donc une marque appliquée là peut sélectionner une table distincte :
iptables -t mangle -A OUTPUT -m owner --uid-owner 1001 -j MARK --set-mark 0x1
ip rule add fwmark 0x1 table 200
ip route add 192.168.1.0/24 dev eth0 src 192.168.1.0 table 200
ip route add default via 192.168.1.1 dev eth0 table 200
Les paquets de l’utilisateur 1001 consultent alors la table 200 et sortent par la passerelle ordinaire, tandis que la table principale continue d’envoyer tout le reste dans le tunnel. La correspondance owner ne s’applique qu’aux paquets générés localement, ce qui est exactement le trafic qui vous intéresse ici, et elle ne peut pas classer les paquets transmis pour un autre hôte. Vérifiez avec les outils plutôt qu’avec l’intention : ss -tnp montre l’adresse locale et le processus propriétaire des connexions établies, et ip route get 1.1.1.1 mark 0x1 montre quelle table la marque sélectionne.
Un espace de noms réseau est la réponse la plus solide pour un programme autonome, car chaque socket créé à l’intérieur y est lié par construction, donc les processus auxiliaires et les connexions enfants héritent du comportement sans être classés du tout. Le coût est de la plomberie : une paire veth, une adresse à chaque extrémité et une route par défaut dans l’espace de noms qui pointe vers l’hôte.
ip netns add novpn
ip link add veth-host type veth peer name veth-ns
ip link set veth-ns netns novpn
ip addr add 10.200.0.1/24 dev veth-host
ip netns exec novpn ip addr add 10.200.0.2/24 dev veth-ns
ip netns exec novpn ip route add default via 10.200.0.1
Windows : la destination décide encore
Windows choisit l’interface de sortie d’après la destination, donc un programme qui veut un autre chemin doit changer quelque chose que la pile consulte avant ce choix. ForceBindIP couvre la première moitié : il lance un programme avec ses sockets déjà liées à une adresse locale que vous nommez. Cela seul ne change pas l’interface par laquelle le paquet sort, car la destination sélectionne toujours la route. Liez une source sur un portable dont la route par défaut pointe dans le tunnel et le paquet y entre quand même.
Le symptôme a une forme lisible une fois qu’on le connaît. Il vaut pour une adresse LAN que l’interface choisie atteint directement et échoue pour tout ce qui, sur internet, a une route pointant vers le tunnel. Il semble aussi fonctionner jusqu’à ce que le programme confie du travail à un auxiliaire, car un auxiliaire qui ouvre sa propre socket n’a jamais été informé de la liaison.
Déplacez la décision quand un seul processus est la mauvaise unité
Si l’exigence réelle est un appareil et non un programme, mettez-le sur son propre SSID ou VLAN et laissez le routeur décider : cette source prend le chemin normal tandis que les autres utilisent le tunnel. Une machine passerelle dédiée est l’autre conception honnête : elle garde le VPN et ne reçoit que les destinations que le routeur lui envoie. Sur un VLAN, la politique couvre chaque flux que l’appareil ouvre, y compris les processus auxiliaires qui ont cassé l’approche Windows. L’échange porte sur la portée : deux programmes sur cet appareil ne peuvent plus être traités différemment.
Les deux sont des politiques de source ou de destination dont la portée tient en une phrase. Aucune n’est par application, et une conception qui se vend comme telle échoue la première fois que le programme délègue son travail à un second processus.