nftables cgroup apėjimui reikia ir šaltinio adreso pataisos
Pažymėjus vieną cgroup, jis siunčiamas į kitą lentelę, o socket išlaiko jau turėtą adresą. Klasifikavimas, maršrutizavimas ir vertimas – trys atskiri žingsniai.
Vienos cgroup srauto žymėjimas yra lengvoji dalis. Trys atskiri sprendimai turi sutapti, kol viena programa išeis per fizinę sąsają, o visa kita liks tunelyje: kuris socket priklauso išimčiai, kokią maršruto paiešką sukelia žymė, ir kokį šaltinio adresą paketas neša išeidamas. Dauguma nepavykusių bandymų pirmą padaro teisingai, antrą – pusiau, o į trečią net nepažiūri.
Trys sprendimai, o ne vienas
Klasifikavimas atsako, kas atleistas. Maršrutizavimas atsako, kur pažymėtas paketas eina vietoj to. Šaltinio parinkimas atsako, ką matys tolimasis galas ir kur turi grįžti atsakymas.
Šie dalykai nepavyksta nepriklausomai. Paketas gali būti klasifikuotas, peradresuotas į fizinę sąsają ir vis tiek nešti privatų adresą, kurio joks aukštesnio lygio maršrutizatorius negali grąžinti, o tai sukelia laiko limitą, atrodantį lygiai kaip ugniasienės blokavimas. Niekas klasifikavimo žingsnyje apie tai neįspėja. Niekas ir maršrutizavimo žingsnyje.
Tvarka taip pat svarbi. Klasifikavimas vyksta kuriant paketą, maršrutizavimas – po to, o vertimas – išėjimo taške.
Jei negali įvardyti, kuris iš trijų etapų sugedęs, tu ne derini, o perstatai taisykles ir tikiesi.
Suderink cgroup, kuri išliks ir rytoj
nftables gali patikrinti socket cgroup v2 priklausomybę, ir tai tikrai naudinga, nes sekama procesu, o ne paskirties vieta. Kabliukas – identifikatorius. Iš meniu paleista darbalaukio programa dažnai gyvena trumpalaikiame scope, kurio pavadinimas pasikeičia kitą kartą paleidus.
nft list ruleset
systemctl status session.slice 2>/dev/null
cat /proc/self/cgroupScope pavadinimo nusikopijavimas iš vienos sesijos ir įkodavimas sukuria taisyklę, kuri veikia šiandien ir rytoj tyliai nustoja atitikti. Vietoj to įdėk programą į sąmoningą, stabilų vykdymo kontekstą, pavyzdžiui, atskirą scope ar unit, kurį kontroliuoji, ir derink su juo. Tada taisyklė išlieka po perkrovimų ir paketų atnaujinimų. Ji taip pat tampa kažkuo, apie ką kolega gali mąstyti be tavo sesijos istorijos.
Taip pat būk tikslus, kurį mechanizmą naudoji. cgroup v1 net_cls klasifikavimas ir cgroup v2 socketų atitikimas yra skirtingi dalykai, o panašiai pavadintas laukas dokumentacijoje nepadaro jų keičiamais.
Antrą paiešką sukelia route grandinė
Vietoje generuojamam srautui grandinės tipas nusprendžia, ar kas nors įvyks po žymės nustatymo. filter tipo output grandinė gali pažymėti paketą, o branduolys ir toliau naudos jau pasirinktą maršrutą. route tipo grandinė yra mechanizmas, kuris prašo naujos paieškos.
table inet bypass {
chain mark {
type route hook output priority mangle; policy accept;
socket cgroupv2 level 2 "app.slice" meta mark set 0x1 comment "app bypass"
}
}
ip rule add fwmark 0x1 lookup 200
ip route add default via 203.0.113.1 dev wlan0 table 200Tada žymei reikia politikos taisyklės, kuri nusiųstų ją į lentelę, ir ta lentelė turi būti išsami: numatytasis maršrutas, vietiniai tikslai, kurių programai dar reikia, ir aukštesnio lygio šliuzas, kuris tikrai atsako.
Žymės reikšmę rink sąmoningai. WireGuard išoriniam transporto srautui naudoja savo fwmark, o atsitiktinai pataikius į tą patį skaičių galima sutrikdyti paties tunelio maršruto išimtį taip, kad diagnozuoti bus skausminga.
Šaltinio adresas neseka maršrutu
Socket, kuris jau pasirinko šaltinio adresą tunelio keliui, išlaiko jį ir po peradresavimo. Niekas maršruto pakeitime jo neperrašo, todėl paketas išeina per fizinę sąsają su privačiu šaltiniu, kurio aukštesnio lygio tinklas negali grąžinti.
Matomas simptomas – programa, kuri tarsi siunčia duomenis ir niekada negauna atsakymo, ir ugniasienės žurnalas, kuris nieko nerodo, nes paketas niekada negrįžo.
Siauras sprendimas – šaltinio vertimo taisyklė, apribota tos programos žyme ir tikrąja išvesties sąsaja, integruota su jau esančiu NAT, o ne jį pakeičianti:
table inet bypass {
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
meta mark 0x1 oifname "wlan0" masquerade
}
}Versk tik išimtį ir nieko daugiau. Bendra masquerade taisyklė ištaiso simptomą ir sunaikina galimybę atskirti, kuris srautas ėjo kuriuo keliu. Derink pagal žymę, tikrąją išvesties sąsają ir, jei gali, pačios programos adresą. Plačias taisykles lengva rašyti ir beveik neįmanoma vėliau audituoti.
Kas vis dar ištrūksta iš išimties
Vardų skyrimas gali ateiti iš atskiro resolver proceso kitoje cgroup, todėl naršyklės socket klasifikavimas neklasifikuoja jo paieškų. Jei resolver užklausos lieka tunelyje, o ryšys išeina už jo, split-horizon atsakymai gali neatitikti kelio. Tas neatitikimas sukelia gedimus, kurie atrodo kaip DNS klaidos, bet jomis nėra.
Vaikiniai procesai daugumoje konfigūracijų paveldi cgroup, bet pagalbininkas, kuris persikelia į savo scope, nepaveldi. Tikrink, o ne daryk prielaidų, ypač viskam, kas save paleidžia iš naujo.
Galiausiai nuspręsk, kas turi įvykti, kai tunelis neveikia. Išimtis, kuri tyliai tampa visišku apėjimu, yra kitokia saugumo pozicija nei ta, kuri užsidaro, ir tik viena jų yra tai, ką turėjai omenyje.