Označevanje prometa iz ene cgroup je lažji del. Tri ločene odločitve se morajo uskladiti, preden ena aplikacija pride ven skozi fizični vmesnik, medtem ko vse ostalo ostane v tunelu: katera vtičnica spada k izjemi, katero iskanje poti sproži oznaka in kateri izvorni naslov nosi paket, ko odide. Večina neuspešnih poskusov prvo naredi prav, drugo na pol, tretje pa nikoli ne pogleda.

Tri odločitve, ne ena

Klasifikacija odgovarja, kdo je izvzet. Usmerjanje odgovarja, kam gre označeni paket namesto tega. Izbira vira odgovarja, kaj bo videla oddaljena stran in kam se mora odgovor vrniti.

Te stvari odpovedo neodvisno. Paket je lahko klasificiran, preusmerjen na fizični vmesnik in še vedno nosi zasebni naslov, ki ga noben nadrejeni usmerjevalnik ne more vrniti, kar povzroči časovno prekoračitev, ki je videti natanko kot blokada požarnega zidu. Nič v koraku klasifikacije te na to ne opozori. Nič v koraku usmerjanja tudi ne.

Tudi vrstni red je pomemben. Klasifikacija se zgodi, ko je paket ustvarjen, usmerjanje za tem, prevajanje pa na izhodni točki.

Če ne moreš poimenovati, katera od treh stopenj je pokvarjena, ne razhroščuješ, ampak preurejaš pravila in upaš.

Ujemi cgroup, ki bo obstajala tudi jutri

nftables lahko preveri pripadnost vtičnice cgroup v2, kar je res koristno, ker sledi procesu in ne cilju. Past je identifikator. Namizna aplikacija, zagnana iz menija, pogosto živi v prehodnem scope, katerega ime se ob naslednjem zagonu spremeni.

nft list ruleset
systemctl status session.slice 2>/dev/null
cat /proc/self/cgroup

Kopiranje imena scope iz ene seje in trdo zapisovanje ustvari pravilo, ki danes deluje in jutri tiho preneha ustrezati. Namesto tega postavi aplikacijo v namerno, stabilno okolje izvajanja, na primer v namenski scope ali unit, ki ga nadzoruješ, in ujemi tistega. Pravilo nato preživi ponovne zagone in posodobitve paketov. Postane tudi nekaj, o čemer lahko sodelavec razmišlja brez tvoje zgodovine sej.

Bodi tudi natančen glede mehanizma, ki ga uporabljaš. Klasifikacija net_cls v cgroup v1 in ujemanje vtičnic v cgroup v2 sta različni stvari in podobno poimenovano polje v dokumentaciji ju ne naredi zamenljivih.

Drugo iskanje sproži veriga route

Za lokalno ustvarjen promet vrsta verige odloča, ali se po nastavitvi oznake kaj zgodi. Veriga output vrste filter lahko označi paket in jedro bo še naprej uporabljalo pot, ki jo je že izbralo. Veriga vrste route je mehanizem, ki zahteva novo iskanje.

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 200

Oznaka nato potrebuje pravilo politike, ki jo pošlje v tabelo, in ta tabela mora biti popolna: privzeta pot, lokalni cilji, ki jih aplikacija še potrebuje, in nadrejeni prehod, ki v resnici odgovarja.

Vrednost oznake izberi namerno. WireGuard uporablja svoj fwmark za zunanji transportni promet, in naključni pristanek na isti številki lahko moti izjemo usmerjanja samega tunela na načine, ki jih je boleče diagnosticirati.

Izvorni naslov ne sledi poti

Vtičnica, ki je že izbrala izvorni naslov za pot tunela, ga obdrži tudi po preusmeritvi. Nič v spremembi poti ga ne prepiše, zato paket odide skozi fizični vmesnik z zasebnim virom, ki ga nadrejeno omrežje ne more vrniti.

Viden simptom je aplikacija, ki se zdi, da pošilja podatke, in nikoli ne prejme odgovora, ter dnevnik požarnega zidu, ki ne pokaže ničesar, ker paket ni nikoli prišel nazaj.

Ozka rešitev je pravilo prevajanja vira, omejeno na oznako te aplikacije in njen dejanski izhodni vmesnik, vključeno v obstoječi NAT, namesto da bi ga nadomestilo:

table inet bypass {
  chain postrouting {
    type nat hook postrouting priority srcnat; policy accept;
    meta mark 0x1 oifname "wlan0" masquerade
  }
}

Prevedi izjemo in nič drugega. Splošno pravilo masquerade odpravi simptom in uniči tvojo zmožnost povedati, kateri promet je šel po kateri poti. Ujemi oznako, dejanski izhodni vmesnik in, če lahko, naslov same aplikacije. Široka pravila je lahko napisati in skoraj nemogoče pozneje revidirati.

Kaj še vedno uide izjemi

Razreševanje imen lahko prihaja iz ločenega procesa resolverja v drugi cgroup, zato klasifikacija vtičnice brskalnika ne klasificira njenih iskanj. Če poizvedbe resolverja ostanejo v tunelu, medtem ko povezava gre zunaj njega, se odgovori split-horizon morda ne ujemajo s potjo. To neskladje povzroči okvare, ki so videti kot napake DNS in niso.

Podrejeni procesi podedujejo cgroup v večini nastavitev, a pomočnik, ki se premakne v svoj scope, je ne. Preveri, namesto da predpostavljaš, zlasti pri vsem, kar se znova zažene.

Na koncu se odloči, kaj naj se zgodi, ko je tunel dol. Izjema, ki tiho postane popoln obhod, je druga varnostna drža kot tista, ki se ob napaki zapre, in le ena od njiju je tisto, kar si mislil.

Sorodni članki