Een firewall met ufw en nftables
Module 5: Het netwerk afschermen · Leestijd: 12 minuten
Leerdoel: Na deze les kun je een firewall instellen die alleen toelaat wat nodig is, voor IPv4 én IPv6, zonder jezelf buiten te sluiten, en weet je waar een firewall op je server niet tegen beschermt.
Kernbegrippen: pakketfilter, netfilter, nftables, iptables-nft, ufw, standaardbeleid, allow, deny, reject, limit, IPv6 in ufw, firewall van de aanbieder, firewalld, Docker en de firewall
Wat een firewall doet
Een firewall op je server is een pakketfilter: voor elk binnenkomend netwerkpakketje kijkt hij naar een lijst regels en beslist of het door mag. In Linux zit dat filter in de kernel en heet het netfilter. Je stelt het in met een programma:
- nftables (commando
nft) is het huidige gereedschap. Debian gebruikt het standaard sinds Debian 10. - iptables is het oude gereedschap. Op moderne systemen is
iptablesmeestal een vertaling naar nftables (iptables-nft), zodat oude handleidingen nog werken. - ufw (Uncomplicated Firewall) is een eenvoudige laag erbovenop, standaard aanwezig op Ubuntu en met één commando te installeren op Debian. Voor een enkele server is ufw de makkelijkste keus. Deze les gebruikt ufw en laat daarna zien hoe dezelfde regels er in nftables uitzien.
Een firewall is je tweede verdedigingslaag. De eerste is dat diensten alleen op het juiste adres luisteren (les 5.1). Samen zorgen ze dat een vergissing in de ene laag niet meteen een open deur is.
Eerst: hoe kom je terug als het misgaat?
De klassieke fout: je zet de firewall aan, vergeet SSH toe te laten, en je verbinding valt weg. Je kunt er dan niet meer bij via SSH. Voordat je begint:
- Weet hoe je de console van je aanbieder opent (les 1.2). Die werkt buiten het netwerk om, dus ook als de firewall alles dichtzet. Daar log je in en typ je
ufw disable. - Maak een snapshot als je twijfelt.
- Houd je huidige SSH-sessie open en test met een tweede sessie.
ufw in vijf stappen
Stap 1: installeren en de standaard kiezen.
anna@web1:~$ sudo apt install ufw
anna@web1:~$ sudo ufw default deny incoming
Default incoming policy changed to 'deny'
anna@web1:~$ sudo ufw default allow outgoing
Default outgoing policy changed to 'allow'Het standaardbeleid geldt voor alles waar geen regel voor is. "Deny incoming" betekent: alles wat binnenkomt is verboden, behalve wat je hierna toestaat. Dat is de enige veilige basis. Uitgaand verkeer (je server die updates ophaalt) laat je toe.
Stap 2: SSH toelaten, vóór je de firewall aanzet.
anna@web1:~$ sudo ufw allow OpenSSH
Rules updated
Rules updated (v6)OpenSSH is een applicatieprofiel dat ufw kent (het staat voor poort 22/tcp). Draait SSH op een andere poort, gebruik dan het nummer: sudo ufw allow 2222/tcp. Let op "Rules updated (v6)": ufw maakt de regel ook voor IPv6. Dat doet hij omdat in /etc/default/ufw de regel IPV6=yes staat, wat de standaard is. Controleer dat even; staat hij op no, dan geldt je firewall alleen voor IPv4.
Stap 3: wat je verder nodig hebt.
anna@web1:~$ sudo ufw allow 80/tcp
anna@web1:~$ sudo ufw allow 443/tcp
anna@web1:~$ sudo ufw allow 443/udp # alleen als je HTTP/3 gebruiktJe kunt een regel beperken tot één bronadres, bijvoorbeeld een beheerpoort die alleen vanaf je kantoor mag:
anna@web1:~$ sudo ufw allow from 198.51.100.20 to any port 9090 proto tcpStap 4: aanzetten.
anna@web1:~$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startupStap 5: controleren. Open een tweede venster en log opnieuw in. Lukt dat, dan staat SSH goed. Bekijk daarna de regels:
anna@web1:~$ sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), deny (routed)
New profiles: skip
To Action From
-- ------ ----
22/tcp (OpenSSH) ALLOW IN Anywhere
80/tcp ALLOW IN Anywhere
443/tcp ALLOW IN Anywhere
22/tcp (OpenSSH (v6)) ALLOW IN Anywhere (v6)
80/tcp (v6) ALLOW IN Anywhere (v6)
443/tcp (v6) ALLOW IN Anywhere (v6)Een regel weghalen gaat met nummers: sudo ufw status numbered en dan sudo ufw delete 3.
deny, reject en limit
- deny laat het pakketje stil vallen: van buiten zie je "gefilterd" (les 5.1).
- reject stuurt een weigering terug: van buiten zie je "dicht". Netter voor je eigen diensten, maar het verraadt dat er een server is.
- limit laat een verbinding toe, maar blokkeert een adres dat binnen 30 seconden zes keer of vaker verbinding probeert te maken. Handig voor SSH:
sudo ufw limit OpenSSHin plaats vanallow. Het is grof (het telt verbindingen, niet mislukte logins); fail2ban (les 5.3) is preciezer.
Dezelfde regels in nftables
ufw schrijft onder de motorkap netfilter-regels. Wil je zonder ufw werken, dan schrijf je zelf een nftables-bestand. Op Debian staat het in /etc/nftables.conf en laad je het met de dienst nftables:
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
ct state established,related accept
ct state invalid drop
iif "lo" accept
meta l4proto { icmp, ipv6-icmp } accept
tcp dport { 22, 80, 443 } accept
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
}Lees het zo. De tabel heet filter en is van de familie inet: één tabel voor IPv4 én IPv6 tegelijk, zodat je IPv6 niet kunt vergeten. In de keten input is het beleid drop. Daarna: antwoorden op verbindingen die al bestaan mogen terug (established,related), alles op loopback mag, ICMP mag (nodig voor onder meer IPv6 en foutmeldingen over pakketgrootte), en de poorten 22, 80 en 443 mogen.
anna@web1:~$ sudo nft -c -f /etc/nftables.conf # controleren zonder te laden
anna@web1:~$ sudo systemctl enable --now nftables
anna@web1:~$ sudo nft list rulesetGebruik óf ufw óf een eigen nftables-bestand, niet allebei: ze schrijven in hetzelfde netfilter en kunnen elkaars regels in de weg zitten.
Waar je firewall niet tegen beschermt
- Diensten die je zelf toelaat. Poort 443 staat open voor je website; een lek in je website is dus gewoon bereikbaar. De firewall beschermt alleen de poorten die dicht zijn.
- Docker. Als je met Docker een poort publiceert (
-p 5432:5432), zet Docker zijn eigen netfilter-regels, die het verkeer omleiden voordat de regels van ufw gelden. De Docker-documentatie zegt letterlijk dat Docker en ufw niet goed samengaan. Een container-poort kan dus van buiten open staan terwijlufw statushem niet toont. De oplossing (publiceren op127.0.0.1) leer je in les 9.3. - Uitgaand verkeer. Met "allow outgoing" kan een gehackt programma overal naartoe. Voor de meeste kleine servers is dat een aanvaardbare keuze; strenge omgevingen beperken ook uitgaand verkeer.
De firewall van je aanbieder
Veel aanbieders hebben ook een firewall in het netwerk, vóór je server, die je in het klantpaneel instelt (soms "cloud firewall" of "security group" genoemd). Die is een prima extra laag, en hij werkt ook als je op de server zelf iets verkeerd doet. Maar hij vervangt de firewall op de server niet: verhuis je de server of verander je van aanbieder, dan gaat hij niet mee, en niet elke aanbieder biedt hem aan. Houd daarom altijd een firewall op de server zelf.
Op AlmaLinux en Rocky Linux
Daar staat firewalld standaard aan, met zones. De belangrijkste commando's:
[root@web1 ~]# firewall-cmd --list-all
[root@web1 ~]# firewall-cmd --permanent --add-service=http --add-service=https
[root@web1 ~]# firewall-cmd --reloadZonder --permanent geldt een wijziging alleen tot de volgende herstart; met --permanent pas na --reload. SSH staat in de standaardzone al open.
In de praktijk
Sluit je jezelf toch buiten op een VPS bij WebOké, dan open je in het VPS-scherm de console, log je in en zet je de firewall uit (ufw disable) of draai je de laatste regel terug. Bij andere aanbieders heet die noodingang ook console, VNC of rescue. Weet waar die knop zit voordat je hem nodig hebt.
Samenvatting
- Een firewall is je tweede laag na "luister alleen waar nodig"; nftables is het gereedschap in de kernel, ufw een eenvoudige laag erbovenop.
- Begin met
default deny incoming, sta SSH toe vóórufw enable, test met een tweede sessie, en ken de console van je aanbieder. - Controleer dat ufw ook IPv6 afdekt (
IPV6=yes); in nftables doet de familieinetdat in één keer. denygeeft van buiten "gefilterd",rejectgeeft "dicht";limitremt herhaalde verbindingen.- Docker-poorten gaan langs ufw heen (les 9.3); de firewall van je aanbieder is een extra laag, geen vervanging.
Quiz
Opdracht
Opdracht O5.2: Je firewall inrichten. Zet op je server een firewall aan met ufw (of nftables, of firewalld op AlmaLinux/Rocky): standaard alles dicht binnenkomend, SSH, en wat je verder echt nodig hebt. Test met een tweede sessie, controleer of IPv6 is afgedekt, en kijk van buitenaf met nc of een niet-toegestane poort dicht of gefilterd is. Vul de checklist in en plak je ufw status verbose (of nft list ruleset); geef bij elke open poort aan waarvoor hij is.
Opdracht O5.2: Je firewall inrichten
Deze opdracht doe je zelf; niemand kijkt hem na. Vink af wat je gedaan hebt en markeer de opdracht als gedaan.
Voor een webserver alleen 22 (of je SSH-poort), 80 en 443, voor IPv4 en IPv6. Beheerpoorten alleen vanaf een vast adres of via een SSH-tunnel. Via de console: ufw disable (of de nftables-regels leegmaken).
Je vinkjes en aantekeningen blijven alleen in deze browser; we sturen ze nergens heen. Ben je aangemeld, dan bewaren we in Mijn cursussen alleen dat je de opdracht gedaan hebt.
Verder lezen
- Je VPS beveiligen: de eerste vijf minuten
- Geen toegang meer tot je VPS: wat nu?
- Debian Wiki, nftables: https://wiki.debian.org/nftables
- Ubuntu Server-documentatie, Firewall (ufw): https://ubuntu.com/server/docs/how-to/security/firewalls/
- Docker-documentatie, Packet filtering and firewalls: https://docs.docker.com/engine/network/packet-filtering-firewalls/
