[Zurück: Tabellen]
[Inhalt]
[Weiter: Network Address Translation]
PF: Pakete filtern
Inhaltsverzeichnis
Einführung
Mit dem Filtern von Paketen ist das selekte Durchlassen oder Blocken
von Datenpaketen gemeint, sobald sie durch das Netzwerkinterface
gehen. Die Kriterien, die
pf(4) verwendet, wenn Pakete untersucht werden, basieren auf den
Layer-3-
(IPv4 und
IPv6) und Layer-4-
(TCP,
UDP,
ICMP und
ICMPv6) Headern. Die meistgenutzten Kriterien sind Quell- und
Zieladressen sowie Zielport und das Protokoll.
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.
Regelsyntax
Die generelle höchstgradig vereinfachte Syntax für Filterregeln
ist:
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]
- action
- Die Aktion, die für zutreffende Pakete angewandt werden soll:
pass oder block. Die pass-Aktion wird das
Paket zurück zum Kernel für weitere Verarbeitung lassen, während die
block-Aktion je nach der
block-policy-Option
anders reagieren wird. Die standardmäßige Reaktion kann entweder durch
Angabe von block drop oder block return
verändert werden.
- direction
- Die Richtung, in die das Paket sich bewegt: rein (in)
oder raus (out).
- log
- Gibt an, dass das Paket per
pflogd(8) aufgezeichnet werden soll. Wenn die Regel zustandsbezogen
ist, dann wird nur das Paket aufgezeichnet, das den Status aufgebaut hat.
Um alle Pakete unabhängig davon aufzuzeichnen, verwende
log (all).
- quick
- Wenn ein Paket auf eine Regel zutrifft, die quick angibt,
dann wird die Regel als letzte zutreffende Regel angesehen, wodurch
sie die Aktion (action) angibt, die durchgeführt werden
soll.
- interface
- Der Name eines Netzwerkinterfaces (bzw. die Gruppe von
Netzwerkinterfaces) durch das sich das Paket bewegt.
Interfaces können mit dem
ifconfig(8)-Kommando zu beliebigen Gruppen hinzugefügt werden.
Einige Gruppen werden automatisch vom Kernel erstellt:
- Die egress-Gruppe, die Interfaces enthält, die die
Standardroute(n) enthalten.
- Interfacefamiliengruppe für geklonte Interfaces.
Zum Beispiel ppp oder carp.
Dies wird dazu führen, dass die Regel für jedes Paket zutrifft, das
das ppp- oder carp-Interface durchläuft - je nachdem.
- af
- Die Adressfamilie des Pakets: inet für IPv4 oder
inet6 für IPv6. PF ist normalerweise in der Lage, anhand der
Parameter für die Quell- und/oder Zieladresse(n) das selbst zu
erkennen.
- protocol
- Die Layer-4-Protokolle des Pakets:
- tcp
- udp
- icmp
- icmp6
- Ein gültiger Protokollname aus
/etc/protocols
- Eine Protokollnummer zwischen 0 und 255
- Ein Satz an Protokollen unter Verwendung einer
Liste.
- src_addr, dst_addr
- Die Quell/Zieladresse im IP-Header. Adressen können wie folgt
angegeben werden:
- Eine einzelne IPv4- oder IPv6-Adresse.
- Ein
CIDR-Netzwerkblock
- Ein »fully qualified domain name«, der per DNS aufgelöst wird, wenn
der Regelsatz geladen wird. Alle resultierenden IP-Adressen werden in
die Regel eingesetzt.
- Der Name des Netzwerkinterfaces. Jegliche IP-Adressen, die dem
Interface zugewiesen worden sind, werden in die Regel eingesetzt.
- Der Name des Netzwerkinterfaces gefolgt von
/netmask (z. B. /24). Jede IP-Adresse auf
dem Interface wird mit der Netzmaske kombiniert, um einen
CIDR-Netzwerkblock zu formen, welcher in die Regel eingesetzt wird.
- Der Name des Netzwerkinterfaces oder der Gruppe in Klammern
( ). Die Klammern teilen PF mit, dass die Regel sich
aktualisieren soll, wenn sich die IP-Adresse(n) des genannten
Interfaces ändert/ändern. Dies ist insbesondere dann sinnvoll, wenn die
IP-Adresse per DHCP oder dial-up erhalten wird, da der Regelsatz so
nicht jedes Mal neugeladen werden muss, wenn sich die Adresse ändert.
- Der Name eines Netzwerkinterfaces gefolgt von einem dieser
Modifizierer:
- :network - fügt den CIDR-Netzwerkblock ein (z. B.
192.168.0.0/24)
- :broadcast - fügt die Netzwerk-Broadcastadresse ein
(z. B. 192.168.0.255)
- :peer - fügt die IP-Adresse des Peers auf einem
Point-to-Point-Link ein
- Zusätzlich kann der :0-Modifizierer einem Interfacenamen
oder einem der vorherigen Modifizierer angehängt werden, um darauf
hinzuweisen, dass PF keine IP-Adressaliase in die Einfügung mit
übernehmen soll. Diese Modifizierer können ebenfalls verwendet werden,
wenn sich das Interface in Klammern befindet.
Beispiel: fxp0:network:0
- Eine Tabelle.
- Das Schlüsselwort urpf-failed kann für die Quelladresse
verwendet werden, um anzugeben, dass diese durch den
uRPF-Check geschickt werden soll.
- Irgendeine der oben genannten, unter Verwendung der !-
("nicht") Modifikation.
- Ein Satz an Adressen unter Verwendung einer
Liste.
- Das Schlüsselwort any, das bedeutet für alle Adressen
steht.
- Das Schlüsselwort all, das eine Kurzschreibweise für
from any to any ist.
- src_port, dst_port
- Der Quell/Ziel-Port in dem Layer-4-Paket-Header. Ports können
wie folgt angegeben werden:
- Eine Nummer zwischen 1 und 65535
- Ein gültiger Servicename aus
/etc/services
- Ein Satz an Ports unter Verwendung einer
Liste
- Ein Bereich:
- != (ungleich)
- < (kleiner als)
- > (größer als)
- <= (kleiner oder gleich)
- >= (größer oder gleich)
- >< (Bereich)
- <> (invertierter Bereich)
- Die letzten beiden sind Binäroperatoren (sie benötigen zwei
Argumente) und fügen die Argumente nicht in den Bereich ein.
- : (inklusiver Bereich)
- Der Operator für den inklusiven Bereich ist ebenfalls ein
Binäroperator und fügt die Argumente mit in den Bereich ein.
- tcp_flags
- Gibt die Flags an, die in dem TCP-Header gesetzt sein müssen, wenn
proto tcp verwendet wird. Flags werden als
flags check/mask angegeben.
flags S/SA - dies instruiert PF nur auf die S- und A-Schalter (SYN und
ACK) zu achten, und eine Entsprechung nur dann zu erkennen, wenn einzig der
SYN-Schalter aktiviert ist (dies wird standardmäßig auf alle TCP-Regeln
angewandt).
flags any instruiert PF, keinerlei Schalter zu überprüfen.
- state
- Gibt an, ob die Statusinformation für das Paket gehalten werden
soll, das auf diese Regel zutrifft.
- no state - funktioniert mit TCP, UDP und ICMP.
PF wird keinen Zustand für diese Verbindung zurückverfolgen.
Für TCP-Verbindungen wird normalerweise flags any zusätzlich benötigt.
- keep state - funktioniert mit TCP, UDP und ICMP.
Diese Option ist Standard für alle Filterregeln.
- modulate state - funktioniert nur mit TCP. PF wird
starke »Initial Sequence Numbers« (ISNs) für Pakete erstellen, die auf
diese Regel zutreffen.
- synproxy state - eingehende TCP-Verbindungen werden durch
den Proxy geschickt, um beim Beschützen der Server vor Floods von
gefälschten TCP-SYNs zu helfen. Diese Option beinhaltet die
Funktionalität von keep state und modulate state.
Standardmäßiges Blocken
Die empfohlene Praxis, wenn eine Firewall aufgesetzt wird ist, einen
»standardmäßig block«-Weg einzuschlagen. Dies bedeutet, dass
alles geblockt und dann selektiv bestimmter Verkehr durch
die Firewall gelassen wird. Dieser Weg ist empfohlen, da man trotz
entstehender Fehler auf der sicheren Seite ist und das Schreiben eines
Regelsatzes einfacher wird.
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.
Verkehr durchlassen
Verkehr muss nun explizit durch die Firewall gelassen werden oder er
wird wegen der »standardmäßig blocken«-Richtlinie fallen gelassen.
Nun kommen Paketkriterien wie Quell/Zielports, Quell/Zieladressen
und das Protokoll ins Spiel. Wann auch immer Verkehr durch die
Firewall gelassen wird, sollte(n) die Regel(n) so restriktiv wie möglich
geschrieben werden. Dies stellt sicher, dass der beabsichtigte Verkehr -
und zwar nur der beabsichtigte Verkehr - durchgelassen wird.
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
Das quick-Schlüsselwort
Wie zuvor angedeutet wurde, wird jedes Paket mit dem gesamten
Filterregelsatz von oben nach unten überprüft. Standardmäßig wird das
Paket als durchgelassen markiert, was aber von jeglicher Regel geändert
werden kann. Das wiederum kann mehrmals wechseln, bevor das Ende
der Filterregeln erreicht ist. Die letzte zutreffende Regel
gewinnt. Es gibt eine Ausnahme dafür: Die quick-Option
einer Filterregel hat zur Folge, dass jegliche Verarbeitung der weiteren
Regeln abgebrochen und die angegebene Aktion durchgeführt wird.
Lass uns nun einige Beispiele dafür ansehen:
Falsch:
block in on fxp0 proto tcp to port ssh
pass in all
In diesem Fall wird die block-Zeile zwar verarbeitet, aber
keinen Effekt haben, da sie von einer Zeile gefolgt wird, die alles
durchlässt.
Besser:
block in quick on fxp0 proto tcp to 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.
Status halten
Eine der wichtigen Fähigkeiten von Packet Filter ist »keeping state«
(bzw. »stateful inspection«. »Stateful inspection« verweist auf PFs
Fähigkeit, den Status (oder Fortschritt) auf der Netzwerkverbindung
nachweisen zu können. Durch die Aufbewahrung der Informationen über
jede Verbindung in einer Statustabelle ist PF in der Lage, schnell
herauszufinden, ob ein Paket, das durch die Firewall gelassen wird,
zu einer bereits erstellten Verbindung gehört. Wenn es das tut, wird
es durch die Firewall gelassen, ohne durch die Regelsätze geschickt
zu werden.
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.
Alle pass-Regeln erzeugen automatisch Statuseinträge wenn ein Paket der
Regel entspricht.
Dies kann durch Benutzung der Option no state explizit deaktiviert
werden.
pass out on fxp0 proto tcp from any to any
Diese Regel erlaubt jeglichen ausgehenden TCP-Verkehr auf dem
fxp0-Interface und lassen ebenfalls Antwortverkehr zu, der
zurück durch die Firewall geht.
Die Vorhaltung von Zuständen steigert die Performance deiner Firewall
signifikant, da Zustandszugriffe um ein Vielfaches schneller sind als das
Anwenden der Filterregeln auf ein Paket.
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.
Um einfachere Regelsätze zu ermöglichen, kann die Option
modulate state in Regeln benutzt werden, die sich nicht auf das
TCP-Protokoll beziehen; in diesen Fällen wird es als keep state
behandelt.
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- 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.
Den Zustand für UDP vorhalten
Man wird ab und zu hören, dass jemand sagt: »Man kann keinen Zustand
mit UDP erstellen, da UDP ein zustandsloses Protokoll ist!« Obwohl es
stimmt, dass UDP-Verbindungssitzungen kein Konzept eines Zustands
haben (einen expliziten Anfang und ein explizites Ende), hat dies keine
Wirkung auf PFs Fähigkeit, einen Status für eine UDP-Sitzung zu
erstellen. In dem Fall von Protokollen ohne Start- und Endpakete,
merkt sich PF einfach, wie lange es her ist, dass ein zutreffendes
Paket durchgelassen wurde. Wenn der Timeout erreicht wurde, wird
der Status gelöscht. Der Timeout-Wert kann in der
options-Sektion in der Datei
pf.conf gesetzt werden.
Optionen für zustandsabhängiges Tracking
Filterregeln, die einen Statuseintrag erstellen, können mehrere
Optionen angeben, um das Verhalten des resultierenden Statuseintrags
zu kontrollieren. Die folgenden Optionen sind verfügbar:
- max anzahl
- Begrenzt die maximale Anzahl Statuseinträge, die die Regel
erstellen kann, auf anzahl.
Wenn das Maximum erreicht wurde, werden Pakete, die normalerweise
einen Status erstellen würden, nicht auf diese Regel zutreffen, bis
die Anzahl vorhandener Zustände wieder unterhalb der Obergrenze liegt.
- no state
- Die Regel wird davon abgehalten, automatisch einen Statuseintrag
anzulegen.
- source-track
- Diese Option aktiviert das Tracking der Anzahl der Zustände, die
für jede einzelne IP-Adresse erstellt wurden.
Diese Option hat zwei Formate:
- source-track rule - Die maximale Anzahl der
Zustände, die durch diese Regel erstellt werden können, wird
durch die max-src-nodes- und
max-src-states-Optionen dieser Regel begrenzt. Nur
Statuseinträge, die durch diese bestimmte Regel erstellt
wurden, werden gezählt und mit der Grenze dieser Regel
überprüft.
- source-track global - Die Anzahl der Zustände
aller Regeln, die diese Option nutzen, werden begrenzt. Jede
Regel kann unterschiedliche max-src-nodes- und
max-src-states-Optionen angeben, jedoch werden
Statuseinträge, die durch eine der teilnehmenden Regeln
erstellt wurden, mit der individuellen Begrenzung der Regel
überprüft.
Die gesamte Anzahl der Quell-IP-Adressen, die verfolgt werden, kann
systemweit durch die Verwendung der
src-nodes-Laufzeitoption
kontrolliert werden.
- max-src-nodes anzahl
- Wenn die source-track-Option genutzt wird, wird
max-src-nodes die Anzahl der Quell-IP-Adressen begrenzen, die
gleichzeitig einen Status anlegen können. Diese Option kann nur zusammen
mit source-track rule genutzt werden.
- max-src-states anzahl
- Wenn die source-track-Option verwendet wird,
wird max-src-states die Anzahl gleichzeitig erstellter
Statuseinträge begrenzen, die pro Quell-IP-Adresse angelegt werden
können.
Der Bereich dieser Begrenzung (z. B. Zustände, die nur durch
diese Regel erstellt wurden, oder die durch alle Regeln unter
Verwendung von source-track erstellt wurden) ist abhängig von
der angegebenen source-track-Option.
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:
- Begrenze die maximale Anzahl der Zustände, die diese Regel
erstellen kann, auf 200
- Aktiviere Sourcetracking; begrenze die Anzahl möglicher
Statuserstellungen nur für diese Regel
- Begrenze die maximale Anzahl der Nodes, die gleichzeitig Zustände
erstellen, auf 100
- Begrenze die maximale Anzahl gleichzeitiger Zustände pro
Quell-IP auf 3
Ein separater Satz von Begrenzungen kann auf zustandsabhängigen
TCP-Verbindungen gesetzt werden, die den dreifachen Handschlag vollzogen
haben.
- max-src-conn Nummer
- Begrenzt die maximale Anzahl gleichzeitiger TCP-Verbindungen,
die den dreifachen Handschlag vollzogen haben, die ein einzelner Host
erstellen kann.
- max-src-conn-rate Nummer / Intervall
- Begrenzt die Rate der neuen Verbindungen, die zu einem bestimmten
Zeitintervall aufgebaut werden können.
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.
- overload <Tabelle>
- Schreibt den IP-Adresse des offensiven Hosts in die benannte
Tabelle.
- flush [global]
- Zerstöre alle anderen ,states', die auf diese Regel zutreffen und
die von dieser Quell-IP stammen.
Wenn global angegeben wird, zerstöre alle ,states', die auf
diese Quell-IP zutreffen, unabhängig davon, welche Regel diesen ,state'
erzeugt hat.
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:
- Begrenzt die maximale Anzahl der Verbindungen pro Quelle auf 100
- Begrenzt die Rate der Anzahl der Verbindungen auf 15 pro
5-sekündiger Zeitspanne
- Schreibt die IP-Adresse jeglichen Hosts, der diese Begrenzungen
bricht, in die Tabelle <abusive_hosts>
- Für jegliche offensive IP-Adresse gilt, dass alle ,states', die
von dieser Regel erzeugt wurden, gelöscht werden.
TCP-Flags
TCP-Pakete anhand ihrer Flags zu überprüfen wird meistens verwendet, um
TCP-Pakete zu filtern, die versuchen, eine neue Verbindung zu eröffnen.
Die TCP-Flags und ihre Bedeutungen sind hier aufgeführt:
- F : FIN - Finish; Ende der Sitzung
- S : SYN - Synchronize; Weist auf eine Anfrage hin, eine Sitzung zu beginnen
- R : RST - Reset; Lasse eine Verbindung fallen
- P : PUSH - Push; Paket wird umgehend gesendet
- A : ACK - Acknowledgement; Erhalten
- U : URG - Urgent; Dringend
- E : ECE - Explicit Congestion Notification Echo
- W : CWR - Congestion Window Reduced
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
pass in on fxp0 proto tcp from any to any port ssh
Da flags S/SA standardmäßig gesetzt ist, sind obige Regeln äquivalent.
Jede dieser Regeln lässt TCP-Datenverkehr mit gesetztem SYN-Schalter passieren,
und betrachtet dabei nur die SYN- und ACK-Schalter.
Ein Paket mit gesetzten SYN- und ECE-Schaltern würde obigen Regeln entsprechen,
nicht jedoch ein Paket mit gesetzten SYN und ACK oder nur ACK.
Die Standardschalter können mit Hilfe der Option flags wie oben
erläutert überschrieben werden.
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 der FIN- und
RST-Schalter unnötig, wenn der Datenverkehr ebenfalls gereinigt wird.
Der Reinigungsprozeß veranlasst PF, sowohl eingehende Pakete mit unzulässigen
TCP-Schalterkombinationen (wie SYN und RST) zu verwerfen, als auch potenziell
zweifelhafte Kombinationen (wie SYN und FIN) zu normalisieren.
TCP-SYN-Proxy
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 besitzt jedoch die Fähigkeit, als Proxy für den Handschlag zu fungieren.
Im Falle einer »TCP SYN flood«-Attacke beendet der Angreifer niemals den
Dreiwegehandschlag, sodass die Packete des Angreifers niemals den geschützten
Server erreichen, zulässige Clients jedoch den Handschlag komplettieren und
durchgelassen werden.
Die Handhabung angetäuschter »TCP SYN«-Fluten in PF minimiert deren Einfluss
auf den geschützten Service.
Die routinemäßige Anwendung dieser Option ist jedoch nicht empfehlenswert, da
mit ihr das TCP-Protokoll nicht dem erwarteten Verhalten entspricht, und zwar
sowohl wenn der Server eine Anforderung nicht bearbeiten kann, als auch wenn
Belastungsausgleicher (»Load Balancer«) involviert sind.
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 to $web_server port www 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.
Blockade gefälschter Pakete
Adress-»fälschung« liegt vor, wenn ein böswilliger Benutzer die
Quell-IP-Adresse in den Paketen ändert, die versendet werden, um entweder
seine tatsächliche Adresse zu verbergen oder um so zu wirken, als würde
er ein anderes Gerät im Netzwerk bedienen. Sobald ein Benutzer eine
,spoofed' Adresse hat, kann er Netzwerkattacken durchführen, ohne seine
wahre Herkunft offenzulegen, oder erreicht Zugriff auf Netzwerkdienste,
die nur bestimmten IP-Adressen ermöglicht werden sollen.
PF bietet einen gewissen Schutz gegen Adress-,spoofing' durch das
antispoof-Schlüsselwort:
antispoof [log] [quick] for interface [af]
- log
- Gibt ab, ob das zutreffende Paket via
pflogd(8) aufgezeichnet werden soll.
- quick
- Wenn ein Paket auf diese Zeile zutrifft, wird es als ,Gewinner'-Regel
angesehen und die Verarbeitung des Regelsatzes angehalten.
- interface
- Das Netzwerk-Interface, auf dem ,spoofing'-Schutz aktiviert werden
soll. Dies kann ebenfalls eine Liste
von Interfaces sein.
- af
- Die Adress-Familie, für die der ,spoofing'-Schutz aktiviert werden
soll, entweder inet für IPv4 oder inet6 für IPv6.
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:
- Blockt den gesamten Verkehr, der vom 10.0.0.0/24-Netzwerk kommt, der
nicht durch fxp0 hereinkommt. Da das 10.0.0.0/24-Netzwerk
auf dem fxp0-Interface liegt, dürften Pakete mit Quell-Adressen aus
diesem Netzwerkblock niemals auf anderen Interfaces gesehen werden können.
- Blockt den gesamten Verkehr von 10.0.0.1, der IP-Adresse von
fxp0.
Die Host-Maschine dürfte niemals Pakete zu sich selbst durch ein externes
Interface senden, sodass alle eingehenden Pakete mit der Source-Adresse,
die an dieser Maschine ankommen, als böswillig angesehen werden können.
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.
Unicast Reverse Path Forwarding
PF bietet »Unicast Reverse Path Forwarding« (uRPF).
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 Betriebssystem-,Fingerprinting'
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 proto tcp from any os OpenBSD keep state
block in on $ext_if proto tcp from any os "Windows 2000"
block in on $ext_if proto tcp from any os "Linux 2.4 ts"
block in on $ext_if proto tcp from any os unknown
Die spezielle Betriebssystem-Klasse unknown erlaubt es, dass
alle Pakete zutreffen, wenn der ,fingerprint' des OS unbekannt ist.
Folgendes sollte ZUR KENNTNIS GENOMMEN WERDEN:
- Betriebssystem-,fingerprints' sind ab und zu falsch, da ,spoofed'
oder erstellte Pakete so gemacht worden sind, dass sie so aussehen,
als wenn sie von einem spezifischen Betriebssystem kommen würden.
- Bestimmte Revisionen oder Patchlevel eines Betriebssystems können
das Verhalten vom ,stack' ändern und daher dazu führen, dass der
,fingerprint' nicht mehr übereinstimmt oder wie ein anderer Eintrag
wirkt.
- OSFP funktioniert nur mit TCP-SYN-Paketen; es wird nicht mit anderen
Protokollen oder bereits aufgebauten Verbindungen funktionieren.
IP-Optionen
Standardmäßig blockt PF alle Pakete, die IP-Optionen haben. Dies kann
die Arbeit für ,OS fingerprinting'-Anwendungen wie nmap erschweren.
Wenn du eine Applikation hast, die das Durchlassen dieser Pakete
erfordert, wie zum Beispiel Multicast oder IGMP, kannst du die
allow-opts-Direktive verwenden:
pass in quick on fxp0 all allow-opts
Beispiel-Filterregelsatz
Weiter unten ist ein Beispiel für einen Filterregelsatz. Auf der
Maschine läuft PF, die als Firewall zwischen einem kleinen, internen
Netzwerk und dem Internet fungiert. Nur die Filterregeln werden
angezeigt;
queueing,
nat,
rdr
etc. wurden aus diesem Beispiel herausgelassen.
ext_if = "fxp0"
int_if = "dc0"
lan_net = "192.168.0.0/24"
# table containing all IP addresses assigned to the firewall
table <firewall> const { self }
# don't filter on the loopback interface
set skip on lo0
# scrub incoming packets
match in all scrub (no-df)
# setup a default deny policy
block all
# activate spoofing protection for all interfaces
block in quick from urpf-failed
# only allow ssh connections from the local network if it's from the
# trusted computer, 192.168.0.15. use "block return" so that a TCP RST is
# sent to close blocked connections right away. use "quick" so that this
# rule is not overridden by the "pass" rules below.
block return in quick on $int_if proto tcp from ! 192.168.0.15 \
to $int_if port ssh
# pass all traffic to and from the local network.
# these rules will create state entries due to the default
# "keep state" option which will automatically be applied.
pass in on $int_if from $lan_net
pass out on $int_if to $lan_net
# pass tcp, udp, and icmp out on the external (Internet) interface.
# tcp connections will be modulated, udp/icmp will be tracked
# statefully.
pass out on $ext_if proto { tcp udp icmp } all modulate state
# allow ssh connections in on the external interface as long as they're
# NOT destined for the firewall (i.e., they're destined for a machine on
# the local network). log the initial packet so that we can later tell
# who is trying to connect.
# Uncomment last part to use the tcp syn proxy to proxy the connection.
pass in log on $ext_if proto tcp to ! <firewall> \
port ssh # synproxy state
|
[Zurück: Tabellen]
[Inhalt]
[Weiter: Network Address Translation]
www@openbsd.org
$OpenBSD: filter.html,v 1.43 2012/11/02 07:24:05 ajacoutot Exp $