Created: 2024-09-26 Thu 05:55
Mit dem Befehl
# sudo lsmod | grep "nf_t"
kann geprüft werden, ob nftables im Linux-System schon aktiv ist.
nft Befehlnft Befehlnft Befehlnft kann Regeln aus einer Datei, von der Kommando-Zeile (Shell) oder in einem interaktiven Modus direkt vom der Tastatur einlesen.
Da die Beschreibungssprache Zeichen beinhalten kann, welche in Unix-Shells besondere Bedeutungen haben, müssen diese Zeichen, oder besser der gesamte nft Befehlsteil, per Quoting vor dem Zugriff der Shell geschützt werden.
nft BefehlBeispiel: Lesen der Firewall-Regeln aus einer Datei
# nft -f /etc/nftables/firewall.nft
Beispiel: Eine Regel (IPv4, Tabelle "fw", Kette "input") hinzufügen
# nft "add rule ip fw input drop"
Beispiel: eine interaktive nft Sitzung
# nft -ia
nft> list ruleset
table inet workstation-fw {
chain input {
type filter hook input priority 0;
}
}
Beispiel: eine interaktive nft Sitzung
nft> add rule inet workstation-fw input tcp dport {ssh, http} accept
nft> list ruleset
table inet workstation-fw {
chain input {
type filter hook input priority 0;
tcp dport { ssh, http} accept # handle 3
}
}
nft> quit
flush löscht Objekte aus der nftables Kernel-Firewall.flush ruleset löscht die gesamten Firewall-Regeln.flush ruleset sollte am Anfang eines nftables-Regelsatzes
stehen:
# nft flush ruleset
flush chain und flush table können Ketten und Tabellen
gelöscht werden.add fügt die Regel immer am Ende der Kette aninsert kann eine Regel an einer beliebigen Stelle der Kette
eingefügt werden.delete löscht eine Regel aus einer Kette. Zum Löschen
einer Regel wird das Handle der Regel benötigt, das Handle wird
über den Kommandozeilenparameter -a ausgegeben:
# nft -a list ruleset
...
ip6 saddr 2001:db8::/64 # handle 15
...
# nft delete rule inet filter input handle 15
Mittels nft monitor können Änderungen in der nftables-Firewall
überwacht werden.
Der Befehl schreibt Modifikationen im Regelsatz der Firewall als
nft-Befehlszeilen (Alternativ als XML oder JSON) auf die Konsole:
# nft monitor
add table inet filter
add chain inet filter input { type filter hook input priority 0; }
add rule inet filter input iif lo accept
add rule inet filter input ct state established,related accept
add rule inet filter input ip6 daddr ff02::1010 udp dport ntp accept
add rule inet filter input ip6 daddr ff02::fb udp dport mdns accept
add rule inet filter input ip daddr 224.0.0.251 udp dport mdns accept
add rule inet filter input ip6 saddr & :: == :: udp dport dhcpv6-client accept
add rule inet filter input udp dport ipp accept
add rule inet filter input ip6 saddr & :: == :: icmpv6
type { nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert} accept
add rule inet filter input ip6 saddr & :: == :: icmpv6
type { echo-reply, echo-request, packet-too-big, destination-unreachable,
time-exceeded, param-problem} accept
add rule inet filter input counter packets 0 bytes 0 log prefix "nftables drop: " drop
table inet filter01 {
chain input01 {
type filter hook input priority 0;
}
chain output01 {
type filter hook output priority 0;
}
}
goto oder jump Direktive an die "auxiliary
chain" verteilt werden:
table inet filter01 {
# auxiliary chain
chain link-local-aux01 {
counter packets 0 bytes 0 log prefix "link-local: " accept
# weitere Regeln für link-local IPv6
[...]
}
# base chain
chain input01 {
type filter hook input priority 0;
ip6 daddr fe80::/64 jump link-local-aux01
}
# base chain
chain output01 {
type filter hook output priority 0;
}
}
daddr
ff02::fb und dem UDP-Port dport mdns (Multicast-DNS):
# nft "add rule inet filter input ip6 daddr" \
"ff02::fb udp dport mdns accept"
nft.accept (Paket passieren lassen) * drop (Paket
ohne Rückmeldung an den Sender verwerfen) und * reject (mit
Rückmeldung verwerfen).reject kann optional die ICMP-Meldung spezifiziert werden,
welche an den Sender des Paketes zurückgeliefert wird:
# nft "add rule inet filter input ip6 saddr 2001:db8::/64" \
"reject with icmpv6 type admin-prohibited"
Neben den entgültigen Urteilen kann eine Regel die Bearbeitung eines Paketes auch an anderen Stelle fortsetzen:
continue Bearbeitung des Paketes mit die nächsten Regel in der
Kettejump <chain> verzweigt die Bearbeitung wie ein Unterprogrammaufruf
in eine andere Kette. Am Ende der neuen Kette wird die Bearbeitung in
der ursprünglichen Kette weitergeführt.goto <chain> wird direkt in eine andere Kette gesprungen, ohne das
die Bearbeitung jemals wieder zurückkehrt.queue verzweigt die Verarbeitung an ein externes Programm im
Userspace.return beendet die Bearbeitung der aktuellen Kette an dieser
Stelle. Wird return in einer Kette der obersten Bearbeitungsebene
verwendet, so wird das Paket durch die Firewall gelassen (identisch
zu einem accept).list ruleset, ausgegeben.log in der Regel wichtig:
log nach der Filterbedingung, so wird
der Log-Eintrag nur geschrieben, wenn die Filterbedingung
zutrifft.counter.
# schreibe einen Log-Eintrag für jedes Paket
# welches von dieser Regel gesehen wird
log tcp dport { 22, 80, 443 } ct state new accept
# schreibe einen Log-Eintrag nur wenn die Regel zutrifft
tcp dport { 22, 80, 443 } ct state new log counter accept
log kann mit dem Parameter prefix eine beliebige Zeichenkette mitgegeben werden.
table inet filter {
chain input {
...
}
}
define deklariert und
mit einem Wert versehen. Im Regelwerk wird dann der Variablenname
mit einem vorangestellem Dollar-Zeichen "$" verwendet, vergleichbar
mit Variablen der Unix-Shell.
define lan_if = eth0
define DMZ-Dienste = { ssh, smtp, dns, http, https }
add rule inet filter input iif $lan_if tcp dport $DMZ-Dienste accept
nft "add rule inet filter input ip6 daddr 2001:db8::0-2001:db8::1000 drop" nft "add rule inet filter input tcp dport 0-1023 drop"
nft "add rule inet filter input udp dport { 137, 138, 139, 445 } reject"
nft "add set inet filter bogus { type ipv4_addr; }"
nft "add element inet filter bogus { 203.0.113.0; }"
nft "add element inet filter bogus { 203.0.113.1; }"
nft "add rule inet filter input ip saddr @bogus drop"
nft "list set inet filter bogus"
# nft "add rule ip nat prerouting dnat" \
"tcp dport map { 80 : 192.168.1.100, 8888 : 192.168.1.101 }"
nft "add map inet filter aktion { type ipv4_addr : verdict; }"
nft "add element inet filter aktion" \
"{ 192.0.2.80 : accept, 192.0.2.88 : drop, 192.0.2.99 : drop }"
nft "add rule inet filter input ip saddr vmap @aktion"
flush ruleset
define any = 0::0/0
table inet filter {
chain input {
type filter hook input priority 0;
# accept any localhost traffic
iif lo accept
# accept traffic originated from us
ct state established,related accept
# activate the following line to accept common local services
#tcp dport { 22, 80, 443 } ct state new accept
# NTP multicast
ip6 daddr ff02::1010 udp dport 123 accept
# mDNS (avahi)
ip6 daddr ff02::fb udp dport 5353 accept
ip daddr 224.0.0.251 udp dport 5353 accept
# DHCPv6
ip6 saddr $any udp dport 546 accept
# IPP (CUPS)
udp dport 631 accept
# Accept neighbour discovery otherwise IPv6 connectivity breaks.
ip6 saddr $any icmpv6 type { nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } accept
# Accept essential icmpv6
# nft cannot parse "param-problem" (icmpv6 type 4)
ip6 saddr $any icmpv6 type { echo-reply, echo-request, packet-too-big, destination-unreachable, time-exceeded, 4 } accept
# count and drop any other traffic
counter log prefix "nftables drop: " drop
}
}
flush ruleset
define any = 0::0/0
table inet filter {
chain input {
type filter hook input priority 0;
# accept any localhost traffic
iif lo accept
# accept traffic originated from us
ct state established,related accept
...
...
# activate the following line to accept common local services
#tcp dport { 22, 80, 443 } ct state new accept
# NTP multicast
ip6 daddr ff02::1010 udp dport 123 accept
# mDNS (avahi)
ip6 daddr ff02::fb udp dport 5353 accept
ip daddr 224.0.0.251 udp dport 5353 accept
# DHCPv6
ip6 saddr $any udp dport 546 accept
# IPP (CUPS)
udp dport 631 accept
...
...
# Accept neighbour discovery otherwise IPv6 connectivity breaks.
ip6 saddr $any icmpv6 type {
nd-neighbor-solicit,
nd-router-advert,
nd-neighbor-advert
} accept
# Accept essential icmpv6
# nft cannot parse "param-problem" (icmpv6 type 4)
ip6 saddr $any icmpv6 type {
echo-reply,
echo-request,
packet-too-big,
destination-unreachable,
time-exceeded, 4
} accept
# count and drop any other traffic
counter log prefix "nftables drop: " drop
}
}
#!/usr/bin/nft -f
flush ruleset
define mgt_if = eth0
define wan_if = eth1
define lan_if = eth3
define dmz_if = eth2
define any_v6 = 0::0/0
table inet gateway-fw {
chain forward {
type filter hook forward priority 0
# accept established traffic
ct state established,related accept
# allow all outgoing traffic from LAN
iif $lan_if accept
# access to services in the DMZ
oif $dmz_if tcp dport { http, https, smtp, imap, imaps } counter accept
# Accept essential icmpv6
# nft cannot parse "param-problem" (icmpv6 type 4)
ip6 saddr $any_v6 icmpv6 type { echo-reply, echo-request, packet-too-big, destination-unreachable, time-exceeded, 4 } accept
# reject everything else
counter log reject
}
chain input {
type filter hook input priority 0
iif lo accept
iif $mgt_if tcp dport ssh accept
ip6 saddr $any_v6 icmpv6 type { nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } accept
ip6 saddr $any_v6 icmpv6 type { echo-reply, echo-request, packet-too-big, destination-unreachable, time-exceeded, 4 } accept
counter log reject
}
}
table ip nat {
chain prerouting {
type nat hook prerouting priority 0
}
chain postrouting {
type nat hook postrouting priority 0
oif $wan_if log masquerade
}
}
#!/usr/bin/nft -f
flush ruleset
define mgt_if = eth0
define wan_if = eth1
define lan_if = eth3
define dmz_if = eth2
define any_v6 = 0::0/0
...
...
table inet gateway-fw {
chain forward {
type filter hook forward priority 0
# accept established traffic
ct state established,related accept
# allow all outgoing traffic from LAN
iif $lan_if accept
# access to services in the DMZ
oif $dmz_if tcp dport { http, https, smtp, imap, imaps } counter accept
# Accept essential icmpv6
# nft cannot parse "param-problem" (icmpv6 type 4)
ip6 saddr $any_v6 icmpv6 type {
echo-reply, echo-request,
packet-too-big, destination-unreachable,
time-exceeded, 4 } accept
# reject everything else
counter log reject
}
...
...
chain input {
type filter hook input priority 0
iif lo accept
iif $mgt_if tcp dport ssh accept
ip6 saddr $any_v6 icmpv6 type {
nd-neighbor-solicit, nd-router-advert,
nd-neighbor-advert
} accept
ip6 saddr $any_v6 icmpv6 type {
echo-reply, echo-request,
packet-too-big, destination-unreachable,
time-exceeded, 4
} accept
counter log reject
}
} # end table inet gateway-fw
...
...
table ip nat {
chain prerouting {
type nat hook prerouting priority 0
}
chain postrouting {
type nat hook postrouting priority 0
oif $wan_if log masquerade
}
}