[OpenBSD]

[Vorige: Firewall Redundantie met CARP en pfsync] [Inhoud]

PF: Voorbeeld: Firewall voor Thuis of Klein Kantoor


Inhoudsopgave


Het Scenario

In dit voorbeeld draait PF op een OpenBSD machine die fungeert als firewall en NAT gateway voor een klein netwerk in een huis of kantoor. De globale doelstelling is om Internettoegang aan te bieden aan het netwerk en beperkte toegang tot de firewall machine vanaf het Internet, en een interne webserver aan het externe Internet bloot te stellen. Dit document zal een volledige regelset overlopen die precies dat doet.

Het Netwerk

Het netwerk is als volgt opgebouwd: [ COMP1 ] [ COMP3 ] | | ---+------+-----+------- xl0 [ OpenBSD ] fxp0 -------- ( Internet ) | [ COMP2 ]

Er zijn een aantal computers in het interne netwerk; het diagramma toont er drie maar het werkelijke aantal is irrelevant. Deze computers zijn gewone werkstations die gebruikt worden voor web surfen, e-mail, chatten, enz., behalve COMP3 die ook een kleine webserver draait. Het interne netwerk gebruikt het 192.168.0.0 / 255.255.255.0 netwerkblok.

De OpenBSD firewall is een Celeron 300 met twee netwerkkaarten: een 3com 3c509B (xl0) en een Intel EtherExpress Pro/100 (fxp0). De firewall heeft een kabelverbinding naar het Internet en gebruikt NAT om deze verbinding te delen met het interne netwerk. Het IP adres op de externe interface wordt dynamisch toegekend door de Internet Service Provider.

De Doelstelling

De doelstellingen zijn:

Voorbereiding

Dit document veronderstelt dat de OpenBSD host netjes geconfigureerd is om als router te fungeren, inclusief het verifiëren van de IP netwerksetup, Internet-connectiviteit, en het instellen van de sysctl(3) variabelen net.inet.ip.forwarding en/of net.inet6.ip6.forwarding op "1". U moet ook PF ingeschakeld hebben met pfctl(8) of door de overeenkomstige variabele in te stellen in /etc/rc.conf.local.

De Regelset

Het volgende zal doorheen een regelset stappen die de bovenstaande doelstellingen vervult.

Macro's

De volgende macro's worden gedefinieerd om onderhoud en het lezen van de regelset gemakkelijker te maken:
ext_if="fxp0"
int_if="xl0"

tcp_services="{ 22, 113 }"
icmp_types="echoreq"

comp3="192.168.0.3"

De eerste twee lijnen definiëren de netwerkinterfaces waarop filtering zal gebeuren. Door ze hier te definiëren, kunnen we als we dit systeem moeten verplaatsen naar een systeem met andere hardware, alleen die twee lijnen veranderen, en zal de rest van de regelset nog steeds bruikbaar zijn. De derde en vierde lijnen sommen de TCP poortnummers op van de diensten die geopend zullen worden voor het Internet (SSH en ident/auth) en de ICMP pakket-types die zullen doorgelaten worden op de firewall machine. Tenslotte definieert de laatste lijn het IP adres van COMP3.

Opmerking: Als de Internetverbinding PPPoE vereiste, dan zou filtering en NAT moeten plaatsvinden op de tun0 interface en niet op fxp0.

Opties

De volgende twee opties zullen het standaard antwoord instellen voor block filterregels en het loggen van statistieken inschakelen voor de externe interface:
set block-policy return
set loginterface $ext_if

Elk Unix systeem heeft een "loopback" interface. Dit is een virtuele netwerkinterface die door toepassingen gebruikt worden om binnen het systeem met elkaar te communiceren. Op OpenBSD is de loopback interface lo(4). Het wordt als de beste gewoonte beschouwd om al het filteren op loopback interfaces uit te schakelen. Met set skip zullen we dat tot stand brengen.

set skip on lo
Merk op dat we hier de volledige interface-groep lo overslaan, hierdoor hoeven we ons later, mochten we bijkomende loopback interfaces toevoegen, geen zorgen te maken over het wijzigen van dit gedeelte van ons bestaande regelsbestand.

Scrub

Er is geen reden om het aanbevolen schrobben van alle binnenkomende verkeer niet te gebruiken, dus dit is een eenvoudige one-liner:
scrub in

Network Address Translation

Om NAT uit te voeren voor het volledige interne netwerk wordt de volgende nat regel gebruikt:
nat on $ext_if from !($ext_if) to any -> ($ext_if)

De "!($ext_if)" zou in dit geval gemakkelijk kunnen vervangen worden door een "$int_if", maar als u meerdere interne interfaces toevoegt, zou u bijkomende NAT regels moeten toevoegen, terwijl met deze structuur NAT zal geregeld worden op alle beschermde interfaces.

Aangezien het IP adres op de externe interface dynamisch toegekend wordt, worden er haakjes gezet rond de vertalingsinterface zodat PF zal merken wanneer het adres verandert.

Aangezien we een werkende FTP proxy zullen willen, zullen we het NAT anker er ook inzetten:

nat-anchor "ftp-proxy/*"

Omleiding ("redirection")

De eerste omleidingsregels die nodig zijn dienen voor ftp-proxy(8) zodat FTP clients op het lokale netwerk kunnen verbinden naar FTP servers op het Internet.
rdr-anchor "ftp-proxy/*"
rdr on $int_if proto tcp from any to any port 21 -> 127.0.0.1 port 8021

Merk op dat deze regel alleen FTP verbindingen naar poort 21 zal opvangen. Als gebruikers regelmatig verbinden naar FTP servers op andere poorten, dan moet er een lijst gebruikt worden om de bestemmingspoort te specificeren, bijvoorbeeld: from any to any port { 21, 2121 }.

De laatste omleidingsregel vangt pogingen op door iemand op het Internet om te verbinden naar TCP poort 80 op de firewall. Legitieme pogingen om deze poort te benaderen zullen komen van gebruikers die proberen de webserver van het netwerk te bereiken. Deze verbindingspogingen moeten omgeleid worden naar COMP3:

rdr on $ext_if proto tcp from any to any port 80 -> $comp3

Filterregels

Nu de filterregels. Begin met het "standaard weigeren":
block in

Op dit ogenblik zal alle verkeer dat op een interface probeert binnen te komen, geblokkeerd worden, zelfs dat van het interne netwerk. Volgende regels zullen de firewall openen volgens de bovenstaande doelstellingen en ook alle benodigde virtuele interfaces openen.

Hou in het achterhoofd dat pf verkeer kan blokkeren dat binnenkomt of buitengaat op een interface. Het kan uw leven vereenvoudigen als u ervoor kiest om verkeer in één richting te filteren, veeleer dan te proberen het overeind te houden wanneer u bepaalde dingen inwaarts filtert, en andere dingen uitwaarts. In ons geval zullen we verkiezen om inwaarts verkeer te filteren, maar zodra het verkeer toegelaten wordt in een interface, zullen we niet proberen het te blokkeren als het weer naar buiten gaat, dus we zullen het volgende doen:

pass out keep state

We hebben een anker nodig voor ftp-proxy(8):

anchor "ftp-proxy/*"
Het is goed om de spoofed address protection te gebruiken:
antispoof quick for { lo $int_if }

Open nu de poorten gebruikt door die netwerkdiensten die beschikbaar zullen zijn voor het Internet. Eerst het verkeer dat bestemd is voor de firewall zelf:

pass in on $ext_if inet proto tcp from any to ($ext_if) \
   port $tcp_services flags S/SA keep state

Het specificeren van de netwerkpoorten in de macro $tcp_services maakt het eenvoudig om bijkomende diensten te openen voor het Internet door eenvoudigweg de macro te bewerken en de regelset te herladen. UDP diensten kunnen ook geopend worden door een $udp_services macro aan te maken en een filterregel toe te voegen die gelijkaardig is aan de bovenstaande en proto udp specificeert.

Bovenop een rdr regel te hebben die webserver-verkeer doorgeeft naar COMP3, MOETEN we dit verkeer ook doorheen de firewall laten gaan:

pass in on $ext_if inet proto tcp from any to $comp3 port 80 \
    flags S/SA synproxy state

Voor een bijkomend beetje veiligheid, zullen we gebruik maken van de TCP SYN Proxy om de webserver verder te beschermen.

ICMP verkeer moet doorgelaten worden:

pass in inet proto icmp all icmp-type $icmp_types keep state

Gelijkaardig aan de $tcp_services macro, kan de $icmp_types macro gemakkelijk bewerkt worden om de types van ICMP pakketten te veranderen die zullen toegestaan worden de firewall te bereiken. Merk op dat deze regel van toepassing is op alle netwerkinterfaces.

Nu moet verkeer naar en vanuit het interne netwerk doorgelaten worden. We zullen aannemen dat gebruikers op het interne netwerk weten wat ze aan het doen zijn en dat ze geen problemen gaan veroorzaken. Dit is niet noodzakelijk een geldige veronderstelling; een veel meer beperkende regelset zou voor vele omgevingen gepast zijn.

pass in quick on $int_if

TCP, UDP en ICMP verkeer wordt toegestaan om de firewall te verlaten naar het Internet dankzij de "pass out keep state" lijn hierboven. Toestandsinformatie wordt bijgehouden zodat de terugkerende pakketten binnen gelaten zullen worden doorheen de firewall.

De Volledige Regelset

# macro's ext_if="fxp0" int_if="xl0" tcp_services="{ 22, 113 }" icmp_types="echoreq" comp3="192.168.0.3" # opties set block-policy return set loginterface $ext_if set skip on lo # scrub scrub in # nat/rdr nat on $ext_if from !($ext_if) -> ($ext_if:0) nat-anchor "ftp-proxy/*" rdr-anchor "ftp-proxy/*" rdr pass on $int_if proto tcp to port ftp -> 127.0.0.1 port 8021 rdr on $ext_if proto tcp from any to any port 80 -> $comp3 # filterregels block in pass out keep state anchor "ftp-proxy/*" antispoof quick for { lo $int_if } pass in on $ext_if inet proto tcp from any to ($ext_if) \ port $tcp_services flags S/SA keep state pass in on $ext_if inet proto tcp from any to $comp3 port 80 \ flags S/SA synproxy state pass in inet proto icmp all icmp-type $icmp_types keep state pass in quick on $int_if

[Vorige: Firewall Redundantie met CARP en pfsync] [Inhoud]


[terug] www@openbsd.org
$OpenBSD: example1.html,v 1.14 2007/12/30 14:59:18 tobias Exp $