Mijn eerste kennismaking met pfctl op OpenBSD
Reeds jaren werk ik met Linux, zowel op laptops en desktops als servers. Sinds kort ben ik FreeBSD en OpenBSD aan het verkennen. Zo draai ik FreeBSD op een HP Envy-laptop en OpenBSD op een HP Mini-PC.
Omdat ik *BSD wil inzetten als serverbesturingssysteem, wil ik goed begrijpen hoe de onderliggende systemen werken. De firewall speelt daarbij een centrale rol — het is immers essentieel om je systeem afdoende te beveiligen.
Voor dit artikel heb ik OpenBSD bekeken. OpenBSD wordt vaak geprezen om zijn veiligheid. Of het daadwerkelijk zo veilig is, is een vraag die het beste beantwoord kan worden door iemand die zich heeft verdiept in de kwetsbaarheden van het besturingssysteem. Voor meer informatie hierover kun je terecht op de website Is OpenBSD secure. Hoewel OpenBSD veel lof krijgt om zijn beveiliging, is de kans groter dat ik in een productieomgeving uiteindelijk FreeBSD of NetBSD zal gebruiken. De reden dat ik OpenBSD in dit geval probeer, is eigenlijk heel eenvoudig: ik vind de mascotte erg leuk. 😄
Installatie en partitie-indeling
Zonder besturingssysteem gebeurt er weinig. Als eerste heb ik OpenBSD geïnstalleerd als virtuele machine binnen Proxmox.
Tijdens de installatie viel mij het partitioneerprogramma van OpenBSD op. Na wat experimenteren koos ik voor een eenvoudige indeling: een swap-partitie en één grote rootpartitie (/
). Hoewel dit niet de gebruikelijke aanpak is, volstaat het voor mijn doeleinden. Voor productieomgevingen is het echter vaak verstandiger om bepaalde directories op aparte partities te plaatsen, om risico’s te beperken zoals het vollopen van /
door logbestanden of gebruikersdata.
Onderstaand overzicht laat zien waarom het (eigenlijk) verstandiger is om bepaalde locaties op afzonderlijke partities te plaatsen.
Partitie | Functie | Standaardgebruik | Waarom apart zetten? |
---|---|---|---|
/ |
Het rootbestandssysteem, bevat het besturingssysteem en de meeste programma's en configuraties. | Bevat standaard alles als je geen aparte partities gebruikt. | N.v.t.; root is altijd nodig, maar je voorkomt risico’s door bepaalde directories uit te splitsen. |
swap |
Virtueel geheugen bij RAM-tekort. | Bijna altijd aanwezig op systemen. | Geen partitie nodig, maar logisch gescheiden vanwege geheugengebruik. |
/home |
Gebruikt voor persoonlijke bestanden van gebruikers. | Vaak standaard op desktop-systemen. | Voorkomt dat gebruikersbestanden het hele systeem laten vollopen. |
/var |
Bevat variabele bestanden, zoals logs, mail, en spool-gegevens. | Standaard op servers en werkstations. | Logbestanden kunnen snel groeien en zo / vullen — apart zetten voorkomt dit. |
/tmp |
Tijdelijke opslag van applicaties. Wordt vaak leeggemaakt bij reboot. | Vaak aparte partitie of als tmpfs. | Beperkt het risico dat tijdelijke bestanden de root vullen of dat onbetrouwbare data blijft staan. |
Eerste stappen
SSH-toegang en firewall
Op Linux- en Unix-achtige besturingssystemen is SSH vaak standaard beschikbaar, en OpenBSD vormt daarop geen uitzondering. Ook een firewall is standaard aanwezig. OpenBSD maakt gebruik van een actieve firewall, PF (Packet Filter), die beheerd wordt met het commando pfctl. Verderop in dit artikel ga ik dieper in op PF.
Werken met doas
Het is gebruikelijk om niet voortdurend met beheerrechten te werken. Eén van mijn eerste acties was het instellen van doas, het OpenBSD-alternatief voor sudo onder Linux:
echo "permit persist main as root" >> /etc/doas.conf
Hiermee krijgt de gebruiker main
de mogelijkheid om systeembeheertaken uit te voeren door tijdelijk verhoogde rechten te verkrijgen. Het sleutelwoord ‘persist’ houdt in dat het wachtwoord slechts één keer per sessie hoeft te worden ingevoerd. Een root-shell start je eenvoudig met doas -s
, wat vergelijkbaar is met sudo su
onder Linux.
Ik kies vaak voor de gebruikersnaam main
, omdat ik een apart account nodig heb voor onderhoudstaken. In dit geval staat main voor ‘maintenance user’, maar het is tegelijkertijd een woordgrap: ‘main’ betekent ook ‘hoofd’, zoals in ‘hoofdgebruiker’. En ja, ook onder OpenBSD moet je goed je hoofd gebruiken. 😉
Poorten controleren
Ik was benieuwd welke poorten standaard openstaan. Zo verwachtte ik bijvoorbeeld TCP-poort 22 voor SSH.
Waar ik onder Linux vaak netstat -antu
of netstat -tulpn
(of beter: ss -tulpn
) gebruik, werkt dat op OpenBSD niet. Alternatieven zijn:
netstat -an | grep LISTEN
fstat | grep internet
Firewallregels bekijken
Zoals eerder genoemd, wordt OpenBSD standaard geleverd met een actieve firewall — een goed begin! Met het commando pfctl -sr
bekijk je de actieve firewallregels:
pfctl -sr
De uitvoer verbaasde mij:
block return all
pass all flags S/SA
block return in on ! lo0 proto tcp from any to any port 6000:6010
block return out log proto tcp all user = 55
block return out log proto udp all user = 55
SSH is blijkbaar bereikbaar op basis van de bovenstaande regels, hoewel TCP-poort 22 niet expliciet openstaat. Wat blijkt: SSH is bereikbaar door de regel pass all flags S/SA
, waarmee verbindingen die de juiste TCP-vlaggen gebruiken, worden toegestaan. Deze regel is krachtig en laat alleen verbindingen toe die voldoen aan een geldige connectie-opbouw, wat veiliger is dan simpelweg pass in
toestaan.
Hier verwijst S/SA
naar de TCP-vlaggen SYN (S) en SYN+ACK (SA), die respectievelijk het begin en de bevestiging vormen van een geldige TCP-handshake.
Daarnaast valt op dat de poorten 6000 tot en met 6010 worden geblokkeerd. Dit voorkomt verbindingen met X11, het grafische systeem dat vaak wordt gebruikt om een grafische gebruikersinterface over een netwerk op te zetten. Deze keuze is logisch, aangezien X11 kwetsbaar is door het ontbreken van versleuteling.
De regels blokkeren verder uitgaand TCP- en UDP-verkeer van gebruiker 55, maar wie of wat is gebruiker 55?
Het commando:
grep ':55:' /etc/passwd
leverde het volgende op:
_pbuild:*:55:55:dpb build user:/nonexistent:/sbin/nologin
Deze gebruiker wordt gebruikt voor het bouwen van ports. Door zijn netwerktoegang te beperken, voorkom je dat er tijdens het bouwen van software verbindingen gelegd worden met onbetrouwbare servers.
Wat is pfctl?
Zoals genoemd is pfctl
het beheercommando voor de PF-firewall. Hier een handig overzicht van veelgebruikte opties:
Commando | Betekenis |
---|---|
pfctl -sr |
Toon de actieve firewallregels |
pfctl -si |
Toon firewallstatistieken |
pfctl -sa |
Toon alle instellingen en tabellen |
pfctl -nf /etc/pf.conf |
Check de syntax van je pf.conf |
pfctl -f /etc/pf.conf |
Herlaad de configuratie |
pfctl -e |
Schakel PF in (enable) |
pfctl -d |
Schakel PF uit (disable) |
Zie ook de pfctl cheat sheet voor meer informatie.
Ik ben niet geheel onbekend met Packet Filter (PF). Ik werk regelmatig met firewalls zoals pfSense, OPNsense en DynFi, die gebruik maken van PF voor hun netwerkbeveiliging. Het grote verschil is dat PF in zowel pfSense als OPNsense en DynFi via een webinterface wordt beheerd, wat het voor gebruikers zonder diepgaande commandoregelkennis makkelijker maakt om firewallregels in te stellen. Werken met PF op command-line niveau daarentegen is technisch gezien een stuk complexer (uitdagender), maar biedt meer controle en flexibiliteit. Het is ook een stuk leerzamer, omdat het je dwingt om de onderliggende werking van de firewallregels en netwerkbeveiliging beter te begrijpen. Hoewel de grafische interfaces van pfSense en OPNsense gebruikers een toegankelijke manier bieden om firewalls te beheren, geeft werken met de commandoregel je de mogelijkheid om diepgaandere configuraties te maken en precies te begrijpen wat er achter de schermen gebeurt.
Conclusie
Mijn eerste ervaring met PF en pfctl
op OpenBSD was verhelderend. OpenBSD hanteert een "default-deny"-aanpak: blokkeer alles, en sta alleen het noodzakelijke toe. Dit zet je aan tot bewuste keuzes in systeembeveiliging.
Waar je in Linux vaak met een open configuratie begint, draait OpenBSD het om: alles is dicht, tenzij expliciet toegestaan. Het resultaat is een minimalistische maar krachtige benadering van netwerkbeveiliging.
Vergelijking tussen pf en iptables (nftables)
Regel (OpenBSD PF) | Wat gebeurt er? | Veiligheidsniveau | Equivalent in Linux (iptables) |
---|---|---|---|
pass all flags S/SA |
Staat alleen verbindingen met SYN/ACK flags toe, wat een geldige TCP-handshake betekent. | Hoger: Alleen legitieme verbindingen worden toegestaan. | -A INPUT -p tcp --syn -m state --state NEW -j ACCEPT |
pass in |
Staat alle inkomende verbindingen toe zonder enige controle. | Laag: Alle verkeer wordt geaccepteerd, inclusief ongewenste verbindingen. | -A INPUT -j ACCEPT |
block return all |
Blokkeert alle verbindingen, met uitzondering van de expliciet toegestane regels. | Zeer hoog: De standaard is blokkeren, wat betekent dat alleen benodigde verbindingen worden toegestaan. | -A INPUT -j DROP |
Hoewel iptables (tegenwoordig nftables) meer uitgebreide functionaliteit en modules biedt, dwingt PF met zijn eenvoudige en duidelijke syntaxis tot doordachte keuzes. Het is daarmee een krachtig hulpmiddel voor wie streeft naar een minimalistische, maar effectieve beveiliging.