[Zurück: Tabellen]
[Inhalt]
[Weiter: Network Address Translation]
PF: Pakete filtern
Inhaltsverzeichnis
Einführung
Paket-Filtern ist das selektive Durchlassen oder Blocken von Datenpaketen,
sobald sie durch das Netzwerk-Interface 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
Ziel-Adressen sowie Ziel-Port und das Protokoll.
Filterregeln geben die Kriterien an, auf die ein Paket zutreffen muss, und
die resultierende Handlung, entweder Blocken oder Durchlassen, die
durchgeführt wird, wenn eine Übereintreffung gefunden wird. Filterregeln
werden in sequentieller 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, entweder
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
das Angeben von block drop oder block return
verändert werden.
- direction
- Die Richtung, in die das Paket sich bewegt, entweder rein (in)
oder raus (out).
- log
- Gibt an, dass das Paket per
pflogd(8) aufgezeichnet werden soll. Wenn die Regel die
keep state-, modulate state- oder
synproxy state-Option angibt, dann wird nur das Paket
aufgezeichnet, das den ,state' 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 Netzwerk-Interfaces, bzw. die Gruppe von Netzwerk-Interfaces,
durch das sich das Paket bewegt.
Eine Interface-Gruppe wird mit dem Namen des Interfaces angegeben, jedoch
ohne der angehängten Zahl am Ende.
Zum Beispiel: ppp oder fxp.
Dies wird dazu führen, dass die Regel für jedes Paket zutrifft, das
das ppp- oder fxp-Interface durchläuft, je nachdem.
- af
- Die Adress-Familie des Pakets, entweder inet für IPv4 oder
inet6 für IPv6. PF ist normalerweise in der Lage, anhand der
Parameter für die Quell- und/oder Ziel-Adresse(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-/Ziel-Adresse 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 Netzwerk-Interfaces. Jegliche IP-Adressen, die dem
Interface zugewiesen worden sind, werden in die Regel eingesetzt.
- Der Name des Netzwerk-Interfaces 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 Netzwerk-Interfaces in Klammern ( ). Diese
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 Netzwerk-Interfaces gefolgt von einem dieser
Modifizierer:
- :network - fügt den CIDR-Netzwerkblock ein (z.B.
192.168.0.0/24)
- :broadcast - fügt die Netzwerk-Broadcast-Adresse 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 Interface-Namen
oder einem der vorherigen Modifizierer angehängt werden, um darauf
hinzuweisen, dass PF keine IP-Adress-Aliase 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.
- Irgendeine der oben genannten, unter Verwendung der !-
("nicht") Modifikation.
- Ein Satz an Adressen unter Verwendung einer
Liste.
- Das Schlüsselwort any, das bedeutet: alle Adressen
- Das Schlüsselwort all, welches 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)
- <> (umgekehrter Bereich)
- Die letzten beiden sind Binär-Operatoren (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är-Operator 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. Zum Beispiel: flags
S/SA - dies sagt PF, dass nur auf die S- und A- (SYN und ACK) Flags
geachtet werden und zutreffen soll, wenn nur das SYN-Flag ,an' ist.
- state
- Gibt an, ob die ,state'-Information für das Paket gehalten werden
soll, das auf diese Regel zutrifft.
- keep state - funktioniert mit TCP, UDP und ICMP.
- 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 bei der Beschützung der Server vor ,spoofed'
TCP-SYN-Floods 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äßiges Blocken'-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 er das Schreiben eines
Regelsatzes einfacher macht.
Um eine ,standardmäßiges Blocken'-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äßiges Blocken'-Richtlinie fallen gelassen.
Dies ist, wo Paket-Kriterien wie Quell-/Ziel-Ports, Quell-/Ziel-Adressen
und das Protokoll ins Spiel kommen. 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 Web-Server herein, der auf der
# OpenBSD-Maschine läuft. Der Interface-Name fxp0 wird als Ziel-Adresse
# verwendet, so dass 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, und das wiederum mehrmals wechseln kann, 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 from any to any port ssh
pass in all
In diesem Fall wird die block-Zeile zwar verarbeit, aber
wird keinen Effekt haben, da sie von einer Zeile gefolgt wird, die alles
durchlassen wird.
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.
,state' halten
Eine der wichtigen Fähigkeiten von Packet Filter ist ,keeping state',
bzw. ,stateful inspection'. ,Stateful inspection' verweist auf PFs
Fähigkeit, den ,state', oder Fortschritt, auf der Netzwerkverbindung
nachweisen zu können. Durch das Aufbewahren der Informationen über
jede Verbindung in einer ,state'-Tabelle 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 ,state' zu halten hat viele Vorteilen, einschließlich einfacherer
Regelsätze und besserer Leistung beim Paket-Filtern. PF ist in der
Lage, Pakete mit den Einträgen in der ,state'-Tabelle zu überprüfen,
egal, in welche Richtung sich das Paket bewegt, was bedeutet, dass
Filterregeln, die den Antwort-Verkehr hereinlassen, nicht geschrieben
werden müssen. Und da Pakete, die mit ,stateful'-Verbindungen
übereinstimmen, nicht durch die Regelsatz-Überprüfung gehen, kann
die Zeit, die PF zum Verarbeiten der Pakete benötigt, drastisch
verringert werden.
Wenn eine Regel die keep state-Option besitzt, erstellt das
erste zutreffende Paket einen ,state' zwischen Sender und Empfänger.
Nun werden nicht nur die Pakete ohne Überprüfung durchgelassen,
die vom Sender zum Empfänger gehen, sondern auch die Antwort-Pakete
vom Empfänger zum Sender. Zum Beispiel:
pass out on fxp0 proto tcp from any to any keep state
Dies erlaubt jeglichen ausgehenden TCP-Verkehr auf dem
fxp0-Interface und lässt ebenfalls Antwort-Verkehr zu, der
zurück durch die Firewall geht.
Während das Halten von ,states' eine schöne Funktionalität ist, kann
es die Leistung deiner Firewall signifikant erhöhen, da
,state'-Ü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 ,state' 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 ,states' ist, dass der
dazugehörige ICMP-Verkehr durch die Firewall gelassen wird. Wenn zum
Beispiel keep state für eine TCP-Verbindung angegeben wurde
und eine ICMP-,source-quench'-Nachricht für diese TCP-Verbindung
ankommt, wird sie mit dem dazugehörigem ,state' übereinstimmen und
durch die Firewall gelassen.
Der Bereich des ,state'-Eintrags wird systemweit durch die
state-policy-Laufzeit-Option
auf einer Regel-spezifischen Basis durch die if-bound-,
group-bound- und floating-state-Option-Schlüsselwörter
kontrolliert. Diese Regel-spezifischen 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, damit Pakete mit dem ,state'-Eintrag
übereinstimmen können, diese durch das fxp0-Interface gelangen
müssen.
Bedenke, dass nat-,
binat- und
rdr-Regeln implizit einen ,state'
für zutreffende Verbindungen erstellen, solange die Verbindung
durch den Filterregelsatz gelassen wird.
,state' für UDP halten
Man wird ab und zu hören, dass jemand sagt: "Man kann keinen ,state'
mit UDP erstellen, da UDP ein ,stateless' Protokoll ist!" Obwohl es
wahr ist, dass UDP-Verbindungssitzungen kein Konzept eines ,states'
haben (einen expliziten Anfang und ein explizites Ende), hat dies keine
Wirkung auf PFs Fähigkeit, einen ,state' für eine UDP-Sitzung zu
erstellen. In dem Fall von Protokollen ohne ,Start'- und ,Ende'-Paketen,
merkt sich PF einfach, wie lange es her ist, dass ein zutreffendes
Paket durchgelassen wurde. Wenn der Timeout erreicht wurde, wird
der ,state' gelöscht. Der Timeout-Wert kann in der
options-Sektion in der Datei
pf.conf gesetzt werden.
Optionen für ,Stateful' Tracking
Wenn eine Filterregel einen ,state'-Tabelleneintrag durch das Verwenden
irgendeines keep state-, modulate state- oder
synproxy state-Schlüsselwort anlegt, können bestimmte Optionen
angegeben werden, die das Verhalten der ,state'-Erstellung beeinflussen.
Die folgenden Optionen sind verfügbar:
- max anzahl
- Begrenzt die maximale Anzahl von ,state'-Einträgen, die die Regel
erstellen kann, auf anzahl.
Wenn das Maximum erreicht wurde, werden Pakete, die normalerweise
,state' erstellen würden, fallen gelassen, bis die Anzahl der
existierenden ,states' wieder sinkt.
- source-track
- Diese Option aktiviert das Tracking der Anzahl von States, die für
jede einzelne IP-Adresse erstellt wurden.
Diese Option hat zwei Formate:
- source-track rule - Die maximale Anzahl von
,states', die durch diese Regel erstellt werden können, wird
durch die max-src-nodes- und
max-src-states-Optionen dieser Regel begrenzt. Nur
,state'-Einträge, die durch diese bestimmte Regel erstellt
wurden, werden gezählt und mit der Grenze dieser Regel
überprüft.
- source-track global - Die Anzahl von ,states'
aller Regeln, die diese Option nutzen, werden begrenzt. Jede
Regel kann unterschiedliche max-src-nodes- und
max-src-states-Optionen angeben, jedoch werden
,state'-Einträge, die durch eine der teilnehmenden Regeln
erstellt wurden, mit der individuellen Begrenzung der Regel
überprüft.
Die gesamte Anzahl von Quell-IP-Adressen, die verfolgt werden, kann
systemweit durch die Verwendung der
src-nodes-Laufzeit-Option
kontrolliert werden.
- max-src-nodes anzahl
- Wenn die source-track-Option genutzt wird, wird
max-src-nodes die Anzahl von Quell-IP-Adressen begrenzen, die
gleichzeitig einen ,state' 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 von gleichzeitig erstellten
,state'-Einträge begrenzen, die pro Quell-IP-Adresse angelegt werden
können.
Der Bereich dieser Begrenzung (z.B. ,states', die nur durch diese Regel
erstellt wurden, oder ,states', die durch alle Regeln unter Verwendung
von source-track erstellt wurden) ist abhängig von der
angegebenen source-track-Option.
Eine Beispielregel:
pass in on $ext_if proto tcp to $web_server \
port www flags S/SA 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 von ,states', die diese Regel erstellen
kann, auf 200
- Aktiviere ,source tracking'; begrenze die Anzahl der
,state'-Erstellung nur für diese Regel
- Begrenze die maximale Anzahl von ,nodes', die gleichzeitig ,states'
Erstellen, auf 100
- Begrenze die maximale Anzahl von gleichzeitigen ,states' pro
Quell-IP auf 3
Ein separater Satz von Begrenzungen kann auf ,stateful' TCP-Verbindungen
gesetzt werden, die den dreifachen Handschlag vollzogen haben.
- max-src-conn Nummer
- Begrenzt die maximale Anzahl an gleichzeitigen 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 von Verbindungen pro Quelle auf 100
- Begrenzt die Rate der Anzahl von 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
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.
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.
Hinweis: in früheren Versionen von OpenSBD wurde die folgende Syntax
unterstützt:
. . . flags S
Dies gilt heute nicht mehr. Eine Maske muss nun immer angegeben
werden.
Flags werden oft in Verbindung mit keep state-Regeln verwendet,
um zu helfen, die Erstellung von ,state'-Einträgen besser kontrollieren
zu können:
pass out on fxp0 proto tcp all flags S/SA keep state
Dies würde das Erstellen eines ,states' für alle ausgehenden TCP-Pakete
mit gesetztem SYN-Flag erlauben, unter der Überprüfung von SYN- und
ACK-Flags.
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:
. . . 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 potentiell unklare Kombinationen (z. B. SYN und
FIN) zu normalisieren. Es wird dringend empfohlen, den eingehenden
Verkehr immer einem scrub zu unterziehen:
scrub in on fxp0
.
.
.
pass in on fxp0 proto tcp from any to any port ssh flags S/SA \
keep state
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 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.
,spoofed' Pakete blocken
Adress-,spoofing' 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, so dass 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.
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 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:
- Betriebssytem-,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"
# 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 das interne interface aktivieren.
antispoof quick for $int_if inet
# nur ssh-verbindungen vom lokalen netzwerk erlauben, wenn es von dem
# computer 192.168.0.15 kommt, dem man vertrauen kann. verwende
# ,block return', so dass 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 flags S/SA
# den gesamten verkehr von und zum lokalen netzwerk durchlassen
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.
# halte den ,state' für udp und icmp und ,modulate state' für tcp.
pass out on $ext_if proto tcp all modulate state flags S/SA
pass out on $ext_if proto { udp, icmp } all keep 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, so dass wir später sagen können, wer versucht, zu verbinden.
# verwende den tcp-syn-proxy um einen proxy für diese verbindung
# aufzubauen.
pass in log on $ext_if proto tcp from any to ! <firewall> \
port ssh flags S/SA synproxy state
|
[Zurück: Tabellen]
[Inhalt]
[Weiter: Network Address Translation]
www@openbsd.org
$OpenBSD: filter.html,v 1.20 2006/05/01 12:19:17 jufi Exp $