Užklausa visada yra to paties sakinio variantas: palikite VPN naršymui, bet leiskite SSH ar atsarginio kopijavimo užduočiai naudoti įprastą ryšį. Šia tema sklandantis patarimas, persiųsti prievadą iptables NAT taisyklėmis, to nepadaro. NAT taisyklė perrašo adresus ir prievadus srauto viduje; ji niekada neparenka, per kurią sąsają paketas išeina. Šis sprendimas priklauso maršruto paieškai, o maršruto paieškai reikia pagalbos, kad pamatytų prievadą.

Kodėl paprastas maršrutas negali atitikti prievado

Linux parenka maršrutą ieškodamas paskirties adreso lentelėje, kai kandidatų lentelės jau išfiltruotos politikos taisyklėmis. Tos taisyklės gali atitikti ugniasienės žymę, šaltinio adresą, įeinančią sąsają arba UID. Pats maršruto įrašas neturi prievado lauko, nes maršrutas parenkamas anksčiau, nei transporto antraštė pradeda turėti reikšmės.

Dabartiniai iproute2 ir branduoliai praplečia taisyklės parinkiklį: ipproto, sport ir dport priimami, todėl ip rule add ipproto tcp dport 22 table 100 ketinimą išreiškia vienoje eilutėje. Vykdykite ip rule add help realiame hoste, kad pamatytumėte, ar jūsų kompiliacija išvardija dport. Jei taip, baigėte viena komanda; jei ne, toliau aprašytas žymės kelias yra lygiavertis.

Bet kuriuo atveju taisyklė yra tik rodyklė. 100 lentelei vis tiek reikia maršruto, ir būtent šią dalį žmonės pamiršta.

Trys dalys, arba viena

Šiuolaikinė forma yra viena taisyklė aukščiau plius maršrutas alternatyvioje lentelėje. Klasikinė forma įterpia netfilter per vidurį: pažymėkite paketą, tada sulyginkite žymę taisyklėje. Abi baigiasi ta pačia paieška; skiriasi tuo, kur skaitomas prievadas.

Žymės metodas egzistuoja todėl, kad netfilter mato transporto antraštę, o maršrutizavimo kodas istoriškai jos nematė. Tai visas mechanizmas, ir tai paaiškina, kodėl atsarginis variantas yra trys bendradarbiaujančios dalys, o ne viena gudri komanda.

Trys dalys iš eilės

Pirmiausia pažymėkite srautus, kuriuos norite nukreipti, grandinėje, kuri veikia pakankamai anksti, kad žymė atsirastų prieš maršruto sprendimą:

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

Antra, siųskite pažymėtus paketus į atskirą lentelę:

ip rule add fwmark 0x1/0x1 table 100

Trečia, suteikite tai lentelei numatytąjį maršrutą per fizinę jungtį. Adresai iliustraciniai; įstatykite savo:

ip route add default via 192.168.1.1 dev wlan0 table 100

Praleiskite trečią žingsnį ir pažymėtas paketas 100 lentelėje neras maršruto, todėl nepavyks. Simptomas atrodo taip, lyg taisyklė sugadino tinklą, nors iš tikrųjų ji pašalino vienintelį kelią, kuris paketui buvo likęs.

Kas palaiko tai veikiant po pirmo paketo

Žymės taikomos išeinantiems paketams. Atsakymas atvyksta į fizinę sąsają su adresu, kurį priskyrė ta jungtis, o pagrindinė lentelė vis dar gali teikti pirmenybę tuneliui tai paskirčiai. Du mechanizmai palaiko nuoseklų atsakymo kelią: šaltiniu pagrįsta taisyklė jungties adresui ir ryšių sekimas, kuris išsaugo sprendimą visą srauto gyvavimo laiką. Žymės išsaugojimas conntrack ir atkūrimas atsakyme yra įprastas būdas padaryti būsenos išimtį stabilią.

Atvirkštinio kelio filtravimas yra kitas tylus žudikas. Jei branduolys griežtai tikrina grįžimo kelią, o atsakymas atvyksta į sąsają, kurios pagrindinė lentelė nesirinktų, paketas numetamas be jokio pranešimo. rp_filter numatytosios reikšmės skiriasi priklausomai nuo distribucijos ir nuo to, ar sąsaja persiunčiama, todėl skaitykite efektyvią reikšmę, o ne manykite, kad ji išjungta.

Nežymėkite paties tunelio transporto. WireGuard arba UDP OpenVPN tunelis nėra TCP 22, todėl aukščiau pateiktas receptas saugus, bet išimtis, parašyta kaip viskas, išskyrus tunelio paskirtį, gali sugauti užšifruotus paketus ir sugadinti tunelį taip, kad atrodytų kaip maršrutizavimo kilpa.

Patikrinkite, o ne manykite

Paklauskite branduolio, kokį kelią jis rinktųsi, paskirčiai ir prievadui, tada paleiskite tikrą perdavimą:

ip route get 203.0.113.10
ip rule show
nft list ruleset

Jei žymė yra, bet skaitikliai niekada nejuda, taisyklė neatitinka. Skaitikliai yra skirtumas tarp konfigūracijos, kurią parašėte, ir politikos, kurią branduolys taiko.

Kada tai netinkamas įrankis

Prievadu pagrįstos išimtys iš prigimties trapios. Paslaugos keičia prievadus, HTTP/3 ateina kaip UDP 443, o viena programa gali atidaryti kelis skirtingų tipų srautus. Jei tikrasis reikalavimas yra, kad ši programa naudotų įprastą jungtį, maršrutizavimo sluoksnis yra netinkama vieta; tinklo vardų erdvė arba tarpinis serveris kiekvienai programai tinka geriau.

Jei reikalavimas yra, kad šis potinklis naudotų įprastą jungtį, visiškai praleiskite žymes ir pridėkite konkretesnį maršrutą. Tai paprasčiau, matoma vienoje lentelėje, ir kitas žmogus gali tai audituoti neskaitęs taisyklių rinkinio.

Užsirašykite, kuris iš trijų reikalavimų jums iš tikrųjų galioja, prieš liesdami ugniasienę. Aukščiau aprašytas mechanizmas yra tikslus, o netinkamame sluoksnyje pritaikytas tikslumas tebus ilgesnė pertrauka.

Susiję straipsniai