Product SiteDocumentation Site

14.2. Tallafocs o filtratge de paquets

Un tallafocs és una passarel·la filtrant de xarxa i només és eficaç en paquets que han de passar a través d'ella. Per tant, només pot ser eficaç quan el pas pel tallafocs és l'única ruta per a aquests paquets.
El nucli de Linux innclou el tallafocs netfilter, que es pot controlar des de l'espai d'usuari amb les ordres iptables, ip6tables, arptablesi ebtables.
No obstant això, les ordres iptables de Netfilter s'estan substituint per nftables, que evita molts dels seus problemes. El seu disseny implica menys duplicació de codi, i es pot gestionar amb només l'ordre nft. A partir de Debian Buster, s'usa nftables per defecte. Les ordres esmentades anteriorment són proporcionades per versions, que utilitzen l'API nftables del nucli, per defecte. Si una requerís les ordres “clàssiques”, els binaris corresponents es poden ajustar utilitzant update-alternatives.
Per activar un tallafocs per defecte a Debian executeu:
# 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. El comportament d'nftables

Quan el nucli està processant un paquet de xarxa, fa una pausa i ens permet inspeccionar-lo i decidir què fer-ne. Per exemple, podríem voler deixar o descartar determinats paquets entrants, modificar altres paquets de diverses maneres, bloquejar certs paquets sortints per lluitar contra el programari maliciós o redirigir alguns paquets al més aviat possible a les interfícies de xarxa de pont o per repartir la càrrega dels paquets entrants entre sistemes.
Una bona comprensió de les capes 3, 4 i 5 del model OSI (Open Systems Interconnection) és essencial per obtenir el màxim rendiment del netfilter.
El tallafocs està configurat amb tables (taules), que contenen rules (regles) contingudes en chains (cadenes). A diferència d'iptables, nftables no té cap taula predeterminada. L'usuari decideix quines i quantes taules crear. Cada taula ha de tenir només una de les següents cinc famílies assignades: ip, ip6, inet, arp i bridge. S'utilitzarà ip si no s'especifica la família.
Hi ha dos tipus de cadenes: base chains (cadenes bàsiques) i regular chains (cadenes regulars). Una cadena bàsica és un punt d'entrada per als paquets des de la pila de xarxa. Les cadenes bàsiques són registrades als ganxos («hooks») de Netfilter, és a dir, veuen paquets fluint a través de la pila TCP/IP. D'altra banda, una cadena regular no s'uneix a cap ganxo, així que no veu cap trànsit. Però es pot utilitzar com a objectiu de salt per a una millor organització de les regles.
Les regles es composen de declaracions, que inclouen algunes expressions d'encaix i després una declaració de veredicte, com accept (acceptar), drop (retirar), queue (encuar), continu (continuar), return (retornar),jump chain (saltar cadena) i goto chain (anar a cadena).

14.2.2. Migració des d'iptables a nftables

Les ordres iptables-translate i ip6tables-translate es poden utilitzar per traduir ordres antigues d'iptables a la nova sintaxi d'nftables. També es poden traduir conjunts sencers de regles, en aquest cas migrem les regles configurades en un ordinador que té instal·lat Docker:
# iptables-save > iptables-ruleset.txt
# iptables-restore-translate -f iptables-ruleset.txt

# Translated by iptables-restore-translate v1.8.7 on Wed Mar 16 22:06:32 2022
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 Mar 16 22:06:32 2022
# iptables-restore-translate -f iptables-ruleset.txt > ruleset.nft
# nft -f ruleset.nft
# nft list ruleset
table inet filter {
	chain input {
		type filter hook input priority filter; policy accept;
	}

	chain forward {
		type filter hook forward priority filter; policy accept;
	}

	chain output {
		type filter hook output priority filter; policy accept;
	}
}
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 1 bytes 60 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;
	}
}
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;
	}
}
Les eines iptables-nft, ip6tables-nft, arptables-nft i ebtables-nft són versions d'iptables que utilitzen l'API nftables, de manera que els usuaris poden seguir utilitzant la sintaxi de l'antic iptables amb ells, però això no és recomanable; aquestes eines només s'han d'utilitzar per a compatibilitat amb versions anteriors.

14.2.3. Sintaxi d'nft

Les ordres nft permeten manipular taules, cadenes i regles. L'opció table admet múltiples operacions: add, create, delete, list i flush. nft add table ip6 mangle afegeix una taula nova de la família ip6.
Per a inserir una nova cadena base a la taula filter, podeu executar la següent ordre (tingueu en compte que el punt i coma s'escapa amb una barra inversa quan s'utilitza Bash):
# nft add chain filter input { type filter hook input priority 0 \; }
Les regles s'afegeixen normalment amb la sintaxi següent: nft add rule [família] taula cadena handle handle statement.
insert és similar a la comanda add, però la regla donada és ubicada al començament de la cadena o abans de la regla amb «handle» donat en lloc de fer-ho al final o després d'aquesta regla. Per exemple, la següent ordre insereix una regla abans de la regla amb el «handler» número 8:
# nft insert rule filter output position 8 ip daddr 127.0.0.8 drop
Les ordres nft executades no fan canvis permanents a la configuració, de manera que es perden si no es desen. Les regles del tallafocs es troben a /etc/nftables.conf. Una manera senzilla de desar la configuració actual del tallafocs d'una manera permanent és executar nft list ruleset > /etc/nftables.conf com a superusuari.
nft permet moltes més operacions, vegeu la seva pàgina del manual nft(8) per a més informació.

14.2.4. Instal·lació de les regles a cada arrencada

Per activar per defecte un tallafocs a Debian cal desar les regles a /etc/nftables.conf i executar systemctl enable nftables com a superusuari. Podeu aturar el tallafocs executant nft flush ruleset com a superusuari.
En altres casos, la manera recomanada és registrar l'script de configuració a la directiva up del fitxer /etc/network/interfaces. En el següent exemple, l'script s'emmagatzema sota /usr/local/etc/arrakis.fw.

Exemple 14.1. fitxer interfaces cridant l'script del tallafocs

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
Això suposa òbviament que esteu utilitzant ifupdown per configurar les interfícies de xarxa. Si esteu utilitzant alguna altre cosa (com NetworkManager o systemd-networkd), llavors consulteu la respectiva documentació corresponent per trobar maneres d'executar un script després que s'hagi creat la interfície.