nftables
Tato kapitola výrazně navazuje na předešlou kapitolu o iptables a pro pochopení některých souvislostí je nutné znát i iptables.
nftables je podsystém jádra Linux, sloužící pro filtrování síťové komunikace. Nahrazuje nástroj iptables a zároveň mění vnitřní fungování Netflitru. Oproti iptables přináší také podporu pro IPv6 a ARP filtrování. Pro manipulaci s nftables používáme utilitu nft
nftables vs. iptables
Nástroje iptables a nftables jsou podobné, ale najdeme mezi nimi podstatné rozdíly, mezi ty hlavní patří tyto:
nftables již neobsahují žádné výchozí tabulky ani řetězce, ty si při konfiguraci nastavujeme sami za pomocí tzv. hooks
pravidla v nftables mohou vykonávat několik akcí, narozdíl od iptables, kde jedno pravidlo = jedna akce
nftables pravidla jsou dynamická, což zlepšuje jejich správu a výkon.
Ruleset
Tímto pojmem označujeme celou konfiguraci nftables, tedy všechny tabulky, řetězce apod. Pro jeho vypsání můžeme použít příkaz:
nft list ruleset
Naopak pro smazání celé konfigurace můžeme použít příkaz:
nft flush ruleset
Address families
Definují jaký protokol budeme v tabulce využívat. Mezi ty základní patří tyto:
Název | Využití |
---|---|
ip | Pouze IPv4 adresy |
ip6 | Pouze IPv6 adresy |
inet | Internet neboli jak IPv4, tak IPv6 adresy |
arp | ARP protokol pro IPv4 adresy |
Tabulky
Tabulky stejně jako v iptables sdružují řetězce, ale narozdíl od iptables nejsou v nftables žádné předdefinované a tedy si všechny tvoříme sami. Při tvoření definujeme address family, neboli s jakým protokolem bude tabulka pracovat a její název.
Pro základní manipulaci s tabulkami používáme příkazy:
add
- pro vytvoření tabulky
delete
- pro smazání tabulky
list
- pro vypsání všech řetězců a pravidel v dané tabulce, pokud místo table použijeme tables, vypíší se všechny tabulky v rulesetu
flush
- pro smazání všech řetězců a pravidel v dané tabulce
Syntaxe je následující:
nft [příkaz] table [address family] [název tabulky]
Například pro vytvoření tabulky pro IPv4 a IPv6 adresy s názvem nase_tabulka využijeme příkaz
nft add table inet nase_tabulka
A pro její smazání příkaz
nft delete table inet nase_tabulka
Řetězce
Opět stejně jako v iptables řetězce sdružují pravidla a jsou umístěné v tabulkách a opět nejsou žádné v nftables předdefinované, takže si všechny tvoříme sami. V nftables najdeme dva druhy řetězců a to základní (base) a standardní (regular). Rozdíl je, že základní řetězce přijímají pakety automaticky dle nastaveného hook a typu, zatímco běžné řetězce slouží jenom jako cíle.
Pro základní manipulaci s řetězci používáme příkazy:
add
- pro vytvoření řetězce
delete
- pro smazání řetězce
rename
- pro přejmenování řetězce
list
- pro vypsání všech pravidel daného řetězce
flush
- pro vymazání všech pravidel daného řetězce
Tvorba základních řetězců
Pro tvorbu základních řetězců používáme následující syntaxi
nft [příkaz] chain [address family] [název tabulky] [název řetězce] '{type [typ řetězce] hook [hook] priority [priorita]; }'
typ řetězce nám určuje jaké akce bude řetězec provádět, jejich seznam se nachází v tabulce níže, hook nám určuje v jaké fázi zpracování chceme aby řetězec paket zachytil a nakonec priorita určuje v jakém pořadí se bude řetězec zpracovávat, čím nižší číslo, tím dříve se bude řetězec zpracovávat.
Typy řetězců
Název | Využití |
---|---|
filter | Nejpoužívanější typ, určen pro filtrování |
nat | Typ pro aplikaci Network address translation - pouze ip, ip6 a inet address families a prerouting, input, output, postrouting hooks |
route | Typ pro routování - pouze ip a ip6 address families a output hook |
ip/ip6/inet hooks
Název | Využití |
---|---|
input | Příchozí pakety |
output | Odchozí pakety |
forward | Procházející pakety |
prerouting | Pakety před zpracováním routovací tabulkou |
postrouting | Pakety po zpracování routovací tabulkou |
arp hooks
Název | Využití |
---|---|
input | Příchozí pakety |
output | Odchozí pakety |
Například pro tvorbu řetězce nas_retezec který bude filtrovat všechny příchozí pakety v tabulce nase_tabulka s prioritou 0, využijeme následující příkaz:
nft add chain inet nase_tabulka nas_retezec '{type filter hook input priority 0; }'
Tvorba standardních řetězců
Pro manipulaci se standardními řetězci používame stejnou syntaxi, jako pro základní řetězce, jen vynecháme typ, hook a prioritu neboli syntaxe vypadá takto:
nft [příkaz] chain [address family] [název tabulky] [název řetězce]
Pravidla
Pravidla jsou obsažena v řetězcích a skládají se typicky z expression a verdiktu. Expression určuje shodu (např. při shodě IP adresy, při shodě portu…). Verdikt určuje akci, která se při shodě provede (např. zahodit paket, propustit paket…).
Pro základní manipulaci s pravidly používáme příkazy:
add
- pro vytvoření pravidla na konci řetězce
delete
- pro smazání pravidla
insert
- pro vytvoření pravidla na začátku řetězce
replace
- pro nahrazení zvoleného pravidla
A používáme následující syntaxi
nft [příkaz] rule [address family] [název tabulky] [název řetězce] [expresion] [verdikt]
Expression
Zde je základní výběr shod a argumentů, pomocí kterých budeme tvořit naše první pravidla.
ip:
daddr:
Cílová IP adresa
saddr:
Zdrojová IP adresa
ipv6:
daddr:
Cílová IPv6 adresa
saddr:
Zdrojová IPv6 adresa
tcp:
dport:
Cílový TCP port
sport:
Zdrojový TCP port
udp:
dport:
Cílový UDP port
sport:
Zdrojový UDP port
ct:
state:
Stav připojení <new | established | related | invalid>
icmp:
type:
Typ ICMP požadavku
icmpv6:
type:
Typ ICMPv6 požadavku
Verdikty
accept
- Přijme paket
drop
- Zahodí paket
counter
- Započítá paket do čítače
jump
- Skočí na jiný řetězec
Seznamy
Seznamy nám umožňují seskupit několik prvků, např. TCP porty. V nftables nalezneme dva typy, a to nepojmenované a pojmenované. Nepojmenovaný seznam je integrovaný v pravidlu a nelze ho měnit. V příkazu níže ho nalezneme označený tučně.
nft add rule inet nase_tabulka nas_retezec tcp dport **{http, https}** accept
Pojmenovaný seznam vytváříme v tabulce samostatně a můžeme ho upravovat. Pro manipulaci s pojmenovanými seznamy používáme příkazy:
add
- pro vytvoření pojmenovaného seznamu
delete
- pro smazání pojmenovaného seznamu
list
- pro vypsání pojmenovaného seznamu
flush
- pro smazání všech prvků z pojmenovaného seznamu
Příklad tvorby jednoduchého rulesetu
Nyní si můžeme ukázat tvorbu jednoduchého rulesetu za pomocí příkazů, které jsem si v této kapitole ukázali.
Vytvoříme si ruleset s jednou tabulkou pro IPv4 i IPv6 adresy, tato tabulka bude obsahovat 2 řetězce, a to pro filtrování příchozí a odchozí komunikace. Následně vytvoříme pravidlo pro započtení každého paketu s destinací na IP 1.1.1.1
a naposled nastavit politiku zahodit všechny příchozí pakety. Doporučuji se zadání nejdříve vypracovat samostatně a až poté se podívat na řešení.
Na začátek je vhodné, pokud již nemáme něco cíleně nakonfigurovaného, vymazat si celý ruleset. To provedeme následujícím příkazem:
nft flush ruleset
Nyní si vytvoříme tabulku, kam vše umístíme, je vhodné si jí pojmenovat podle účelu nebo podle jejího obsahu, abychom se v rulesetu později vyznali. V našem případě to bude inet_table
. K tomu použijeme tento příkaz:
nft add table inet inet_table
Následně v tabulce vytvoříme dva základní řetězce, jeden pro filtrování příchozí komunikace a jeden pro filtrování odchozí komunikace. To učiníme následujícími příkazy:
nft add chain inet inet_table output_chain '{type filter hook output priority 0; }'
nft add chain inet inet_table input_chain '{type filter hook input priority 0; }'
Následně si vytvoříme pravidlo pro počítaní paketů s destinací na IP 1.1.1.1
. Na to využijeme tento příkaz:
nft add rule inet inet_table output_chain ip daddr 1.1.1.1 counter
A nakonec přenastavíme politiku input_chain
aby veškeré pakety zahazoval. Na to pooužijeme tento příkaz:
nft chain inet inet_table input_chain '{ policy drop ; }'
Nyní si můžeme ruleset vypsat
nft list ruleset
Pokud jsme vše udělali správně, měl by výstup vypadat takto:
table inet inet_table {
chain output_chain {
type filter hook output priority filter; policy accept;
ip daddr 1.1.1.1 counter packets 0 bytes 0
}
chain input_chain {
type filter hook input priority filter; policy accept;
}
}
Aplikace NAT
V této části si pouze rozebereme konfiguraci NAT v nftables, teorii NAT jsme již rozebírali v kapitole o iptables.
Konfigurace SNAT
Pro konfiguraci SNAT využijeme tabulku ip/ip6/inet
, dle nastavení naší sítě a řetězec napojený na hook postrouting
. V tomto řetězci vytvoříme samotné pravidlo, které zachytí správné pakety a přepíše jejich zdrojovou IP adresu.
Konfigurace může například vypadat následovně:
nft add table ip nat_table
nft add chain ip nat_table snat_chain '{ type nat hook postrouting priority 100; }'
nft add rule ip nat_table snat_chain ip saddr 192.168.1.0/24 oif eth0 snat 146.6.177.31
Pro konfiguraci maškarády využijeme tento příkaz:
nft add rule ip nat_table snat_chain masquerade
Konfigurace DNAT
Používáme stejný postup jako při konfiguraci SNAT akorát s rozdílem, že se napojujeme na hook prerouting
místo postrouting
.
Konfigurace na přesměrování na náš webserver může vypadat například takto:
nft add table ip nat_table
nft add chain ip nat_table dnat_chain '{ type nat hook prerouting priority -100; }'
nft add rule ip nat_table dnat_chain iif eth0 tcp dport { 80, 443 } dnat 192.168.1.10
A pro konfiguraci přesměrování například následující příkaz:
nft add rule ip nat_table dnat_chain tcp dport 80 redirect to 8080
Diagnostika pravidel
V diagnostice pravidel nftables nám především pomohou 2 verdikty a to log
a counter
. Za pomocí log
můžeme provést záznam do systémového logu a za pomocí counter
můžeme počítat kolik paketů mělo shodu z daným pravidlem.
Překlad iptables
Pokud již máme pravidla v iptables formátu, můžeme je jednoduše přeložit do nft formátu pomocí utility iptables-translate
případně můžeme přeložit i celou iptables konfiguraci pomocí iptables-restore-translate
.
Uložení stavu
Jelikož nft
ukládá ruleset do paměti, při restartu počítače se ruleset nezachová. Pokud chceme aktuální ruleset zachovat použijeme následující příkaz:
nft list ruleset > /etc/nftables.conf
Systémy používající systemd
automaticky tento soubor hledají a načítají z něho.