Obísť VPN pre jeden port vyžaduje policy routing
Pravidlo NAT prepisuje adresy, ale nevyberá odchádzajúce rozhranie. Tu je pravidlo, tabuľka a značka, ktoré skutočne držia jeden port TCP mimo tunela.
Požiadavka je vždy variantom tej istej vety: nechaj VPN na prehliadanie, ale dovoľ SSH alebo úlohe zálohovania použiť bežné pripojenie. Rada, ktorá o tom koluje, presmerovať port pravidlami NAT v iptables, to nerobí. Pravidlo NAT prepisuje adresy a porty vnútri toku; nikdy nevyberá rozhranie, ktorým paket odchádza. To rozhodnutie patrí vyhľadávaniu trasy a vyhľadávanie trasy potrebuje pomoc, aby videlo port.
Prečo bežná trasa nedokáže zodpovedať portu
Linux vyberá trasu vyhľadaním cieľovej adresy v tabuľke, po prefiltrovaní kandidátskych tabuliek pravidlami politiky. Tieto pravidlá môžu zodpovedať značke firewallu, zdrojovej adrese, prichádzajúcemu rozhraniu alebo UID. Samotná položka trasy nemá pole portu, pretože trasa sa vyberá skôr, než záleží na hlavičke transportu.
Súčasné iproute2 a jadrá rozširujú selektor pravidiel: ipproto, sport a dport sú akceptované, takže ip rule add ipproto tcp dport 22 table 100 vyjadruje zámer v jednom riadku. Spusti ip rule add help na skutočnom hoste, aby si videl, či tvoj build uvádza dport. Ak áno, máš to za jeden príkaz; ak nie, cesta cez značku nižšie je ekvivalent.
Tak či tak je pravidlo len ukazovateľ. Tabuľka 100 stále potrebuje trasu, a to je časť, na ktorú ľudia zabúdajú.
Tri časti, alebo jedna
Moderná forma je jedno pravidlo vyššie plus trasa v alternatívnej tabuľke. Klasická forma pridáva netfilter do stredu: označ paket a potom zodpovedaj značku v pravidle. Obe končia pri tom istom vyhľadaní; líšia sa v tom, kde sa port číta.
Prístup so značkou existuje preto, že netfilter vidí hlavičku transportu a kód smerovania ju historicky nevidel. To je celý mechanizmus a vysvetľuje, prečo je záložná cesta tri spolupracujúce časti namiesto jedného dôvtipného príkazu.
Tri časti v poradí
Najprv označ toky, ktoré chceš odkloniť, v reťazci, ktorý sa spúšťa dosť skoro na to, aby značka existovala pred rozhodnutím o trase:
nft add table inet vpnexempt
nft 'add chain inet vpnexempt out { type route hook output priority mangle; }'
nft add rule inet vpnexempt out tcp dport 22 meta mark set 0x1Po druhé, pošli označené pakety do samostatnej tabuľky:
ip rule add fwmark 0x1/0x1 table 100Po tretie, daj tejto tabuľke predvolenú trasu cez fyzické rozhranie. Adresy sú ilustratívne; nahraď ich svojimi:
ip route add default via 192.168.1.1 dev wlan0 table 100Vynechaj tretí krok a označený paket nenájde v tabuľke 100 žiadnu trasu, takže zlyhá. Príznak vyzerá, akoby pravidlo pokazilo sieť, hoci v skutočnosti odstránilo jedinú cestu, ktorá paketu zostala.
Čo to udržiava v chode po prvom pakete
Značky platia na odchádzajúce pakety. Odpoveď prichádza na fyzické rozhranie s adresou, ktorú rozhranie pridelilo, a hlavná tabuľka môže pre tento cieľ stále uprednostňovať tunel. Dva mechanizmy udržiavajú spätnú cestu konzistentnú: pravidlo založené na zdroji pre adresu rozhrania a connection tracking, ktorý zachováva rozhodnutie po celý čas života toku. Uloženie značky do conntracku a jej obnovenie pri odpovedi je zvyčajný spôsob, ako urobiť stavovú výnimku stabilnou.
Filtrovanie spätnej cesty je druhý tichý zabijak. Ak jadro prísne overuje spätnú cestu a odpoveď prichádza na rozhranie, ktoré by hlavná tabuľka nevybrala, paket sa zahodí bez správy. rp_filter predvolené hodnoty sa líšia podľa distribúcie a podľa toho, či sa rozhranie preposiela, takže čítaj účinnú hodnotu namiesto predpokladu, že je vypnutá.
Neoznačuj vlastný transport tunela. Tunel WireGuard alebo UDP OpenVPN nie je TCP 22, takže recept vyššie je bezpečný, ale výnimka napísaná ako všetko okrem cieľa tunela môže zachytiť šifrované pakety a pokaziť tunel spôsobom, ktorý vyzerá ako slučka smerovania.
Over to namiesto predpokladu
Opýtaj sa jadra, akou cestou by šlo, pre cieľ aj pre port, a potom spusť skutočný prenos:
ip route get 203.0.113.10
ip rule show
nft list rulesetAk značka existuje, ale počítadlá sa nikdy nehýbu, pravidlo nezodpovedá. Počítadlá sú rozdiel medzi konfiguráciou, ktorú si napísal, a politikou, ktorú jadro uplatňuje.
Kedy je to nesprávny nástroj
Výnimky založené na porte sú od prírody krehké. Služby menia porty, HTTP/3 prichádza ako UDP 443 a jedna aplikácia môže otvoriť niekoľko tokov rôznych druhov. Ak je skutočnou požiadavkou, aby tento program používal bežné rozhranie, vrstva smerovania je nesprávne miesto; sieťový menný priestor alebo proxy pre aplikáciu sa hodí lepšie.
Ak je požiadavkou, aby táto podsiet používala bežné rozhranie, vynechaj značky úplne a pridaj konkrétnejšiu trasu. Je to jednoduchšie, je to viditeľné v jednej tabuľke a ďalší človek to môže skontrolovať bez čítania sady pravidiel.
Predtým, než sa dotkneš firewallu, zapíš si, ktorú z troch požiadaviek vlastne máš. Mechanizmus vyššie je presný a presnosť aplikovaná na nesprávnu vrstvu je len dlhší výpadok.