[Zurück: Firewall-Redundanz mit CARP und pfsync] [Inhalt]
[ 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.
int_if="xl0"
tcp_services="{ 22, 113 }"
icmp_types="echoreq"
comp3="192.168.0.3"
Die erste Zeile definiert eine interne Netzwerkschnittstelle, auf der das Filtern stattfinden wird. Da wir sie hier definieren, können wir den Regelsatz bei einer Hardwareumstellung so belassen wie er ist und müssen lediglich diese eine Zeile ändern. (Für dieses Beispiel wird die externe Schnittstelle von der egress Schnittstellengruppe gehandhabt. In dieser finden sich alle Schnittstellen, für die eine Standard-Route gesetzt ist, in diesem Fall fxp0.) Die zweite und dritte 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 der Schnittstelle pppoe0 stattfinden und nicht auf der egress-Schnittstelle (fxp0).
set block-policy return set loginterface egress
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.
Beachte, dass wir alle lo-Schnittstellen ü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.set skip on lo
anchor "ftp-proxy/*"
Nun fügen wir die Regel hinzu, die benötigt wird, um FTP-Verbindungen dergestalt umzuleiten, dass sie vin ftp-proxy(8) gesehen werden:
pass in quick on $int_if inet proto tcp to any port ftp \
divert-to 127.0.0.1 port 8021
Diese Regel fängt jegliche FTP-Verbindung zu Port 21 ab, leitet sie zu der ftp-proxy(8)-Instanz auf Port 8021 um, und vermeidet, durch Nutzung des Schlüsselworts quick, eine Abarbeitung von entsprechenden Paketen durch den Rest des Regelsatzes. Verbinden sich Benutzer regulär auf anderen Ports mit FTP-Servern, so sollte eine Liste mit Zielports spezifiziert werden, zum Beispiel: to any port { 21, 2121 }.
Beachte, dass sich sowohl der Anker, als auch die ftp-proxy(8) Umleitungsregel vor jeglicher match-Regel für NAT befinden müssen, oder andernfalls wird der ftp-proxy(8) nicht wie erwartet funktionieren.
Machen wir weiter mit einigen match-Regeln. Für sich selbst kann eine match-Regel nicht festzustellen, ob es einem Paket erlaubt ist, zu passieren. Stattdessen werden die Parameter der Regel erinnert, denen ein Paket entsprach; diese werden dann für jegliche, die Pakete weiterverarbeitenden pass-Regeln benutzt.
Dies ist leistungsfähig: Parameter wie NAT oder Warteschlangen können auf bestimmte Klassen von Paketen angewendet werden, und so können Zugriffsrechte separat definiert werden.
Um NAT für das gesamtes internes Netzwerk auszuführen, wird die folgende match-Regel genutzt:
match out on egress inet from !(egress:network) to any nat-to (egress:0)
In diesem Fall könnte das »!(egress:network)« einfach durch ein »$int_if:network« ersetzt werden, aber wenn du mehrere interne Schnittstellen hinzufügen würdest, so müsstest du zusätzliche NAT-Regeln hinzufügen, währenddessen mit dieser Struktur NAT auf allen geschützten Schnittstellen ausgeführt wird.
Da die IP-Adressen der externen Schnittstelle dynamisch zugewiesen werden, werden Klammern um die Übersetzungsschnittstelle gesetzt, sodass PF bemerkt, wenn sich eine Adresse ändert. Die Nachsilbe :0 wird benutzt so dass, falls die externe Schnittstelle mehrere Adressen besitzt, nur die erste Adresse für die Übersetzung benutzt wird.
Zuletzt wird die Protokollfamilie inet (IPv4) spezifiziert. Dies verhindert die Übersetzung aller inet6 (IPv6)-Pakete, welche eventuell empfangen werden.
Nun die Regeln zur Kontrolle von Zugriffsrechten. Beginne mit der standardmäßigen Verweigerung.
block in log
An diesem Punkt wird jeglicher Datenverkehr, der versucht, in eine Schnittstelle zu gelangen, blockiert, selbst solcher aus dem internen Netzwerk. Alle diese Pakete werden protokolliert. Spätere Regeln werden die Firewall für obige Objektiven öffnen, und ebenfalls alle notwendigen virtuellen Schnittstellen öffnen.
Denke daran, PF kann sowohl in eine Schnittstelle eingehenden, als auch aus einer Schnittstelle ausgehenden Verkehr blocken. Es kann dein Leben vereinfachen, wenn du dich dafür entscheidest, den Verkehr einer Richtung zu filtern, anstatt zu versuchen die Dinge einfach zu halten, wenn man einige Sachen in der einen, und andere in der anderen Richtung filtert. In unserem Fall entscheiden wir uns dafür, den eingehenden Verkehr zu filtern, aber sobald der Datenverkehr einmal für die Schnittstelle zugelassen ist, werden wir nicht mehr versuchen, sie am Verlassen zu hindern, sodass wir bei folgendem Konstrukt enden:
Durch Nutzung von quick wird die Überprüfung ausgehender Pakete durch folgende Regeln vermieden, was die Leistung erhöht.pass out quick
Die Blockade gefälschter Adressen ist gut:
antispoof quick for { lo $int_if }
Nun öffne die Ports, die von den Netzwerkdiensten genutzt werden, die über das Internet erreichbar sein sollen. Zuerst, der Verkehr, der für die Firewall selbst bestimmt ist:
pass in on egress inet proto tcp from any to (egress) \
port $tcp_services
Die Spezifikation der Netwerk-Ports durch das Makro $tcp_services macht das Öffnen weiterer Dienste für das Internet einfach, da einzig das Makro geändert, und der Regelsatz neu geladen werden muss. UDP-Dienste können ebenfalls, durch die Erzeugung eines Makros $udp_services und dem Hinzufügen einer Filterregel ähnlich der obigen, die jedoch proto udp spezifizieren muss, geöffnet werden.
Die nächste Regel fängt alle Versuche ab, aus dem Internet zu dem TCP-Port 80 der Firewall eine Verbindung aufzubauen. Legitime Versuche, auf diesen Port zuzugreifen, kommen von Benutzern, die auf den Webserver des Netzwerks zugreifen möchten. Diese Verbindungsversuche müssen zu COMP3 umgeleitet werden:
pass in on egress inet proto tcp to (egress) port 80 rdr-to $comp3
ICMP-Datenverkehr muss durchgelassen werden:
pass in inet proto icmp all icmp-type $icmp_types
Ähnlich dem Makro $tcp_services kann ein Makro $icmp_types einfach editiert werden, um die Arten von ICMP-Paketen, denen es erlaubt werden soll, die Firewall zu erreichen, zu ändern. Beachte, dass diese Regel für alle Netzwerkschnittstellen gilt.
Nun muss der Datenverkehr zu und von dem internen Netzwerk durchgelassen werden. Wir nehmen an, dass die Benutzer des internen Netzwerks wissen was sie tun, und keinerlei Ärger verursachen. Dies ist nicht notwendigerweise eine richtige Annahme; ein viel restriktiverer Regelsatz wäre in vielen Umgebungen angemessen.
pass in on $int_if
TCP-, UDP- und ICMP-Datenverkehr ist es durch die frühere Zeile »pass out« erlaubt, die Firewall in Richtung Internet zu verlassen. Zustandsinformationen werden aufbewahrt, sodass zurückkommende Pakete ihren Weg zurück durch die Firewall nehmen können.
# macros
int_if="xl0"
tcp_services="{ 22, 113 }"
icmp_types="echoreq"
comp3="192.168.0.3"
# options
set block-policy return
set loginterface egress
set skip on lo
# FTP Proxy rules
anchor "ftp-proxy/*"
pass in quick on $int_if inet proto tcp to any port ftp \
divert-to 127.0.0.1 port 8021
# match rules
match out on egress inet from !(egress:network) to any nat-to (egress:0)
# filter rules
block in log
pass out quick
antispoof quick for { lo $int_if }
pass in on egress inet proto tcp from any to (egress) \
port $tcp_services
pass in on egress inet proto tcp to (egress) port 80 rdr-to $comp3
pass in inet proto icmp all icmp-type $icmp_types
pass in on $int_if
|
[Zurück: Firewall-Redundanz mit CARP und pfsync] [Inhalt]