Product SiteDocumentation Site

14.2. Brannmur eller pakkefiltrering

En brannmur er en filtrerende nettverkspassasje, og er bare effektiv på pakker som må gå gjennom den. Den kan derfor bare være effektiv når den eneste ruten for disse pakkene er gjennom brannmuren.
Linux-kjernen inneholder brannmuren netfilter. Den kan kontrolleres fra brukersiden med kommandoene iptables, ip6tables, arptables og ebtables.
Imidlertid blir Netfilter iptables-kommandoer erstattet av nftables, noe som unngår mange av dets problemer. Designet innebærer mindre kodeduplisering, og det kan administreres med kun nft-kommandoen. Siden Debian Buster brukes nftables-rammeverket som forvalg. Kommandoene som tidligere ble nevnt tilbys av versjoner, som bruker kjerne-API-et til nftables, som forvalg. Hvis man vil ha de klassiske kommandoene, kan de relevante kjørbare filene justeres med update-alternatives.
Slik aktiverer du en forvalgt brannmur i 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. nftables-oppførsel

Når kjernen behandler en nettverkspakke pauser den og tillater oss å inspisere pakken og bestemme hva du skal gjøre med den pakken. Vi vil for eksempel kanskje droppe eller forkaste visse innkommende pakker, endre andre pakker på ulike måter, blokkere visse utgående pakker for å kontrollere mot skadelig programvare, eller omdirigere noen pakker så tidlig som mulig for å bygge bro over nettverksgrensesnitt, eller spre belastningen av innkommende pakker mellom systemer.
En god forståelse av lagene 3, 4 og 5 av OSI (Open Systems Interconnection)-modellen er avgjørende for å få mest mulig ut av netfilter.
Brannmuren er satt opp med tables, som inneholder rules som finnes i chains. I motsetning til iptables har nftables ingen standardtabell. Brukeren bestemmer hvilke og hvor mange tabeller som skal opprettes. Hver tabell må bare ha én av følgende fem familier tildelt: ip, ip6, inet, arp og bridge. ip brukes hvis familien ikke er angitt.
Det finnes to typer kjeder: grunnkjeder og vanlige kjeder. En grunnkjede er et inngangspunkt for pakker fra nettverksstabelen. Grunnkjedene registreres inn i Netfilter-krokene, dvs. disse kjedene ser pakker som strømmer gjennom TCP/IP-stabelen. En vanlig kjede er derimot ikke koblet til noen krok, og ser ikke noe trafikk, men kan brukes som et hopp-mål for bedre organisering av reglene.
Regler er laget av uttrykk, som inkluderer noen uttrykk som skal sammenlignes, og deretter en domsavgjørelse, som accept, drop, queue, continue, return, jump chain og goto chain.

14.2.2. Overgang fra iptables til nftables

Kommandoene iptables-translate og ip6tables-translate kan brukes til å oversette gamle iptables-kommandoer til den nye nftables-syntaksen. Hele regelsett kan også oversettes, i dette tilfellet overfører vi reglene som er satt opp på en datamaskin som har Docker installert:
# iptables-save > iptables-ruleset.txt
# iptables-restore-translate -f iptables-ruleset.txt

# Translated by iptables-restore-translate v1.8.9 on Wed Aug 14 00:35:02 2024
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 OUTPUT { type nat hook output priority -100; policy accept; }
add chain ip nat POSTROUTING { type nat hook postrouting 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 OUTPUT ip daddr != 127.0.0.0/8 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 DOCKER iifname "docker0" counter return
# Completed on Wed Aug 14 00:35:02 2024
# iptables-restore-translate -f iptables-ruleset.txt > ruleset.nft
# nft -f ruleset.nft
# nft list ruleset
# Warning: table ip nat is managed by iptables-nft, do not touch!
table ip nat {
	chain DOCKER {
		iifname "docker0" counter packets 0 bytes 0 return
		iifname "docker0" counter packets 0 bytes 0 return
	}

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

	chain PREROUTING {
		type nat hook prerouting priority dstnat; policy accept;
		fib daddr type local counter packets 0 bytes 0 jump DOCKER
		fib daddr type local counter packets 0 bytes 0 jump DOCKER
	}

	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
		ip daddr != 127.0.0.0/8 fib daddr type local counter packets 0 bytes 0 jump DOCKER
	}

	chain INPUT {
		type nat hook input priority 100; policy accept;
	}
}
# Warning: table ip filter is managed by iptables-nft, do not touch!
table ip filter {
	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
		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
		oifname "docker0" counter packets 0 bytes 0 drop
		counter packets 0 bytes 0 return
	}

	chain FORWARD {
		type filter hook forward priority filter; 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
		counter packets 0 bytes 0 jump DOCKER-USER
		counter packets 0 bytes 0 jump DOCKER-ISOLATION-STAGE-1
		oifname "docker0" ct state established,related 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 DOCKER-USER {
		counter packets 0 bytes 0 return
		counter packets 0 bytes 0 return
	}

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

	chain OUTPUT {
		type filter hook output priority filter; policy accept;
	}
}
Verktøyene iptables-nft, ip6tables-nft, arptables-nft og ebtables-nft er versjoner av iptables som bruker NFTables-API-et, slik at brukerne kan fortsette å bruke den gamle iptables-syntaksen med dem, men det anbefales ikke; disse verktøyene bør kun brukes for bakoverkompatibilitet.

14.2.3. Syntaksen til nft

nft-kommandoene lar en manipulere tabeller, kjeder og regler. Alternativet table støtter flere operasjoner: add, create, delete, list og flush. nft add table ip6 mangle legger til en ny tabell fra ip6-familien.
Hvis du vil sette inn en ny grunnkjede i tabellen filter, kan du utføre følgende kommando (vær oppmerksom på at semikolonet må beskyttes med en omvendt skråstrek når du bruker Bash):
# nft add chain filter input { type filter hook input priority 0 \; }
Regler legges vanligvis til med følgende syntaks: nft add rule [family] table chain handle handle statement.
insert ligner på add-kommandoen, men den gitte regelen blir lagt til i begynnelsen av kjeden eller før regelen med den angitte referansen i stedet for på slutten eller etter denne regelen. Følgende kommando setter for eksempel inn en regel foran regelen med referansenummer 8:
# nft insert rule filter output position 8 ip daddr 127.0.0.8 drop
De utførte kommandoene nft gjør ikke permanente endringer i oppsettet, så de går tapt hvis de ikke lagres. Brannmurreglene er plassert i /etc/nftables.conf. En enkel måte å lagre det gjeldende brannmuroppsettet permanent, er å kjøre nft list ruleset > /etc/nftables.conf som rot-bruker.
nft tillater mange flere operasjoner, sjekk den tilhørende manualsiden nft(8) for mer info.

14.2.4. Å installere reglene ved hver oppstart

For å aktivere en standard-brannmur i Debian må du lagre reglene i /etc/nftables.conf og utføre systemctl enable nftables som root. Du kan stoppe brannmuren ved å kjøre nft flush ruleset som rot-bruker.
I andre tilfeller er den anbefalte måten å registrere skriptet i up-anvisningen til /etc/network/interfaces-filen. I det følgende eksemplet er skriptet lagret under /usr/local/etc/arrakis.fw.

Eksempel 14.1. interfaces-fil (grensesnittsfil) som påkaller et brannmursskript

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
Dette forutsetter selvsagt at du bruker ifupdown til å sette opp nettverksgrensesnittet. Hvis du bruker noe annet (som NetworkManager eller systemd-networkd), les deretter deres respektive dokumentasjon for å finne ut måter til å kjøre et skript, etter at grensesnittet har blitt tatt opp.