[OpenBSD]

[Zurück: Firewal-Redundanz mit CARP und pfsync] [Inhalt]

PF: Beispiel: Firewall für zuhause oder ein kleines Büro


Inhaltsverzeichnis


Das Szenario

In diesem Beispiel läuft PF auf einer OpenBSD-Maschine, deren Aufgabe es ist, als Firewall und NAT-Gateway für ein kleines Netzwerk zuhause oder in einem Büro zu agieren. Das Gesamtziel ist, dem Netzwerk Internetzugriff und begrenzten Zugriff zur Firewallmaschine vom Internet aus zu gewähren. Des Weiteren soll ein interner Webserver vom Internet aus erreichbar gemacht werden. Dieses Dokument wird einen kompletten Regelsatz durchgehen, der genau das macht.

Das Netzwerk

Das Netzwerk ist wie folgt aufgebaut: [ COMP1 ] [ COMP3 ] | | ---+------+-----+------- xl0 [ OpenBSD ] fxp0 -------- ( Internet ) | [ COMP2 ]

In diesem internen Netzwerk befinden sich einige Computer. Das Diagramm zeigt drei, aber die tatsächliche Anzahl ist unbedeutend. Diese Computer sind reguläre Arbeitsplätze, die fürs Websurfen, E-Mail, Chatten etc. verwendet werden. COMP3 ist eine Ausnahme, da er als kleiner Webserver läuft. Das interne Netzwerk verwendet den Netzwerkblock 192.168.0.0/255.255.255.0.

Die OpenBSD-Firewall ist ein Celeron 300 mit zwei Netzwerkkarten: eine 3com 3c509B (xl0) und eine Intel EtherExpress Pro/100 (fxp0). Die Firewall hat eine Kabelverbindung zum Internet und verwendet NAT, um diese Verbindung mit dem internen Netzwerk zu teilen. Die IP-Adresse des externen Interfaces wird vom Internetprovider dynamisch zugewiesen.

Das Ziel

Die Ziele sind:

Vorbereitung

Dieses Dokument nimmt an, dass der OpenBSD-Host ordentlich konfiguriert wurde, sodass er als Router funktioniert - einschließlich der Überprüfung der IP-Netzwerkeinstellungen, Internetverbindung und dass die sysctl(3)-Variablen net.inet.ip.forwarding und/oder net.inet6.ip6.forwarding auf »1« eingestellt wurde. Du musst ebenfalls PF mittels pfctl(8) starten oder die entsprechende Variable in /etc/rc.conf.local aktivieren.

Der Regelsatz

Das nächste Kapitel wird Schritt für Schritt durch einen Regelsatz gehen, der die zuvor genannten Ziele realisiert.

Makros

Die folgenden Makros wurden definiert, um die Wartung und das Lesen des Regelsatzes einfacher zu machen:
ext_if="fxp0"
int_if="xl0"

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

comp3="192.168.0.3"

Die ersten beiden Zeilen definieren die Netzwerkinterfaces, auf denen gefiltert wird. Da wir sie hier definieren, können wir den Regelsatz bei einer Hardwareumstellung so belassen wie er ist und müssen lediglich diese zwei Zeilen abändern. Die dritte und vierte Zeile listen die TCP-Portnummern der Dienste auf, die dem Internet gegenüber offengelegt werden (SSH und ident/auth) und den ICMP-Pakettyp, dem erlaubt wird, die Firewallmaschine zu erreichen. Zum Schluss definiert die letzte Zeile die IP-Adresse von COMP3.

Hinweis: Wenn die Internetverbindung PPPoE benötigt, werden Filter und NAT auf dem tun0-Interface stattfinden und nicht auf fxp0.

Optionen

Die folgenden beiden Optionen werden die standardmäßige Antwort für block-Filterregeln setzen und Statistikaufzeichnungen für das externe Interface anstellen:
set block-policy return
set loginterface $ext_if

Jedes Unix-System hat ein sogenanntes Loopbackinterface. Hierbei handelt es sich um ein virtuelles Netzwerkinterface, das von Applikationen genutzt wird, um mit anderen auf dem gleichen System zu kommunizieren. Unter OpenBSD ist das Loopbackinterface lo(4). Es ist allgemein gute Praxis, jegliches Filtern auf den Loopbackinterfaces zu unterbinden. Die Verwendung von set skip bewerkstelligt dies.

set skip on lo
Beachte, dass wir die gesamte Interfacegruppe lo überspringen. Auf diese Weise können wir später noch Loopbackinterfaces hinzufügen, ohne dass wir uns Gedanken darüber machen müssten, diesen Teil unseres Regelsatzes anzupassen.

Scrub

Es gibt keinen Grund, das empfohlene Scrubbing, das auf den gesamten eingehenden Verkehr angewandt wird, nicht zu verwenden. Somit handelt es sich hierbei um einen einfachen Einzeiler:
scrub in

Network Address Translation

Um NAT auf das gesamte interne Netzwerk durchzuführen, wird folgende nat-Regel verwendet:
nat on $ext_if from !($ext_if) to any -> ($ext_if)

»!($ext_if)« könnte in diesem Fall ganz einfach gegen »$int_if« ausgetauscht werden, doch wenn du weitere interne Interfaces hinzufügst, müsstest du ebenfalls zusätzliche NAT-Regeln einfügen, wobei mit dieser Struktur NAT sofort auf allen geschützten Interfaces funktioniert.

Da die IP-Adresse des externen Interfaces dynamisch zugewiesen wird, werden Klammern um das Übersetzungsinterface herum gesetzt. Auf diese Weise wird PF bemerken, wenn sich die Adresse ändert.

Wir wollen ebenfalls, dass der FTP-Proxy funktioniert. Das erreichen wir dadurch, indem wir ebenfalls den NAT-Anker> einbinden:

nat-anchor "ftp-proxy/*"

Umleitung

Die ersten benötigten Umleitungsregeln sind für ftp-proxy(8), sodass sich FTP-Clients vom lokalen Netzwerk aus mit FTP-Servern im Internet verbinden können.
rdr-anchor "ftp-proxy/*"
rdr on $int_if proto tcp from any to any port 21 -> 127.0.0.1 port 8021

Bedenke, dass diese Regel nur FTP-Verbindungen auf Port 21 erfassen wird. Wenn sich Benutzer auf regulärer Basis mit FTP-Servern auf anderen Ports verbinden, sollte eine Liste verwendet werden, die die Zielports angibt - zum Beispiel: from any to any port { 21, 2121 }.

Die letzte Umleitungsregel erfasst alle Versuche von Personen im Internet, die auf den TCP-Port 80 der Firewall verbinden wollen. Berechtigte Versuche, diesen Port zu erreichen, werden von Benutzern sein, die versuchen, den Webserver vom Netzwerk zu erreichen. Dieser Verbindungsversuch muss auf COMP3 weitergeleitet werden:

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

Filter-Regeln

Nun die Filterregeln. Fange mit standardmäßigem Blocken an:
block in

Zu diesem Zeitpunkt wird der gesamte Verkehr, der in ein Interface gelangen will, abgeblockt - sogar vom internen Netzwerk. Die nächsten Regeln werden die Firewall den oben genannten Zielen entsprechend öffnen, so wie alle benötigten virtuellen Interfaces.

Bedenke, dass PF sowohl den eingehenden als auch den ausgehenden Netzwerkverkehr eines Interfaces blocken kann. Du kannst dir die Konfiguration vereinfachen, indem du den Verkehr nur in eine Richtung filterst, statt sowohl eingehenden als auch ausgehenden. In unserem Fall haben wir uns entschieden, den eingehenden Verkehr zu filtern. Doch sobald der Netzwerkverkehr in ein Interface hineingelassen wurde, werden wir nicht versuchen, ihn am Verlassen zu hintern. Das ganze sieht dann wie folgt aus:

pass out keep state

Des Weiteren benötigen wir einen Anker für ftp-proxy(8):

anchor "ftp-proxy/*"
Sinnvoll ist auch der Einsatz eines Schutzes gegen gefälschte Adressen:
antispoof quick for { lo $int_if }

Nun öffne die Ports, die von den Netzwerkdiensten genutzt werden, die für das Internet verfügbar sein sollen. Zuerst der Verkehr, der für die Firewall selbst bestimmt ist:

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

Die Netzwerkports in dem Makro $tcp_services anzugeben macht es simpel, zusätzliche Dienste dem Internet anzubieten. Neue Ports müssen nur in das Makro eingetragen und der Regelsatz neugeladen werden. UDP-Dienste können ebenfalls geöffnet werden, indem ein $udp_services-Makro erstellt wird und eine Filterregel so wie oben angegeben hinzugefügt wird (mit proto udp).

Zusätzlich zur rdr-Regel, die den Webserververkehr zu COMP3 weiterleitet, MÜSSEN wir ebenfalls diesen Verkehr durch die Firewall leiten:

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

Für ein bisschen mehr Sicherheit werden wir den TCP-SYN-Proxy verwenden, um den Webserver noch besser zu beschützen.

ICMP-Verkehr muss durchgelassen werden:

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

Dem $tcp_services-Makro ähnelnd kann das $icmp_types-Makro einfach editiert werden, um die Typen der ICMP-Pakete zu ändern, denen erlaubt wird, die Firewall zu erreichen. Bedenke, dass diese Regel für alle Netzwerkinterfaces gilt.

Nun muss der Verkehr zu und vom internen Netzwerk zugelassen werden. Wir nehmen an, dass die Benutzer im internen Netzwerk wissen, was sie tun und keinen Ärger verursachen werden. Dies ist nicht notwendigerweise eine gültige Annahme; ein sehr viel restriktiverer Regelsatz wäre für viele Umgebungen angebrachter.

pass in quick on $int_if

TCP-, UDP- und ICMP-Verkehr darf die Firewall in Richtung Internet verlassen. Das ist auf Grund der vorher genannten Zeile »pass out keep state« notwendig. Zustandsinformationen werden aufbewahrt, sodass die wiederkommenden Pakete durch die Firewall gelassen werden.

Der komplette Regelsatz

# makros ext_if="fxp0" int_if="xl0" tcp_services="{ 22, 113 }" icmp_types="echoreq" comp3="192.168.0.3" # optionen 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 # filterregeln 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

[Zurück: Firewal-Redundanz mit CARP und pfsync] [Inhalt]


[zurück] www@openbsd.org
$OpenBSD: example1.html,v 1.22 2008/01/06 13:57:19 tobias Exp $