Hlavní navigace

nftables: struktury pro zvýšení výkonu firewallu

 Autor: Depositphotos
Linuxový firewall iptables je tu s námi téměř dvacet let, ale je postupně nahrazován novým moderním řešením zvaným nftables. Dnes se podíváme na to, jak si ulehčit práci a zefektivnit činnost firewallu.
Petr Krčmář 4. 6. 2020
Doba čtení: 4 minuty

Sdílet

minulém článku našeho seriálu o nftables jsme si řekli, jaké akce je možné provádět a co všechno můžeme udělat s paketem. Dnes se zaměříme na struktury, které umožňují zvýšit efektivitu celého firewallu.

Možná znáte ipset, o kterém byla na Rootu řeč před šesti lety. Jde o modul do iptables, který umožňuje v paměti udržovat malé efektivní databáze různých typů informací: od IP adresu přes porty až po různé kombinace těchto dat. Sety pak umožňují rychlé vyhledávání a dotazování, čímž roste přehlednost a efektivita. Výhodou nftables je, že mají podobné vlastnosti takříkajíc od narození.

Set anonymní či pojmenovaný

Základním prvkem v této oblasti jsou sety, které se na první pohled podobají těm z ipset. Můžeme si tak dle potřeby sestavovat širokou škálu různých setů, které jsou vnitřně reprezentovány jako hašovací tabulky či červeno-černé stromy.

Sety se dělí na anonymní a pojmenované. Ty první jsou napevno součástí některého z pravidel, nejsou identifikovány názvem a nemohou být znovu použity v jiném pravidle či jednoduše aktualizovány. Jednoduše je zapíšeme přímo do pravidla do složených závorek, kde tak nahradíme jednu položku celou jejich sadou. Výhodou je snadný a přehledný zápis.

# nft add rule inet filter input tcp dport {ssh, http, https} accept

Pojmenované sety proti tomu existují jako samostatné objekty, které je možné využívat na více místech a dodatečně je kdykoliv upravovat. Můžeme si tak například vytvořit sadu adres uživatelů, kteří dříve porušili pravidla a dostali nějaký zákaz. Poté jednoduše můžeme kdykoliv sadu editovat a tím přidávat nebo odebírat další adresy.

# nft add set inet filter badboys { type ipv4_addr\;}
# nft add element inet filter badboys { 192.168.1.4 }
# nft add element inet filter badboys { 192.168.2.8, 192.168.2.15 }
# nft add rule inet filter input ip saddr @badboys reject

Typ každého setu je povinný údaj a může obsahovat tyto varianty: ipv4_addr, ipv6_addr, ether_addr, inet_proto, inet_service, mark a ifname. Typ určuje, jaká data se budou v setu nacházet.

U setů je možné nastavovat další vlastnosti. Můžeme tak například nastavit, že nově přidaná položka vždy po určité době ze setu automaticky vypadne.

# nft add set ip filter ports {type inet_service \; timeout 8h \;}

Je také možné stanovit maximální velikost setu, tedy počet položek, který je do něj možné přidat.

# nft add set ip filter saddrs {type ipv4_addr \; size 10 \;}

Můžeme také zapnout možnost uvádět u každé položky individuální čas, po kterém bude tato položka vyřazena.

# nft add set ip filter daddrs {type ipv4_addr \; flags timeout \;}
# nft add element ip filter daddrs {192.168.1.1 timeout 10h, 192.168.1.2 timeout 24h}

Slovníky (mapy verdiktů)

Slovníky vnitřně používají obecnou infrastrukturu pro sety, ale umožňují svázat položku přímo s akcí. Někdy se jim proto také říká mapy verdiktů. Umožňují ohromně zjednodušit správu firewallu, protože vše podstatné shrnují v jedné společné struktuře. Nic podobného v iptables nenajdete.

Je tak možné například vytvořit slovník, ve kterém budeme uvádět kombinaci IP adres a akce, kterou chceme při shodě provést. Na některé adresy chceme provoz pustit, jiné chceme blokovat. Vytvoříme proto slovník, naplníme jej daty a poté použijeme v příslušném pravidlu.

# nft add map filter address { type ipv4_addr : verdict\; }
# nft add element filter address { 192.168.1.1 : drop, 192.168.1.2 : accept, 192.168.1.3 : drop }
# nft add rule filter input ip daddr vmap @address

Nemusíme se samozřejmě omezit jen na zamítnutí či povolení provozu, můžeme skákat do jiných řetězců nebo třeba logovat. Úpravu pravidel pak provádíme pouhým zásahem do slovníku.

Mapy

Mapy jsou také interně postaveny na setech a umožňují rozhodovat o výstupu podle různých vstupních dat. Můžeme tak například velmi přehledně vytvořit DNAT a přesměrovat tak provoz na různé IP adresy podle příchozích portů. Různé služby nám pak mohou obsluhovat různé stroje.

# nft add rule ip nat prerouting dnat tcp dport map { 443 : 192.168.1.1, 53 : 192.168.1.2 }

Opět můžeme vytvořit pojmenovanou mapu, která nám umožní pozdější snadnou editaci. Přidáním nového prvku tak můžeme velmi jednoduše přidávat další přesměrování.

# nft add map nat redirect  { type inet_service: ipv4_addr\; }
# nft add element nat redirect { 443 : 192.168.1.1, 53 : 192.168.1.2 }
# nft add rule ip nat postrouting snat tcp dport map @redirect

Rozsahy

Rozsahy jsou přesně tím, čím mají být: rozsahem určitých hodnot zapsaných v pravidlech. Můžeme tak velmi snadno zvolit například rozmezí portů, na které budeme blokovat komunikaci.

# nft add rule filter input tcp ports 1-1024 reject

Rozsahy ale můžeme kombinovat i se sety či slovníky. Můžeme tak například blokovat více rozsahů portů najednou.

# nft add rule filter input tcp ports { 1-1024, 2048-4096, 8888-10001 } reject

Řetězení

Řetězení umožňuje do jednoho pravidla vložit různé vlastnosti, na které je paket zkontrolován. Tím se opět zpřehledňuje zápis, protože je možné do jednoho pravidla vložit kombinaci prvků. Následující pravidlo například vyhoví, pokud se zároveň shoduje zdrojová adresa, cílová adresa a cílový port.

# nft add rule ip filter input ip saddr . ip daddr . ip dport { 192.168.1.1 . 192.168.2.2 . ssh, 192.168.3.1 . 192.168.4.3 . https} accept

Správná zábava ovšem začne ve chvíli, kdy začnete řetězení používat společně se sety či mapami. Je to užitečné, ale zároveň velmi efektivní, protože je možné napříč touto strukturou velmi rychle vyhledávat a rozhodovat.

Můžeme tak například vytvořit slovník, který bude obsahovat řetězení. Snadno tak můžeme dosáhnout filtru, který bude rozhodovat na základě kombinace zdrojové IP adresy a cílového portu. Přístup ke službám tak povolíme jen konkrétním strojům.

# nft add map filter opened { type ipv4_addr . inet_service : verdict \; }
# nft add rule filter input ip saddr . tcp dport vmap @opened
# nft add element filter opened { 192.168.1.1 . 443 : accept}

Příště příklady

V příštím díle si ukážeme, jak může vypadat konfigurace konkrétního firewallu v různých situacích. Propojíme tím znalostí získané v předchozích článcích a předvedeme si některá použitelná řešení.