Ako pripútať jednu aplikáciu Linux k VPN pomocou pravidiel UID
Pravidlo UID vidí len lokálne sockety a obvyklá výnimka pre loopback zabije tunel. Najprv nasmerujte účet, potom filtrujte a overte každý krok.
Pripútanie jedného programu k VPN v Linuxe je hlavne problém smerovania, a pravidlo firewallu rozhoduje len o tom, čo sa stane po výbere trasy. Ak v OUTPUT porovnáte UID programu skôr, než tunel získa predvolenú trasu, pravidlo zahodí práve ten provoz, ktorý ste chceli ochrániť. To isté pravidlo nevidí ani proces resolvera, ktorý odpovedá na DNS otázky programu. Nastavte poradie správne a jeden účet bez oprávnení sa stane spoľahlivým voličom rozdeleného tunela.
Dajte účtu trasu pred verdiktom
Zhoda vlastníka odpovedá na jednu otázku: zostavil paket lokálny socket, ktorý patrí tomuto UID? Nevyberá rozhranie a nemôže presunúť provoz, ktorý hlavná tabuľka už odosiela cez fyzický NIC. Preto pravidlo UID bez zodpovedajúcej trasy program zablokuje, namiesto toho aby ho presmerovalo.
Pošlite účet najprv cez jeho vlastnú tabuľku a potom nechajte firewall potvrdiť výsledok. Funguje to na hostiteľovi, ktorého iproute2 rozumie uidrange, čo ip rule help hlási v jednom riadku. Tabuľka 100 drží predvolenú trasu tunelom a pravidlo posiela do tejto tabuľky len UID 1000. Všetko ostatné zostáva v hlavnej tabuľke a naďalej používa fyzické rozhranie.
ip rule add uidrange 1000-1000 table 100 ip route add default dev tun0 table 100
Druhý účet, ktorý potrebuje iný tunel, dostane tabuľku 101 a vlastné pravidlo, pretože dva profily nemôžu oba vlastniť predvolenú trasu v tej istej tabuľke. Profily NetworkManager sú systémové, takže táto časť zostáva ručná a pravidlá zmiznú pri reštarte, ak ich niečo neobnoví. Napíšte tabuľky do spúšťacieho skriptu vedľa definície tunela, aby opätovné pripojenie nemohlo nechať jeden účet na nesprávnej ceste.
Prečo výnimka pre loopback zabije tunel
Väčšina skopírovaných verzií pravidla zahodí každý paket, ktorý nevyjde cez loopback. Tunel nie je loopback, takže táto podoba zahodí aj provoz tunela, a výsledok vyzerá ako mŕtvy VPN, nie ako chyba firewallu.
Keď OUTPUT beží, jadro už vybralo výstupné rozhranie, takže -o sa porovnáva s odpoveďou trasy a nie so záhlavím paketu. Zhoda vlastníka sa konzultuje len v OUTPUT a POSTROUTING a presmerované pakety nenesú žiadny socket, ktorý by si prečítalo. Táto kombinácia znamená, že výnimka musí pomenovať rozhranie tunela a túto zhodu negovať, namiesto negovania loopbacku.
Loopback si stále zaslúži vlastný ACCEPT nad DROP, pretože prvý DNS paket z programu ide na lokálny stub cez lo. Dajte obe pravidlá do tohto poradia a účet sa dostane k stubu, potom k tunelu, a nikam inam.
iptables -I OUTPUT 1 -o lo -m owner --uid-owner vpnapp -j ACCEPT iptables -A OUTPUT -m owner --uid-owner vpnapp ! -o tun0 -j DROP
IPv6 je samostatná sada pravidiel a dvojica len pre v4 necháva ip6tables nedotknuté. Program, ktorý uprednostňuje záznamy AAAA, by potom vyšiel cez fyzické rozhranie bez toho, aby sa kedy dostal k DROP. Zrkadlite obe pravidlá v ip6tables, alebo na hostiteľovi vypnite IPv6, keď tunel nenesie žiadnu v6 adresu. Ručne pridané pravidlá tiež zmiznú pri reštarte, takže ich uložte pomocou netfilter-persistent save alebo tú istú logiku znovu postavte ako tabuľku nftables, ktorú načíta spúšťacia jednotka.
DNS odpovede prichádzajú z iného procesu
Otázka programu na 127.0.0.53 prejde cez ACCEPT pre loopback a práve tam sa zhoda UID zastaví. Stub resolver posiela otázku nahor zo svojho servisného účtu, takže pravidlo naviazané na vpnapp nikdy nevidí druhú otázku. Ak resolver pre spojenie vyberie LAN server, odpovede sa vrátia cez fyzický NIC, zatiaľ čo vlastné pakety programu zostanú v tuneli. Viditeľný výsledok je funkčný tunel s pokazenými menami, alebo mená, na ktoré odpovedá server, ktorý ste nevybrali.
Opravte preklad mien na spojení tunela, nie v aplikácii. Dajte profilu tunela DNS server a smerovaciu doménu a potom potvrďte pomocou resolvectl query a resolvectl status tun0 že resolver ho používa pre mená, na ktorých záleží. Vo vnútri sieťového menného priestoru problém zmizne, pretože resolver priestoru pozná len tunel.
Overte pravidlo zo samotného účtu
Opýtajte sa jadra, akú trasu UID dostane, potom odošlite požiadavku ako tento účet a porovnajte výstupnú adresu s adresou svojho účtu. Ak obe hlásia rovnakú adresu, pravidlo zhoduje niečo iné ako provoz, ktorý ste testovali. Prvý príkaz nižšie ukazuje hľadanie trasy bez odoslania paketu, čo oddeľuje chybu smerovania od chyby firewallu.
ip route get 1.1.1.1 uid 1000 sudo -u vpnapp curl -s https://ifconfig.co
Počítadlá ukazujú, či pravidlo niekedy vystrelilo. Spustite iptables -vnL OUTPUT, prečítajte počet paketov vedľa každého pravidla a nulu vedľa DROP po skutočnom provoze berte ako chybu zhody.
Presmerovaný provoz stojí mimo tohto návrhu. Kontajner alebo VM za mostom nemá lokálny socket, ktorý by vlastnil vpnapp, takže zhoda vlastníka nikdy nevystrelí a tieto pakety namiesto toho idú podľa politiky FORWARD. Ak je potrebné taký provoz pokryť, otestujte ho zvlášť a napíšte politiku naviazanú na most alebo adresu kontajnera. Návrh drží, keď tabuľka, výnimka rozhrania, resolver a pravidlá v6 ukazujú všetky rovnakým smerom; vynechajte ktorúkoľvek z nich a účet buď presakuje, alebo stratí pripojenie.