Geen schakelaar om deze app uit te sluiten: geef het proces zijn eigen bron
Routering vergelijkt adressen, niet procesnamen. Geef het uitgesloten programma zijn eigen bron en tabel, of verplaats de beslissing naar de router, waar dat eerlijk is.
Eén programma zou de gewone verbinding moeten gebruiken terwijl al het andere op de tunnel blijft, en de client heeft daar geen schakelaar voor. Er is ook geen verborgen menu te vinden. Een route wordt gekozen uit velden in het pakket, en het pakket draagt adressen en poorten in plaats van de identiteit van het proces dat het heeft gemaakt, dus een uitsluiting moet in een van die velden worden uitgedrukt. Volg een pakket één keer en de beschikbare opties zijn niet langer mysterieus.
Waarom de client het niet kan bieden
Bestemmingsroutering vergelijkt het bestemmingsadres met prefixen en houdt de langste overeenkomst. Op dat moment ziet elk pakket er hetzelfde uit, wat het ook heeft gemaakt. Bronbeleidsroutering verbreedt de vergelijking naar het bronadres, en dat is de haak die elke praktische oplossing gebruikt: verander de bron en een andere tabel komt in aanmerking.
Poorten helpen niet. Een uitsluiting op poort zou vóór de bestemmingsopzoeking moeten worden beoordeeld, en de poort speelt geen rol in die beslissing. Alles wat als poortgebaseerde uitsluiting wordt aangeprezen, sluit in werkelijkheid op een ander veld uit en beschrijft dat losjes.
Echte routering per toepassing bestaat waar het platform daar machinerie voor heeft toegevoegd, zoals filteroproepen op Windows of de VPN-dienstbinding op Android. Een desktopinstantie van OpenVPN levert daar niets van, en geen configuratievlag verzint het.
Linux: markeer het proces en routeer dan de markering
De schoonste aanpak koppelt de beslissing aan het proces dat de socket bezit. De owner-overeenkomst werkt voor lokaal gegenereerd verkeer in de OUTPUT-keten, dus een daar toegepaste markering kan een aparte tabel kiezen:
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
Pakketten van gebruiker 1001 raadplegen dan tabel 200 en verlaten het systeem via de gewone gateway, terwijl de hoofdtabel al het andere nog steeds de tunnel in stuurt. De owner-overeenkomst geldt alleen voor lokaal gegenereerde pakketten, wat precies het verkeer is dat hier telt, en ze kan pakketten die voor een andere host worden doorgestuurd niet classificeren. Controleer met de hulpmiddelen in plaats van met de bedoeling: ss -tnp toont het lokale adres en het bezittende proces van bestaande verbindingen, en ip route get 1.1.1.1 mark 0x1 toont welke tabel de markering kiest.
Een netwerk-naamruimte is het steviger antwoord voor een zelfstandig programma, omdat elke socket die erin wordt gemaakt er per constructie aan gebonden is, dus hulpprocessen en kindverbindingen erven het gedrag zonder überhaupt geclassificeerd te worden. De prijs is loodgieterswerk: een veth-paar, een adres aan elk uiteinde en een standaardroute in de naamruimte die terug naar de host wijst.
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: de bestemming beslist nog steeds
Windows kiest de uitgaande interface op basis van de bestemming, dus een programma dat een ander pad wil, moet iets veranderen dat de stack vóór die keuze raadpleegt. ForceBindIP dekt de eerste helft: het start een programma met zijn sockets al gebonden aan een lokaal adres dat je noemt. Dat alleen verandert niet via welke interface het pakket vertrekt, omdat de bestemming nog steeds de route kiest. Bind een bron op een laptop waarvan de standaardroute de tunnel in wijst, en het pakket gaat alsnog de tunnel in.
Het symptoom heeft een leesbare vorm zodra je het kent. Het geldt voor een LAN-adres dat de gekozen interface rechtstreeks bereikt en faalt voor alles op het internet waarvan de route naar de tunnel wijst. Het lijkt ook te werken totdat het programma werk aan een helper geeft, omdat een helper die zijn eigen socket opent nooit iets over de binding is verteld.
Verplaats de beslissing wanneer één proces de verkeerde eenheid is
Als de echte eis een apparaat is en niet een programma, zet het dan op zijn eigen SSID of VLAN en laat de router beslissen: die bron neemt het normale pad terwijl andere bronnen de tunnel gebruiken. Een toegewijde gateway-machine is het andere eerlijke ontwerp: zij houdt de VPN vast en ontvangt alleen de bestemmingen die de router haar stuurt. Op een VLAN dekt het beleid elke stroom die het apparaat opent, inclusief de hulpprocessen die de Windows-aanpak braken. De ruil is omvang: twee programma's op dat apparaat kunnen niet langer verschillend worden behandeld.
Beide zijn bron- of bestemmingsbeleid met een omvang die je in één zin kunt zeggen. Geen van beide is per toepassing, en een ontwerp dat zich als per toepassing verkoopt, faalt de eerste keer dat het programma zijn werk aan een tweede proces delegeert.