Няма превключвател „изключи това приложение“: дайте на процеса собствен източник
Маршрутизацията сравнява адреси, а не имена на процеси. Дайте на изключената програма собствен източник и таблица или преместете решението на рутера, където това е честно.
Една програма трябва да използва обичайната връзка, докато всичко останало остава в тунела, а клиентът няма превключвател за това. Няма и скрито меню, което да се намери. Маршрутът се избира от полета в самия пакет, а пакетът носи адреси и портове, а не самоличността на процеса, който го е създал, затова изключването трябва да бъде изразено в едно от тези полета. Проследете пакет веднъж и наличните опции спират да бъдат загадъчни.
Защо клиентът не може да го предложи
Маршрутизацията по дестинация сравнява адреса на дестинацията с префикси и запазва най-дългото съвпадение. В този момент всеки пакет изглежда еднакво, каквото и да го е създало. Маршрутизацията по политика на източника разширява сравнението до адреса на източника и това е куката, която използва всяко практично решение: сменете източника и друга таблица става допустима.
Портовете не помагат. Изключване по порт трябва да се оценява преди търсенето на дестинацията, а портът не участва в това решение. Всичко, рекламирано като изключване по порт, всъщност изключва по някое друго поле и го описва небрежно.
Истинска маршрутизация по приложения съществува там, където платформата е добавила механизми за нея, например филтриращи извиквания в Windows или обвързване на VPN услугата в Android. Настолната инсталация на OpenVPN не носи нищо от това и никой конфигурационен флаг не го измисля.
Linux: маркирайте процеса, после маршрутизирайте маркировката
Най-чистият подход обвързва решението с процеса, който притежава сокета. Съвпадението owner работи за локално генериран трафик във веригата OUTPUT, така че маркировка, приложена там, може да избере отделна таблица:
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
Пакетите от потребител 1001 след това се обръщат към таблица 200 и излизат през обичайния шлюз, докато главната таблица все още изпраща всичко останало в тунела. Съвпадението owner важи само за локално генерирани пакети, което е точно трафикът, който ви интересува тук, и не може да класифицира пакети, препратени за друг хост. Проверявайте с инструментите, а не с намерението: ss -tnp показва локалния адрес и притежаващия процес на установените връзки, а ip route get 1.1.1.1 mark 0x1 показва коя таблица избира маркировката.
Мрежово пространство от имена е по-здравият отговор за самостоятелна програма, защото всеки сокет, създаден вътре в него, е обвързан с него по конструкция, така че помощните процеси и дъщерните връзки наследяват поведението, без изобщо да бъдат класифицирани. Цената е водопровод: двойка veth, адрес на всеки край и маршрут по подразбиране вътре в пространството от имена, който сочи обратно към хоста.
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: дестинацията все още решава
Windows избира изходящия интерфейс от дестинацията, затова програма, която иска различен път, трябва да промени нещо, което стекът проверява преди този избор. ForceBindIP покрива първата половина: стартира програма със сокети, вече обвързани с локален адрес, който посочите. Само това не променя интерфейса, през който пакетът излиза, защото дестинацията все още избира маршрута. Обвържете източник на лаптоп, чийто маршрут по подразбиране сочи в тунела, и пакетът все пак влиза в тунела.
Симптомът има четима форма, след като го познавате. Той важи за LAN адрес, до който избраният интерфейс стига директно, и се проваля за всичко в интернет, чийто маршрут сочи към тунела. Също изглежда, че работи, докато програмата не предаде работа на помощен процес, защото на помощен процес, който отваря собствен сокет, никога не са казали за обвързването.
Преместете решението, когато един процес е грешната единица
Ако истинското изискване е устройство, а не програма, сложете го на собствен SSID или VLAN и оставете рутера да реши: този източник поема нормалния път, докато другите източници използват тунела. Отделена машина за шлюз е другият честен дизайн: тя държи VPN и получава само дестинациите, които рутерът ѝ изпраща. На VLAN политиката покрива всеки поток, който устройството отваря, включително помощните процеси, които счупиха подхода за Windows. Разменната цена е обхват: две програми на това устройство вече не могат да се третират различно.
И двете са политики на източник или дестинация с обхват, който можете да изразите в едно изречение. Нито една не е по приложения и дизайн, който се представя за такъв, се проваля първия път, когато програмата делегира работата си на втори процес.