A kérés mindig ugyanannak a mondatnak a változata: tartsd meg a VPN-t böngészéshez, de az SSH vagy egy biztonsági mentési feladat a normál kapcsolatot használja. A tanács, ami erről kering, vagyis a port továbbítása iptables NAT-szabályokkal, ezt nem teszi meg. A NAT-szabály a folyamon belüli címeket és portokat írja át; soha nem választja ki, melyik interfészen hagyja el a csomag a gépet. Az a döntés az útvonal-keresésé, és az útvonal-keresésnek segítség kell, hogy lásson egy portot.

Miért nem tud egy egyszerű útvonal portra illeszkedni

A Linux úgy választ útvonalat, hogy a célcímet egy táblában keresi, miután a jelölttáblákat házirend-szabályokkal megszűrte. Ezek a szabályok illeszkedhetnek tűzfal-jelölésre, forrás címre, bejövő interfészre vagy UID-ra. Magának az útvonal-bejegyzésnek nincs port mezője, mert az útvonal kiválasztása előbb történik, mint hogy a szállítási fejléc számítana.

A mai iproute2 és a kernelek kiszélesítik a szabály választóját: ipproto, sport és dport elfogadott, tehát ip rule add ipproto tcp dport 22 table 100 egy sorban kifejezi a szándékot. Futtassa a ip rule add help parancsot a valódi gazdagépen, hogy lássa, a buildje listázza-e a dport mezőt. Ha igen, egy parancssal kész; ha nem, az alábbi jelöléses útvonal az egyenértékű.

Akárhogy is, a szabály csak mutató. A 100-as táblának még mindig kell útvonal, és pont ezt a részt felejtik el az emberek.

Három darab, vagy egy

A modern forma a fenti egyetlen szabály plusz egy útvonal a másik táblában. A klasszikus forma netfiltert tesz középre: jelöld meg a csomagot, majd illeszkedj a jelölésre egy szabályban. Mindkettő ugyanabban a keresésben végződik; abban különböznek, hol olvassák a portot.

A jelöléses megközelítés azért létezik, mert a netfilter látja a szállítási fejlécet, az útválasztó kód történelmileg nem látta. Ez az egész mechanizmus, és ez magyarázza, miért három együttműködő darab a tartalék, és nem egy okos parancs.

A három darab sorrendben

Először jelöld meg azokat a folyamokat, amelyeket el akarsz terelni, olyan láncban, amely elég korán fut ahhoz, hogy a jelölés létezzen az útvonal-döntés előtt:

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 0x1

Másodszor küldd a megjelölt csomagokat külön táblába:

ip rule add fwmark 0x1/0x1 table 100

Harmadszor adj a táblának alapértelmezett útvonalat a fizikai linken keresztül. A címek szemléltetők; írd be a sajátjaidat:

ip route add default via 192.168.1.1 dev wlan0 table 100

Hagyd ki a harmadik lépést, és a megjelölt csomag nem talál útvonalat a 100-as táblában, ezért elbukik. A tünet olyan, mintha a szabály elrontotta volna a hálózatot, pedig valójában eltávolította az egyetlen utat, ami a csomagnak maradt.

Mi tartja működésben az első csomag után

A jelölések a kimenő csomagokra érvényesek. A válasz a fizikai interfészen érkezik azzal a címmel, amit az a link kapott, és a fő tábla még mindig az alagutat részesítheti előnyben ahhoz a célhoz. Két mechanizmus tartja konzisztensen a válasz útvonalát: a linkcímre vonatkozó forrásalapú szabály, és a kapcsolatkövetés, amely a folyam teljes élettartamára megőrzi a döntést. A jelölés conntrackbe mentése és a válasznál való visszaállítása a szokásos módja annak, hogy egy állapottal bíró kivétel stabil legyen.

A fordított útvonal szűrése a másik csendes gyilkos. Ha a kernel szigorúan ellenőrzi a visszautat, és a válasz olyan interfészen érkezik, amelyet a fő tábla nem választana, a csomag üzenet nélkül eldobódik. rp_filter alapértékei disztribúcióként és aszerint változnak, hogy az interfész továbbítva van-e, ezért olvasd ki a tényleges értéket, ahelyett hogy feltételeznéd, hogy ki van kapcsolva.

Ne jelöld meg az alagút saját szállítását. Egy WireGuard- vagy UDP OpenVPN-alagút nem TCP 22, ezért a fenti recept biztonságos, de a minden, kivéve az alagút célja formában írt kivétel elkaphatja a titkosított csomagokat, és úgy törheti el az alagutat, ami útvonalhuroknak látszik.

Ellenőrizd a feltételezés helyett

Kérdezd meg a kerneltől, melyik útvonalat választaná, a célhoz és a porthoz, majd futtasd a valódi átvitelt:

ip route get 203.0.113.10
ip rule show
nft list ruleset

Ha a jelölés létezik, de a számlálók soha nem mozdulnak, a szabály nem illeszkedik. A számlálók jelentik a különbséget az általad írt konfiguráció és a kernel által alkalmazott házirend között.

Mikor rossz eszköz ez

A portalapú kivételek természetüknél fogva törékenyek. A szolgáltatások portot váltanak, a HTTP/3 UDP 443-ként érkezik, és egy alkalmazás többféle folyamot is nyithat. Ha a valódi követelmény az, hogy ez a program a normál linket használja, az útválasztási réteg rossz hely; egy hálózati névtér vagy alkalmazásonkénti proxy jobban illik.

Ha a követelmény az, hogy ez az alhálózat a normál linket használja, hagyd ki teljesen a jelöléseket, és adj hozzá egy konkrétabb útvonalat. Egyszerűbb, egy táblában látható, és a következő ember szabálykészlet olvasása nélkül ellenőrizheti.

Írd le, melyik a három követelmény közül van valóban nálad, mielőtt a tűzfalhoz nyúlsz. A fenti mechanizmus pontos, és a rossz rétegre alkalmazott pontosság csak egy hosszabb kiesés.

Kapcsolódó cikkek