[Zurück: Tabellen] [Inhalt] [Weiter: Network Address Translation]
Filterregeln geben sowohl die Kriterien an, auf die ein Paket zutreffen muss, als auch die resultierende Handlung (blocken oder durchlassen), die durchgeführt wird, wenn eine Übereintreffung gefunden wird. Filterregeln werden in sequenzieller Reihenfolge verarbeitet: von der ersten bis zur letzten. Solange das Paket nicht auf eine Regel trifft, die das quick-Schlüsselwort beinhaltet, werden alle Filterregeln überprüft, bevor die schlussendliche Aktion durchgeführt wird. Die letzte Regel, die zutrifft, ist der Gewinner und wird die Aktion angeben, die auf das Paket angewandt wird. Es gibt ein impliziertes pass all am Anfang des Filterregelsatzes, das bedeutet, dass falls ein Paket auf keine Filterregel zutrifft, die resultierende Aktion pass sein wird.
action [direction] [log] [quick] [on interface] [af] [proto protocol] \
[from src_addr [port src_port]] [to dst_addr [port dst_port]] \
[flags tcp_flags] [state]
Um eine »standardmäßig block«-Richtlinie zu erstellen, sollten die ersten beiden Filterregeln wie folgt sein:
block in all
block out all
Dies wird den gesamten Verkehr auf allen Interfaces blocken - egal in welche Richtung und von wo nach wo.
Einige Beispiele:
# Lasse den Verkehr auf dc0 vom lokalen Netzwerk 192.168.0.0/24
# zur OpenBSD-Maschine mit der IP-Adresse 192.168.0.1 herein. Lasse
# ebenfalls den Antwort-Verkehr durch dc0 wieder raus.
pass in on dc0 from 192.168.0.0/24 to 192.168.0.1
pass out on dc0 from 192.168.0.1 to 192.168.0.0/24
# Lasse TCP-Verkehr auf fxp0 vom Webserver herein, der auf der
# OpenBSD-Maschine läuft. Der Interfacename fxp0 wird als Zieladresse
# verwendet, sodass Pakete mit dieser Regel nur übereinstimmen, wenn
# sie für die OpenBSD-Maschine gedacht sind.
pass in on fxp0 proto tcp from any to fxp0 port www
Falsch:
block in on fxp0 proto tcp from any to any port ssh
pass in all
In diesem Fall wird die block-Zeile zwar verarbeit, aber keinen Effekt haben, da sie von einer Zeile gefolgt wird, die alles durchlässt.
Besser:
block in quick on fxp0 proto tcp from any to any port ssh
pass in all
Diese Regeln werden auf eine etwas unterschiedliche Weise verarbeitet. Wenn die block-Zeile zutrifft, wird das Paket geblockt und wegen der quick-Option wird der Rest des Regelsatzes ignoriert.
Den Status zu halten hat viele Vorteilen, einschließlich einfacherer Regelsätze und besserer Leistung beim Paketfiltern. PF ist in der Lage, Pakete mit den Einträgen in der Statustabelle zu überprüfen, egal in welche Richtung sich das Paket bewegt. Das bedeutet, dass Filterregeln, die den Antwortverkehr hereinlassen, nicht geschrieben werden müssen. Und da Pakete, die mit zustandsabhängigen Verbindungen übereinstimmen, nicht durch die Regelsatzüberprüfung gehen, kann die Zeit, die PF zur Verarbeitung der Pakete benötigt, drastisch verringert werden.
Wenn eine Regel einen Status erstellt, dann wird das erste zutreffende Paket diesen Status zwischen Sender und Empfänger erstellen. Nun werden nicht nur die Pakete ohne Überprüfung durchgelassen, die vom Sender zum Empfänger gehen, sondern auch die Antwortpakete vom Empfänger zum Sender.
Beginnend mit OpenBSD 4.1 erstellen alle Filterregeln automatisch einen Statuseintrag, wenn ein Paket auf eine Regel zutrifft. In früheren OpenBSD-Versionen musste man für die Filterregel explizit die Option keep state angeben.
Beispiel für OpenBSD 4.1 und späteren Versionen:
pass out on fxp0 proto tcp from any to any
Beispiel für OpenBSD 4.0 und ältere Versionen:
pass out on fxp0 proto tcp from any to any keep state
Diese Regeln erlauben jeglichen ausgehenden TCP-Verkehr auf dem fxp0-Interface und lassen ebenfalls Antwortverkehr zu, der zurück durch die Firewall geht. Während das Halten von Zuständen eine schöne Funktionalität ist, kann es die Leistung deiner Firewall signifikant erhöhen, da Zustandsüberprüfungen um ein vielfaches schneller sind als das Paket durch die Filterregeln zu schicken.
Die modulate state-Option funktioniert genauso wie keep state - mit der Ausnahme, dass es nur auf TCP-Pakete zutrifft. Mit modulate state wird die »Initial Sequence Number« (ISN) des ausgehenden Verkehrs zufällig gewählt. Dies ist sinnvoll, um Verbindungen zu schützen, die von bestimmten Betriebssystemen erstellt worden sind, die eine schlechte Leistung beim Wählen von ISNs an den Tag legen. Beginnend mit OpenBSD 3.5 kann die modulate state-Option in Regeln genutzt werden, die andere Protokolle als TCP angeben.
Den Zustand von ausgehenden TCP-, UDP-, und ICMP-Paketen und ,modulate'-TCP-ISNs halten:
pass out on fxp0 proto { tcp, udp, icmp } from any \
to any modulate state
Ein anderer Vorteil beim Halten von Zuständen ist, dass der dazugehörige ICMP-Verkehr durch die Firewall gelassen wird. Wenn zum Beispiel eine TCP-Verbindung - deren Status überwacht wird - durch die Firewall gelassen wird und eine ICMP-Source-Quench-Nachricht für diese TCP-Verbindung ankommt, wird sie mit dem dazugehörigem Status übereinstimmen und durch die Firewall gelassen.
Der Bereich des Statuseintrags wird systemweit durch die state-policy-Laufzeitoption auf einer regelspezifischen Basis durch die if-bound-, group-bound- und floating-state-Optionsschlüsselwörter kontrolliert. Diese regelspezifischen Schlüsselwörter haben die gleiche Bedeutung als wenn sie mit der state-policy-Option verwendet werden. Beispiel:
pass out on fxp0 proto { tcp, udp, icmp } from any \
to any modulate state (if-bound)
Diese Regel bestimmt, dass nur Pakete, die durch das Interface fx0 gelangen, mit dem Statuseintrag übereinstimmen können.
Bedenke, dass nat-, binat- und rdr-Regeln implizit einen Status für zutreffende Verbindungen erstellen, solange die Verbindung durch den Filterregelsatz gelassen wird.
Optionen werden in Klammern und direkt nach einem der Statusschlüsselwörter (keep state, modulate state oder synproxy state) angegeben. Mehrere Optionen werden mit Kommas getrennt. In OpenBSD 4.1 und späteren Versionen ist die Option keep state implizierter Standard für alle Filterregeln. Trotzdem muss bei der Angabe von Statusoptionen eines dieser Statusschlüsselwörter vor der Option stehen.
Eine Beispielregel:
pass in on $ext_if proto tcp to $web_server \
port www keep state \
(max 200, source-track rule, max-src-nodes 100, max-src-states 3)
Die oben angegebene Regel sorgt für folgendes Verhalten:
Ein separater Satz von Begrenzungen kann auf zustandsabhängigen TCP-Verbindungen gesetzt werden, die den dreifachen Handschlag vollzogen haben.
Beide Optionen beziehen automatisch die source-track rule-Option mit ein und sind inkompatibel zu source-track global.
Da diese Begrenzungen nur für TCP-Verbindungen gültig sind, die den dreifachen Handschlag vollzogen haben, können aggressivere Aktionen gegen die offensiven IP-Adressen durchgeführt werden.
Ein Beispiel:
table <abusive_hosts> persist
block in quick from <abusive_hosts>
pass in on $ext_if proto tcp to $web_server \
port www flags S/SA keep state \
(max-src-conn 100, max-src-conn-rate 15/5, overload <abusive_hosts> flush)
Dies macht Folgendes:
Damit PF die TCP-Flags während der Überprüfung einer Regel inspiziert, muss das flags-Schlüsselwort mit folgender Syntax verwendet werden:
flags check/mask
flags any
Der mask-Teil teilt PF mit, nur die angegebenen Flags zu inspizieren und der check-Teil gibt an, welche(r) Flag(s) im Header aktiviert sein müssen, damit eine Übereinstimmung stattfinden kann. Das Schlüsselwort any ermöglicht jede erdenkliche Kombination der zu setzenden Optionen im Header.
pass in on fxp0 proto tcp from any to any port ssh flags S/SA
Die hier angegebene Regel lässt TCP-Verkehr mit gesetztem SYN-Flag durch, während nur die SYN- und ACK-Flags überprüft werden. Ein Paket mit den SYN- und ECE-Flags würde der oben genannten Regel entsprechen, während ein Paket mit SYN und ACK oder nur ACK keine Übereinstimmung hätte.
In OpenBSD 4.1 und späteren Versionen wird standardmäßig flags S/SA für TCP-Regeln verwendet. Zusammen mit dem OpenBSD-4.1-Standard keep state für Filterregeln sind diese beiden Regeln gleichwertig:
pass out on fxp0 proto tcp all flags S/SA keep state
pass out on fxp0 proto tcp all
Jede Regel wird auf TCP-Pakete reagieren, deren SYN-Flag gesetzt und ACK-Flag nicht gesetzt ist, und einen Statuseintrag für die zutreffenden Pakete anlegen. Die Standardflags können mit der Option flags wie oben erläutert überschrieben werden.
In OpenBSD 4.0 und älteren Versionen wurden keine Standardflags für Filterregeln angegeben. Jede Regel musste daher zu überprüfende Flag(s) übergeben bekommen und explizit die Option keep state gesetzt haben.
pass out on fxp0 proto tcp all flags S/SA keep state
Man sollte vorsichtig bei der Verwendung mit Flags sein - zu verstehen,
was du warum tust, und vorsichtig mit den Ratschlägen von Leuten zu
sein, die häufig schlechte geben. Einige Leute empfehlen das Erstellen
von ,states', "nur, wenn das SYN-Flag gesetzt ist und kein anderes".
Solch eine Regel würde wie folgt enden:
. . . flags S/FSRPAUEW bad idea!!
Die Theorie dahinter ist, dass nur am Anfang der TCP-Sitzung ein ,state' erzeugt wird und die Sitzung nur mit einem SYN-Flag starten sollte, keinem anderen. Das Problem ist, dass einige Seiten anfangen, das ECN-Flag zu verwenden und jegliche Seite, die ECN verwendet und versucht, sich zu dir zu verbinden, bei einer solchen Regel abgeblockt werden würde. Eine bessere Möglichkeit ist es, überhaupt keine Flags anzugeben und PF die Standardflags für deine Regeln übernehmen lassen. Wenn du wirklich unbedingt selbst Flags angeben musst, dann sollte diese Option sicher sein:
. . . flags S/SAFR
Während dies praktisch und sicher ist, ist das Überprüfen für die FIN- und RST-Flags unnötig, wenn der Verkehr ebenfalls ge,scrubbed' wird. Der ,scrubbing'-Prozess wird PF veranlassen, jegliche eingehenden Pakete mit ungültigen TCP-Flag-Kombinationen (wie zum Beispiel SYN und RST) fallen zu lassen und potenziell unklare Kombinationen (z. B. SYN und FIN) zu normalisieren.
Wenn ein Client normalerweise eine TCP-Verbindung zu einem Server aufbaut, wird PF die Handschlag-Pakete zwischen den beiden Endpunkten durchlassen, sobald sie ankommen. PF hat jedoch die Fähigkeit, den Handschlag durch einen Proxy zu senden. Mit einem Handschlag, der durch einen Proxy gesendet wurde, wird PF selbst den Handschlag mit dem Client absolvieren, einen Handschlag mit dem Server beginnen und dann die Pakete zwischen den beiden durchlassen. Der Vorteil von diesem Prozess ist, dass keine Pakete zum Server gesendet werden, bevor der Client den Handschlag abgeschlossen hat. Dies eliminiert die Gefahr eines ,spoofed' TCP-SYN-Floods, die den Server beeinträchtigen könnten, weil die ,spoofed' Client-Verbindung nicht in der Lage ist, den Handschlag zu vollenden.
Der TCP-SYN-Proxy wird durch die Verwendung der synproxy state-Schlüsselworte in den Filterregeln aktiviert. Beispiel:
pass in on $ext_if proto tcp from any to $web_server port www \
flags S/SA synproxy state
Hier werden die Verbindungen zum Webserver durch den TCP-Proxy von PF gesendet.
Wegen der Funktionsweise von synproxy state beinhaltet es die gleiche Funktionalität wie keep state und modulate state.
Der SYN-Proxy wird nicht mit PF funktionieren, wenn dieser auf einer bridge(4) läuft.
PF bietet einen gewissen Schutz gegen Adress-,spoofing' durch das antispoof-Schlüsselwort:
antispoof [log] [quick] for interface [af]
Beispiel:
antispoof for fxp0 inet
Wenn ein Regelsatz geladen wird, wird jedes Vorkommen des antispoof-Schlüsselwortes in zwei Filterregeln eingesetzt. Angenommen, dass das Interface fxp0 die IP-Adresse 10.0.0.1 und eine Subnetz-Maske von 255.255.255.0 hat (z. B. /24), dann würde die oben angegebene antispoof-Regel wie folgt entwickelt werden:
block in on ! fxp0 inet from 10.0.0.0/24 to any
block in inet from 10.0.0.1 to any
Diese Regeln erreichen zwei Dinge:
HINWEIS. Die Filterregeln, die aus der antispoof-Regel hervorgehen, blocken ebenfalls Pakete, die über das Loopback-Interface zur lokalen Adresse gesendet werden. Es ist sowieso ein guter Stil, wenn man auf Loopbackinterfaces nicht filtert - doch bei der Verwendung von antispoof-Regeln ist das eine Notwendigkeit:
set skip on lo0 all
antispoof for fxp0 inet
Die Verwendung von antispoof sollte auf Interfaces beschränkt werden, denen eine IP-Adresse zugewiesen wurde. Wenn antispoof auf ein Interface angewandt wird, das keine IP-Adresse hat, wird das in Filterregeln enden, die so ähnlich wie folgende aussehen werden:
block drop in on ! fxp0 inet all
block drop in inet all
Mit diesen Regeln besteht die Gefahr, dass der gesamte eingehende Verkehr auf allen Interfaces geblockt wird.
Beginnend mit OpenBSD 4.0 bietet PF »Unicast Reverse Path Forwarding« (uRPF) an. Wenn ein Paket durch eine uRPF-Routine überprüft wird, so wird die Quell-IP-Adresse des Pakets in der Routingtabelle nachgesehen. Wenn das weiterführende Interface das gleiche ist, über das das Paket hereingekommen ist, so wird die uRPF-Überprüfung das Paket durchlassen. Sollten sich die Interfaces unterscheiden, so kann es sich um eine gefälschte Quelladresse handeln.
Die uRPF-Überprüfung für Pakete kann mit dem urpf-failed-Schlüsselwort in den Filterregelsätzen aktiviert werden:
block in quick from urpf-failed label uRPF
Denk daran, dass die uRPF-Überprüfung nur in Umgebungen Sinn macht, in denen das Routing symmetrisch abläuft.
uRPF bietet die gleiche Funktionalität wie Antispoof-Regeln.
Passives OS-,Fingerprinting' (OSFP) ist eine Methode zum passiven Ermitteln des Betriebssystems auf dem gegenüberliegendem Host, basierend auf bestimmten Kriterien in den TCP-SYN-Paketen des Hosts. Diese Information kann dann als Kriterium in Filterregeln verwendet werden.
PF ermittelt das entfernte Betriebssystem, indem die Charakteristiken des TCP-SYN-Pakets mit denen in der ,fingerprints'-Datei verglichen werden, welche standardmäßig /etc/pf.os ist. Sobald PF aktiviert wurde, kann die aktuelle ,fingerprint'-Liste mit diesem Kommando angesehen werden:
# pfctl -s osfp
Innerhalb der Filterregel kann ein ,fingerprint' anhand der OS-Klasse, -Version oder -Untertyp/-Patchlevel angegeben werden. Jedes dieser Objekte wird in der Ausgabe des angegebenen pfctl-Kommandos aufgelistet. Um einen ,fingerprint' in einer Filterregel anzugeben, wird das os-Schlüsselwort verwendet:
pass in on $ext_if from any os OpenBSD keep state
block in on $ext_if from any os "Windows 2000"
block in on $ext_if from any os "Linux 2.4 ts"
block in on $ext_if from any os unknown
Die spezielle Betriebssystem-Klasse unknown erlaubt es, dass alle Pakete zutreffen, wenn der ,fingerprint' des OS unbekannt ist.
Folendes sollte ZUR KENNTNIS GENOMMEN WERDEN:
pass in quick on fxp0 all allow-opts
ext_if = "fxp0"
int_if = "dc0"
lan_net = "192.168.0.0/24"
# tabelle, die alle IP-Adressen beinhaltet, die der firewall zugewiesen
# worden sind
table <firewall> const { self }
# filtere nicht das loopback-interface
set skip on lo0
# ,scrub' auf alle eingehenden pakete anwenden
scrub in all
# eine richtlinie zum standardmäßigen blocken errichten
block all
# ,spoofing'-schutz für alle interfaces.
block in quick from urpf-failed
# nur ssh-verbindungen vom lokalen netzwerk erlauben, wenn es von dem
# computer 192.168.0.15 kommt, dem man vertrauen kann. verwende
# ,block return', sodass ein TCP-RST gesendet wird, um blockierte
# Verbindungen sofort zu schließen. verwende ,quick', sodass diese
# regel nicht von der ,pass'-regel weiter unten überschrieben wird.
block return in quick on $int_if proto tcp from ! 192.168.0.15 \
to $int_if port ssh
# den gesamten verkehr von und zum lokalen netzwerk durchlassen.
# diese regeln werden statuseinträge erstellen, da die standardoption
# "keep state" automatisch übernommen wird.
pass in on $int_if from $lan_net to any
pass out on $int_if from any to $lan_net
# tcp, udp und icmp durch das externe (internet-)interface rauslassen.
# tcp-verbindungen werden reguliert, udp/icmp-verbindungen werden
# statusüberwacht.
pass out on $ext_if proto { tcp udp icmp } all modulate state
# erlaube eingehende ssh-verbindungen auf dem externen interface, so
# lange sie NICHT für die firewall bestimmt sind (z. B. wenn sie an
# eine maschine im lokalen netzwerk gerichtet sind). zeichne das erste
# paket auf, sodass wir später sagen können, wer versucht, zu verbinden.
# verwende den tcp-syn-proxy um einen proxy für diese verbindung
# aufzubauen. die standardflags "S/SA" werden dieser regel automatisch
# von PF übergeben.
pass in log on $ext_if proto tcp from any to ! <firewall> \
port ssh synproxy state
|
[Zurück: Tabellen] [Inhalt] [Weiter: Network Address Translation]