Hlavní navigace

nftables: správa pravidel v našem firewallu

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 správu vlastních pravidel a přidávání počítadel.
Petr Krčmář
Doba čtení: 5 minut

Sdílet

minulém článku z našeho seriálu jsme si vysvětlili, jak fungují tabulky a řetězce v nich. Poté jsme si ukázali, jak do řetězce vložit pravidlo a jak to nakonec celé zálohovat do souboru. Dnes se podíváme podrobně na správu pravidel v našich řetězcích.

Přidání nového pravidla

Pokud už máme vytvořenou alespoň jednu tabulku a v ní alespoň jeden řetězec, můžeme do něj přidat vlastní pravidlo. Použijeme opět naši oblíbenou univerzální utilitu  nft, které musíme kromě samotného pravidla sdělit, do jaké tabulky a řetězce jej chceme přidat.

# nft add rule inet filter output ip daddr 8.8.8.8 accept

V tomto příkladu jsme použili příkaz add, který přidá nové pravidlo na konec řetězce. Pokud chceme přidat pravidlo na začátek, použijeme místo toho příkaz insert. Poté uvedeme název tabulky (v našem případě filter)  a řetězce ( output) a následuje samotný zápis pravidla.

Můžeme se podívat, jak v tuhle chvíli vypadá aktuální konfigurace:

# nft list table inet filter
table inet filter {
    chain output {
        type filter hook output priority 0; policy accept;
        ip daddr 8.8.8.8 accept
    }
}

Přidání na určenou pozici

Tímto způsobem můžeme přidat či odebrat pravidlo na začátek nebo na konec. Máme ale také samozřejmě možnost přidat pravidlo mezi už existující položky. Ty jsou interně očíslovány a čísla pravidel si můžeme vypsat pomocí parametru -a. Pro názornost jsem do řetězce přidal několik dalších podobných pravidel.

# nft list table inet filter -a
table inet filter { # handle 1
    chain output { # handle 1
        type filter hook output priority 0; policy accept;
        ip daddr 8.8.8.8 accept # handle 2
        ip daddr 8.8.4.4 accept # handle 3
        ip daddr 1.1.1.1 accept # handle 4
    }
}

Vidíte, že do výpisu přibyly komentáře. Ty obsahují popisky s čísly jednotlivých položek. Pokud bychom nyní chtěli vložit další pravidlo doprostřed výpisu, stačí nám vybrat pozici sousedního už existujícího pravidla. Opět můžeme nové pravidlo přidat za něj ( add) nebo před něj ( insert).

# nft add rule inet filter output position 3 ip daddr 1.0.0.1 accept
# nft list table inet filter -a
table inet filter { # handle 1
    chain output { # handle 1
        type filter hook output priority 0; policy accept;
        ip daddr 8.8.8.8 accept # handle 2
        ip daddr 8.8.4.4 accept # handle 3
        ip daddr 1.0.0.1 accept # handle 5
        ip daddr 1.1.1.1 accept # handle 4
    }
}

Za pozici číslo 3 jsme přidali další pravidlo. Všimněte si, že dostalo další číslo v sekvenci, tedy číslo 5. Zařadilo se na správnou pozici.

Velmi podobně můžeme pomocí parametru replace zvolit, že chceme pravidlo s konkrétním číslem nahradit. Například takto:

Root linux

# nft replace rule inet filter output handle 3 ip daddr 8.8.4.4 reject

Odstranění pravidla

Pomocí čísla můžeme také pravidlo jednoduše odstranit. Řekněme, že se nám nelíbí hned to první, tedy s číslem 2. Odstranění je dílem jednoduchého příkazu.

# nft delete rule inet filter output handle 2
# nft list table inet filter -a
table inet filter { # handle 1
    chain output { # handle 1
        type filter hook output priority 0; policy accept;
        ip daddr 8.8.4.4 accept # handle 3
        ip daddr 1.0.0.1 accept # handle 5
        ip daddr 1.1.1.1 accept # handle 4
    }
}

Pravidla a jejich parametry

Abychom mohli zapisovat skutečná pravidla, musíme znát jejich názvy. Každé pravidlo má také různé parametry, které umožňují přesně popsat, co chceme na daném paketu zkoumat. Níže uvádím přehled nejběžnějších možností používaných s nftables.

meta – meta informace, například o rozhraní
  oif <index výstupního rozhraní>
  iif <index vstupního rozhraní>
  oifname <název výstupního rozhraní>
  iifname <název vstupního rozhraní>

icmp – protokol ICMP
  type <typ icmp>

icmpv6 – protokol ICMP
  type <typ icmpv6>

ip – protokol IPv4
  protocol <protokol>
  daddr <cílová adresa>
  saddr <zdrojová adresa>

ip6 – protokol IPv6
  daddr <cílová adresa>
  saddr <zdrojová adresa>

tcp – protokol TCP
  dport <cílový port>
  sport <zdrojový port>

udp – protokol UDP
  dport <cílový port>
  sport <zdrojový port>

sctp – protokol SCTP
  dport <cílový port>
  sport <zdrojový port>

ct – connection tracking, sledování spojení
  state <new | established | related | invalid>

Počítadla

Firewall nftables umožňuje zapínat u jednotlivých pravidel počítadla. Je potřeba o to ale explicitně požádat. Ve výchozím stavu se žádný provoz automaticky nepočítá. Můžeme ovšem snadno využít toho, že při splnění jednoho výrazu je možné provést více akcí. Můžeme tedy paket například propustit a zároveň ho započítat.

Provedeme to tak, že při přidávání pravidla na jeho konec zapíšeme více akcí za sebou. Například takto:

# nft add rule inet filter output ip daddr 8.8.8.8 counter accept
# nft list table inet filter -a
table inet filter { # handle 1
    chain output { # handle 1
        type filter hook output priority 0; policy accept;
        ip daddr 8.8.8.8 counter packets 0 bytes 0 accept # handle 8
    }
}

Vidíte, že jsme zapsali nové pravidlo, které má u sebe nově i počítadlo. Můžeme rovnou vyzkoušet jeho funkci:

# ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=56 time=27.6 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=56 time=18.9 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=56 time=22.1 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=56 time=48.6 ms
64 bytes from 8.8.8.8: icmp_seq=5 ttl=56 time=38.5 ms
^C
--- 8.8.8.8 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 10ms
rtt min/avg/max/mdev = 18.947/31.156/48.601/10.982 ms

# nft list table inet filter -a
table inet filter { # handle 1
    chain output { # handle 1
        type filter hook output priority 0; policy accept;
        ip daddr 8.8.8.8 counter packets 5 bytes 420 accept # handle 8
    }
}

Komentáře

Velmi užitečné je mít přímo ve firewallu komentáře. Umožňují nám lépe se orientovat v našich pravidlech, případně v pravidlech dalších kolegů, kteří s námi síť spravují. Tyto komentáře jsou pevnou součástí pravidel a při výpisu je vždy uvidíme. Uvádějí se na konci definice nového pravidla.

# nft add rule inet filter output ip daddr 8.8.8.8 counter accept comment \"DNS resolver Google\"

Všimněte si, že jsem musel uvozovky escapovat, aby je shell neodstranil. Pokud to neuděláte, utilita nft dostane jednotlivá slova v komentáři jako samostatné parametry a nebude jim rozumět. Teď už zbývá jen vypsat si současný stav, ve kterém komentář uvidíme:

# nft list table inet filter -a
table inet filter { # handle 1
    chain output { # handle 1
        type filter hook output priority 0; policy accept;
        ip daddr 8.8.8.8 counter packets 0 bytes 0 accept comment "DNS resolver Google" # handle 10
    }
}

Příště budeme akční

Dnes jsme si ukázali, jak můžeme vytvářet pravidla pro filtrování jednotlivých paketů. V dalším článku si ukážeme, jaké akce je možné s pakety provádět. Můžeme je zaznamenávat, nastavovat u nich metainformace, upravovat hlavičky nebo třeba využívat NAT.