Product SiteDocumentation Site

14.2. Firewall oder Paketfilter

Eine Firewall ist ein filternder Netzübergang und nur bei Paketen wirksam, die durch sie hindurchgehen müssen. Deshalb kann sie nur dann wirksam sein, wenn der Weg durch die Firewall für diese Pakete die einzige Route ist.
Der Linux Kernel schließt die Netfilter-Firewall ein, die aus dem User Space mit den Befehlen iptables, ip6tables, arptables und ebtables gesteuert werden kann.
Netfilter iptables-Befehle werden jedoch durch nftables ersetzt, wodurch viele der Probleme vermieden werden. Das Design erfordert weniger Duplizierung im Code und kann einfach mit dem Befehl nft verwendet werden. Debian Buster verwendet standardmäßig das nftables-Framework.
So aktivieren Sie eine Standard-Firewall in Debian:
# apt install -y nftables
Reading package lists... Done
...
# systemctl enable nftables.service
Created symlink /etc/systemd/system/sysinit.target.wants/nftables.service → /lib/systemd/system/nftables.service.

14.2.1. Verhalten von nftables

Wenn der Kernel ein Netzwerkpaket verarbeitet, wird er gestoppt und ermöglicht es uns, das Paket zu überprüfen und zu entscheiden, was mit diesem Paket geschehen soll. Beispielsweise möchten wir möglicherweise bestimmte eingehende Pakete löschen oder verwerfen, andere Pakete auf verschiedene Weise ändern, bestimmte ausgehende Pakete blockieren um sie vor Malware zu schützen oder einige Pakete zum frühestmöglichen Zeitpunkt umleiten, um Netzwerkschnittstellen zu überbrücken oder die Last eingehender Pakete zwischen Systemen zu verteilen.
Ein gutes Verständnis der Schichten 3, 4 und 5 des OSI-Modells (Open Systems Interconnection) ist wichtig, um Netfilter optimal nutzen zu können.
Die Firewall wird mit Tabellen (tables) konfiguriert, die Regeln (rules) in sogenannten Ketten (chains) verwalten. Anders als iptables hat nftables keine Standardtabelle (default table). Der Benutzer legt fest, welche und wie viele Tabellen erstellt werden sollen. Jede Tabelle darf jedoch nur einer der folgenden fünf Kategorien zugeordnet werden: ip, ip6, inet, arp oder bridge. Ist die Kategorie nicht deklariert, wird ip genutzt.
Es existieren zwei Arten von Ketten: Basis-Ketten (base chains) und Reguläre Ketten (regular chains). Eine Basiskette ist der Einstiegspunkt für Pakete vom Netzwerk-Stack, sie werden in den Netfilter-Hooks registriert, d. H. diese Ketten sehen Pakete, die durch den TCP/IP-Stapel fließen. Auf der anderen Seite ist eine reguläre Kette an keinem "hook" registriert, sodass sie keinen Verkehr sehen. Sie kann jedoch als Sprungziel zur besseren Organisation der Regeln verwendet werden.
Regeln bestehen aus Aussagen (statements), die einige übereinstimmende Ausdrücke und dann eine Entscheidung enthalten, wie beispielsweise accept, drop, queue, continue, return, jump chain oder goto chain.

14.2.2. Der Wechsel von iptables zu nftables

Die Befehle iptables-translate und ip6tables-translate können dazu genutzt werden, iptables Befehle in die neuen nftables Syntax zu konvertieren. In einem Rechner mit installiertem Docker können sogar komplette Regelsätze (rulesets) konvertiert werden:
# iptables-save > iptables-ruleset.txt
# iptables-restore-translate -f iptables-ruleset.txt

# Translated by iptables-restore-translate v1.8.2 on Thu Jul 18 10:39:33 2019
add table ip filter
add chain ip filter INPUT { type filter hook input priority 0; policy accept; }
add chain ip filter FORWARD { type filter hook forward priority 0; policy drop; }
add chain ip filter OUTPUT { type filter hook output priority 0; policy accept; }
add chain ip filter DOCKER
add chain ip filter DOCKER-ISOLATION-STAGE-1
add chain ip filter DOCKER-ISOLATION-STAGE-2
add chain ip filter DOCKER-USER
add rule ip filter FORWARD counter jump DOCKER-USER
add rule ip filter FORWARD counter jump DOCKER-ISOLATION-STAGE-1
add rule ip filter FORWARD oifname "docker0" ct state related,established counter accept
add rule ip filter FORWARD oifname "docker0" counter jump DOCKER
add rule ip filter FORWARD iifname "docker0" oifname != "docker0" counter accept
add rule ip filter FORWARD iifname "docker0" oifname "docker0" counter accept
add rule ip filter DOCKER-ISOLATION-STAGE-1 iifname "docker0" oifname != "docker0" counter jump DOCKER-ISOLATION-STAGE-2
add rule ip filter DOCKER-ISOLATION-STAGE-1 counter return
add rule ip filter DOCKER-ISOLATION-STAGE-2 oifname "docker0" counter drop
add rule ip filter DOCKER-ISOLATION-STAGE-2 counter return
add rule ip filter DOCKER-USER counter return
add table ip nat
add chain ip nat PREROUTING { type nat hook prerouting priority -100; policy accept; }
add chain ip nat INPUT { type nat hook input priority 100; policy accept; }
add chain ip nat POSTROUTING { type nat hook postrouting priority 100; policy accept; }
add chain ip nat OUTPUT { type nat hook output priority -100; policy accept; }
add chain ip nat DOCKER
add rule ip nat PREROUTING fib daddr type local counter jump DOCKER
add rule ip nat POSTROUTING oifname != "docker0" ip saddr 172.17.0.0/16 counter masquerade
add rule ip nat OUTPUT ip daddr != 127.0.0.0/8 fib daddr type local counter jump DOCKER
add rule ip nat DOCKER iifname "docker0" counter return
# Completed on Thu Jul 18 10:39:33 2019
# iptables-restore-translate -f iptables-ruleset.txt > ruleset.nft
# nft -f ruleset.nft
# nft list ruleset
table ip filter {
	chain INPUT {
		type filter hook input priority 0; policy accept;
	}

	chain FORWARD {
		type filter hook forward priority 0; policy drop;
		counter packets 0 bytes 0 jump DOCKER-USER
		counter packets 0 bytes 0 jump DOCKER-ISOLATION-STAGE-1
		oifname "docker0" ct state related,established counter packets 0 bytes 0 accept
		oifname "docker0" counter packets 0 bytes 0 jump DOCKER
		iifname "docker0" oifname != "docker0" counter packets 0 bytes 0 accept
		iifname "docker0" oifname "docker0" counter packets 0 bytes 0 accept
	}

	chain OUTPUT {
		type filter hook output priority 0; policy accept;
	}

	chain DOCKER {
	}

	chain DOCKER-ISOLATION-STAGE-1 {
		iifname "docker0" oifname != "docker0" counter packets 0 bytes 0 jump DOCKER-ISOLATION-STAGE-2
		counter packets 0 bytes 0 return
	}

	chain DOCKER-ISOLATION-STAGE-2 {
		oifname "docker0" counter packets 0 bytes 0 drop
		counter packets 0 bytes 0 return
	}

	chain DOCKER-USER {
		counter packets 0 bytes 0 return
	}
}
table ip nat {
	chain PREROUTING {
		type nat hook prerouting priority -100; policy accept;
		fib daddr type local counter packets 0 bytes 0 jump DOCKER
	}

	chain INPUT {
		type nat hook input priority 100; policy accept;
	}

	chain POSTROUTING {
		type nat hook postrouting priority 100; policy accept;
		oifname != "docker0" ip saddr 172.17.0.0/16 counter packets 0 bytes 0 masquerade
	}

	chain OUTPUT {
		type nat hook output priority -100; policy accept;
		ip daddr != 127.0.0.0/8 fib daddr type local counter packets 0 bytes 0 jump DOCKER
	}

	chain DOCKER {
		iifname "docker0" counter packets 0 bytes 0 return
	}
}
table ip mangle {
	chain PREROUTING {
		type filter hook prerouting priority -150; policy accept;
	}

	chain INPUT {
		type filter hook input priority -150; policy accept;
	}

	chain FORWARD {
		type filter hook forward priority -150; policy accept;
	}

	chain OUTPUT {
		type route hook output priority -150; policy accept;
	}

	chain POSTROUTING {
		type filter hook postrouting priority -150; policy accept;
	}
}
Die Hilfsprogramme iptables-nft, ip6tables-nft, arptables-nft, ebtables-nft sind Versionen von iptables welche die nftables API nutzen, damit Systemverwalter die veraltete iptables-Syntax weiter nutzen können. Aber dies wird nicht empfohlen; stattdessen sollten diese Hilfsprogramme lediglich die Rückwärtskompatibilität ermöglichen.

14.2.3. Die Syntax von nft

Der Befehl nft erlaubt die Bearbeitung von Tabellen (tables), Ketten (chains) und Regeln (rules). Die Tabellen--Option bietet mehrere Optionen: add, create, delete, list und flush. nft add table ip6 mangle erstellt eine neue Tabelle aus der Protokloll-Familie ip6.
Um eine neue Basikette (base chain) in der filter-Tabelle zu erstellen, wird das folgende Kommando ausgeführt (Beachten Sie, dass das Semikolon bei Verwendung von Bash mit einem Backslash versehen werden muss):
# nft add chain filter input { type filter hook input priority 0 \; }
Regeln werden normalerweise mit der folgenden Syntax hinzugefügt: nft add rule [Familie] Tabelle Kette handle Handle statement .
insert ähnelt dem Befehl add, aber die angegebene Regel wird am Anfang der Kette oder vor der Regel mit dem angegebenen Handle vorangestellt, anstatt am Ende oder nach dieser Regel. Beispielsweise fügt der folgende Befehl eine Regel vor der Regel mit dem Handler Nummer 8 ein:
# nft insert rule filter output position 8 ip daddr 127.0.0.8 drop
Die ausgeführten nft-Befehle nehmen keine dauerhaften Änderungen an der Konfiguration vor, sodass sie verloren gehen, wenn sie nicht gespeichert werden. Die Firewall-Regeln befinden sich in /etc/nftables.conf. Eine einfache Möglichkeit, die aktuelle Firewall-Konfiguration dauerhaft zu speichern, besteht darin, nft list ruleset > /etc/nftables.conf als root auszuführen.
nft erlaubt viele weitere Operationen, siehe seine Handbuchseite nft(8) für weitere Informationen.

14.2.4. Die Regeln bei jedem Rechnerstart installieren

Um eine Standard-Firewall in Debian zu aktivieren, müssen Sie die Regeln in /etc/nftables.conf speichern und systemctl enable nftables.service als root ausführen. Sie können die Firewall daran hindern, nft flush ruleset als root auszuführen.
In anderen Fällen besteht der empfohlene Weg darin, das Konfigurationsskript in einer up-Anweisung der Datei /etc/network/interfaces einzutragen. Im folgenden Beispiel ist das Skript unter /usr/local/etc/arrakis.fw gespeichert.

Beispiel 14.1. Aufruf eines Firewallskripts durch eine interfaces-Datei

auto eth0
iface eth0 inet static
    address 192.168.0.1
    network 192.168.0.0
    netmask 255.255.255.0
    broadcast 192.168.0.255
    up /usr/local/etc/arrakis.fw
Dies setzt natürlich voraus, dass Sie ifupdown verwenden, um die Netzwerk-Schnittstellen zu konfigurieren. Wenn Sie etwas anderes (wie NetworkManager oder Systemd Networkd) verwenden, dann suchen Sie in der Dokumentation Möglichkeiten ein Skript auszuführen, nachdem die Schnittstelle hochgefahren wurde.