Firewalls met OpenBSD

Geert Vernaeve
Philippe Serbruyns

Installatie van OpenBSD 2.8

We FTP'en de installatiefloppy floppy28.fs (kies een mirror op http://openbsd.rug.ac.be/ftp.html, en ga naar de 2.9/i386 directory) en schrijven het bestand op een floppy. Met deze floppy booten we onze toekomstige firewall. De OpenBSD install stelt een aantal eenvoudige vragen; van de drie netwerkkaarten die onze machine bevat configureren we er voorlopig maar één, omdat we de machine tijdens het installeren als een gewone computer aan het netwerk zullen hangen. De rest van de installatie kan dan gewoon over het netwerk gaan; we installeren enkel de vier gesuggereerde pakketten (base28, etc28, man28 en bsd).

Onze drie netwerkkaarten zijn tijdens de installatie herkend als

Voorlopig configureren we dus enkel de ne1 kaart zodat we kunnen installeren van over het netwerk.

Configuratie van de bridge

We hebben bridging nodig omdat we niet willen dat de rest van het netwerk iets van de aanwezigheid van de firewall merkt. Zonder bridging zouden alle computers van ons lokaal netwerk hun default gateway moeten veranderen in het IP-adres van onze firewall.

/etc/rc.conf veranderingen

sendmail_flags=NO  # (was "-q30m"); we willen zo weinig mogelijk services
                   # en zeker en vast geen mail
ipfilter=YES       # anders werkt de bridge niet
portmap=NO         # niet nodig
inetd=NO           # we draaien geen services op de firewall
Onder OpenBSD 3.4 moeten we pf=YES in plaats van ipfilter=YES schrijven. (Zie de OpenBSD Packet Filter FAQ)

/etc/hostname.ne1, /etc/hostname.wb0, /etc/hostname.wb1

Bevat enkel een lijn met
up
Merk op dat we dus geen enkele netwerkkaart een IP-adres toewijzen. De firewall is dus onzichtbaar voor de rest van het netwerk (vandaar de term transparante firewall). Deze aanpak zorgt ook voor extra veiligheid: zelfs als we per ongeluk een service aan laten staan, kan er toch niemand aan prutsen omdat de machine helemaal geen IP adres heeft. Klein nadeel is dat we ook niet vanop afstand kunnen inloggen op de firewall om iets aan de configuratie te veranderen.

Met ifconfig ne1 157.193.53.38 netmask 255.255.255.0 broadcast 157.193.53.255 (of door een inet 157.193.53.38 255.255.255.0 NONE regel in /etc/hostname.ne1 bij te schrijven) kunnen we de machine indien gewenst wel een IP adres geven. Deze aanpak blijft nog altijd relatief veilig omdat de machine geen gateway heeft en dus voor de buitenwereld niet bereikbaar is.

/etc/bridgename.bridge0

add ne1 add wb0 add wb1 up

/etc/ipf.rules (OpenBSD 2.8)

Standaard staat er
pass in from any to any
pass out from any to any
met andere woorden, laat alle pakketten door. Om te testen of de bridge werkt, zullen we dit voorlopig zo laten staan.

Daarna rebooten we om te testen of alles werkt. Er blijkt natuurlijk niks te werken: ik ben blijkbaar vergeten ipfilter op YES te zetten in /etc/rc.conf. Na een volgende reboot blijkt dat ik ook nog de up in /etc/bridgename.bridge0 ben vergeten. Een snelle test (brconfig bridge0 up) leert ons dat het nu wel zou moeten werken!

We testen de bridge door ne1 aan ons intern netwerk te hangen en wb0 aan een laptop. Vanop de laptop pingen we een server uit ons intern netwerk. Daarna verbinden we de laptop met wb1 en het blijkt dat we de server uit het interne netwerk niet meer kunnen pingen. We moeten daarvoor met brconfig bridge0 flush de bridge dwingen te vergeten dat de laptop aan wb0 hing.

/etc/pf.conf (OpenBSD 3.4)

Configuratie van de firewall

Het komt erop aan in /etc/ipf.rules de juiste regels bij te schrijven. Standaard laat de machine alles door. Om te testen voegen we een regel toe
block in from any to any port = 1000
Met ipf -A -Fa -f /etc/ipf.rules -E maken we de veranderingen actief. (We krijgen wel enkele waarschuwingsboodschappen, maar die zullen blijken niet veel kwaad te kunnen.) De regel zegt dat de firewall geen pakketten doorlaat die voor poort 1000 bestemd zijn. We kunnen testen of dat inderdaad zo is door op de laptop die achter de firewall hangt
telnet cage 1000
te typen. Het commando blijft hangen, daar waar we vroeger de melding telnet: Unable to connect to remote host: Verbinding geweigerd kregen, een bewijs dat de firewall effectief werkt.

Doorvoorsnelheid

Met scp kopiëren we eens een 7MB groot bestand van onze server naar de laptop. We halen in beide gevallen 775kB/s (het theoretische maximum is ongeveer 1000kB/s), wat ons een goed resultaat lijkt.
Met OpenBSD 2.9 (in plaats van 2.8) en met een geswitched UTP-netwerk (in plaats van een single-collision-domain coax netwerk) halen we zelfs 1000kB/s.

IP Masquerading (***werkt niet!***)

Van een aantal computers uit ons intern netwerk willen we niet dat ze van buitenaf te zien zijn. We willen dan ook die computers masqueraden: wanneer ze een verbinding naar de buitenwereld opzetten, moet het van buitenaf lijken dat de verbinding van de firewall-machine komt.

Daarvoor moeten we (volgens de man page van ipf) in /etc/sysctl.conf een regel met net.inet.ip.forwarding=1 invoegen.

[nog te onderzoeken]

We proberen in /etc/ipnat.rules de lijn

map ne1 157.193.53.77/32 -> ne1/32 portmap tcp/udp 1025:65000
map ne1 157.193.53.77/32 -> ne1/32
(gespiekt van Setting up OpenBSD 2.7 as a cable NAT system en de man pages) waarbij 157.193.53.77 het IP adres van de laptop is die we met de wb1 netwerkkaart verbinden. Let wel: ne1 is de netwerkkaart waar de gemasquerade pakketten (die dus IP adres 157.193.53.38 zullen krijgen, het IP adres van de ne1 interface) heen moeten, niet van waar de pakketten afkomstig zijn (die IP adres 157.193.53.77 hadden)!
Het bestand /etc/rc.conf passen we als volgt aan:
ipnat=YES
en we rebooten.
Latere wijzigingen aan /etc/ipnat.rules kunnen met
ipnat -C -F -f /etc/ipnat.rules
actief worden gemaakt (en als bonus worden de regels ook op syntax gecontroleerd). Met ipnat -l kunnen we de huidige regels opvragen (en zien hoe kernel van onze regels eigenlijk heeft begrepen).

[PENDING: het masqueradet langs geen kanten; nu blijkt toch wel in de documentatie te staan dat masquerading via bridge niet ondersteund wordt zeker]

Verwijzingen

OpenBSD bridge without IPs using IPF