12.9 Die Programmierung von ipchains.
Zuerst sollte man die Versionsnummer von ipchains in Erfahrung bringen:
$ ipchains --version
ipchains 1.3.8, 27-Oct-1998
ipchains ist hervorragend dokumentiert. Insbesondere die Manpages sind sehr
ausführlich. (man ipchains) Wer mehr über das
Administrationswerkzeug wissen möchte, der sollte sich auch über ipfw
informieren man 4 ipfw), oder die Quellcodes im Kernel selber
einmal durchschauen, was aber Kenntnisse in der Programmiersprache
C erfordert. Die Datei ist: /usr/src/linux/net/ipv4/ip_fw.c
Insbesondere sei aber die Referenzkarte von Scott Pronson in dem Quellpaket
empfohlen, die im Postscript Format vorliegen.
Mit ipchains kann man verschiedenste Dinge regeln. Zuerst einmal
kann man die Regeln in drei verschiedenen chains managen:
input, output und forward. Letztere kann man
nicht löschen.
- Eine neue chain erzeugen (-N).
- Eine leere chain löschen (-X).
- Die Policy für eine eingebaute chain ändern (-P).
- Alle Regeln in einer chain listen (-L).
- Alle Regeln in einer chain löschen (-F).
- Alle Pakete und Paketzähler in der chain zurücksetzen (-Z).
Es gibt verschiedene Wege, eine Regel in einer chain zu verändern:
- Eine Regel an eine chain anfügen (append) (-A).
- Eine Regel in einer chain einfügen (insert) (-I).
- Eine Regel in einer chain ersetzen (replace) (-R).
- Eine Regel in einer chain löschen (delete) (-D).
- Die erste Regel, die zutrifft in einer chain löschen (-D).
Es gibt noch ein paar weitere Optionen für das Masquerading:
- Zeige die momentan maskierten Regeln an (-M -L).
- Setze Timouts auf maskierte Pakete (-M -S). (Hinweis:
I can't set masquerading timeouts!).
Die eventuell wichtigste Funktion erlaubt die Überprüfung der
Regeln, hierzu mehr später.
Aufsetzen einer Regel
Die am häufigsten verwendeten Befehle werden sicher das Anhängen und Löschen
von Regeln sein. Die anderen Befehle, wie das Einfügen und Ersetzen von
Regeln sind einfach nur Varianten.
Jede Regel definiert einen Satz von Bedingungen, die, wenn sie die Regel
erfüllen, angeben, wie mit dem Paket weiter zu verfahren ist.
127.0.0.1 ist per Definition das loopback interface, welches von
vielen UNIX Programmen immer dann benutzt wird, wenn kein Netzwerk- Interface
zur Kommunikation von Programmen untereinander zur Verfügung steht. Die
Programme binden sich normalerweise an alle Interfaces gleichzeitig. Der
Befehl ping sendet ein Paket vom Typ ICMP Nummer 8 (echo request),
worauf der Host mit einem ICMP Paket Typ 0 (echo reply) antwortet. Ein
Beispiel:
# ping -c 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.2 ms
--- 127.0.0.1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.2/0.2/0.2 ms
# ipchains -A input -s 127.0.0.1 -p icmp -j DENY
# ping -c 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes
--- 127.0.0.1 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
#
Man kann hier gut erkennen, daß das erste Ping ein einmaliges Paket
versendet, und ein Echo erscheint. Nach Programmierung des Kernels erscheint
kein Echo mehr.
Die Syntax des Befehls ist recht einfach: Füge an die input chain
eine Regel an, die Pakete mit dem Protokolls ICMP von der Quelladresse 127.0.0.1 verwirft.
Die Regel kann auf zwei Weisen wieder gelöscht werden. Zuerst kann die
Regel, die die erste und einzige in der chain ist, unter Angabe der Nummer
gelöscht werden.
# ipchains -D input 1
#
Die zweite Variante ist ein Löschen der Regel dadurch, daß man die Syntax
der Regel noch einmal wiederholt, nur diesmal aber nicht anfügt (-A) sondern
löscht (-D):
# ipchains -D input -s 127.0.0.1 -p icmp -j DENY
#
Existieren mehrere gleichlautende Regeln in der chain, so wird nur die erste
Regel gelöscht, als vorsicht mit dem mehrfachen Aufruf von Skripten.
Filter Spezifikationen
Es wurden bisher nur die Optionen -p und -s eingeführt. Um auch Dienste auf
Port- Ebene filtern zu können, sind zusätzliche Angaben notwendig. Genau hierum
dreht sich dieses längere Kompendium.
Filtern nach Quell - und Zieladresse
Die Quell (-s) und Ziel (-d) IP-Adressen können im Prinzip auf vier
verschiedene Arten erfolgen. Einmal können die IP-Adressen direkt als
Quadrupel von vier Zahlen zwischen 0 und 255 angegeben werden, wie
127.0.0.1, zum anderen kann der Name eingesetzt werden, wie z.B. localhost.
oder www.intra.net.
Der dritte und vierte Weg sind die Angaben der Netzwerk-Gruppen. Hier können
Adressen, wie 10.0.0.0/24 oder 192.168.0.0/8 gemacht werden. Die Angaben mit
einem /24 /16 oder /8 bezeichnen die signifikanten Bits (von rechts aus
gesehen). /24 bedeutet, daß die letzen 3 Zahlen variiert werden dürfen. also
alle IP - Nummern von 10.0.0.1 bis 10.254.254.254 verwendet werden dürfen, was
dann einem Class-C Netz entspricht. /16 bezeichnet ein CLASS-B Netzwerk, und
/8 ein CLASS-C Netzwerk mit 254 freien IP - Nummern. Die Bezeichnung /0 steht
für jede IP - Nummer.
# ipchains -A input -s 0/0 -j DENY
#
Alternativ kann dann auch die Angabe -s 0/0 entfallen.
Invertierung von Adressen
Vielen Flags, inklusive den Flags -s und -d kann ein "!" vorangestellt
werden, welches ein logisches nicht bedeutet. Dementsprechend
bezeichnet ein -s ! localhost, jedes Paket, welches nicht von dem
localhost stammt.
Filterung von Ports
Ein Protokolle kann mit dem -p Flag angegeben werden. Das Protokoll kann
entweder eine Zahl, oder eine Bezeichnung für ein Protokoll sein. Diese sind
in der Datei /etc/services angegeben. Beispiele sind ICMP, IGMP,
IPX, TCP, UDP.... Es wird intern nicht zwischen Groß- und Kleinschreibung
unterschieden.
Der Protokollname kann ebenfalls invertiert werden. Bezeichnungen, wie
-p ! TCP bezeichnen alle Protokolle, außer dem TCP Protokoll.
Filterung von Portbereichen
Für den Spezialfall, daß TCP oder UDP als Protokoll angegeben werden, kann
ein weiteres Argument angegeben werden, nämlich ein Bereich von
Ports. Siehe auch
Fragmentierte IP-Pakete.
Ein Bereich wird mit dem Zusatz 6000:6010 oder auch nur :1023 bezeichnet.
Die Syntax lautet dann -p TCP -s 0.0.0.0/0 :1023 für ein Paket,
welches als Quellport einen Port unterhalb von 1024 eingetragen hat.
Auch hier können die Portbereiche invertiert werden. Das Beispiel:
-p TCP -d 0.0.0.0/0 ! www
bezeichnet alle Ports, die nicht Port 80 entsprechen. Man sollte auch stets
auf die Position des Ausrufezeichens achten. Die Bezeichnung
-p TCP -d ! 192.168.1.1 www
unterscheidet sich von
-p TCP -d 192.168.1.1 ! www
Das erste Beispiel bezeichnet ein Paket, welches an alle Hosts auf Port 80,
außer dem bestimmten Host adressiert werden darf. Im zweiten Fall darf nur
dieser Host adressiert werden, aber nicht auf Port 80.
Zum Schuß bleibt noch die Klärung folgender Bezeichnung:
-p TCP -d ! 192.168.1.1 ! www
Dieses bezeichnet ein Paket, welches an alle Hosts außer dem bestimmten Host
adressiert werden darf, und dort auf alle Ports zugreifen darf, außer dem
Port 80. Generell gilt, daß alle Angaben, die hintereinander erfolgen, ein
logisches und implizieren.
Filterung von ICMP
ICMP besitzt zwar Optionen als Argument, diese bezeichnen aber keine
Portnummern, sondern beziehen sich auf Codes. Eine Invertierung, wie bei
obigen Protokollen, ist nicht erlaubt.
ICMP Codebezeichnungen sind recht lang, daher werden häufig nur die
Kurzbezeichnungen angegeben.
Number Name Funktion
0 echo-reply ping
3 destination-unreachable Router, Clients
5 redirect Router
8 echo-request ping
11 time-exceeded traceroute
Keinesfalls sollten alle ICMP Pakete in Firewalls gesperrt werden. Der Code
Nummer 3, destination unreachable ist ein unentbehrliches
Hilfsmittel für korrektes Routing. Es könnten so eventuell Leitungen
überlastet werden, insbesondere ISDN.
Die Zuordnung der Netzwerkkarte
Die Option -i ordnet eine Regel eindeutig einem Interface zu.
Im Gegensatz zu dem alten Firewall-Kernel ist es hier erlaubt, bereits eine
Regel für ein Interface zu definieren, bevor es überhaupt existiert. Diese
Eigenschaft erlaubt es, Regeln für ISDN-Interfaces aufzusetzen, ohne deren
IP - Nummer zu kennen. Das trifft insbesondere auf dial on demand
ISDN-Leitungen zu, deren IP - Nummer erst nach der Einwahl vergeben wird.
Bei der Bezeichnung der Interfaces sind auch wildcards erlaubt, wie
z.B. ippp+ oder ppp+ oder eth+.
Die Invertierung der Interface Bezeichnungen mit einem Ausrufezeichen ist
erlaubt. Dies bedeutet insbesondere, daß mit ! eth+ alle
Interfaces, außer den Netzwerkkarten gemeint sind. Die Regeln treffen dann
beispielsweise auf alle ISDN-Interfaces zu.
Filterung von TCP Paketen
Manchmal ist es sinnvoll, Verbindungen nur in eine Richtung zuzulassen. So
ist es die Regel, den Datenverkehr aus dem Intranet zu Servern im Internet
zuzulassen, ohne daß jedoch ein Angreifer aus dem Intranet Zugriff auf den
Host im Intranet hat.
Der naive User würde also alle TCP Pakete, die aus dem Internet an der
Firewall ankommen, verwerfen. Unglücklicherweise sollten nach einem
Verbindungsaufbau die Antwortpakete die Firewall passieren dürfen.
Die Lösung ist, nur Pakete zu sperren, die erforderlich sind, um eine
Verbindung aufzubauen. Diese haben per Definition das SYN Flag gesetzt. Alle
Antwortpakete haben das ACK Flag gesetzt. Die Firewall merkt sich also, ob
eine Verbindung von innen in das Internet initiiert wurde, und ob
Antwortpakete zurück erwartet werden.
Die Option -y ist genau für diesen Zweck bestimmt worden. Diese
Option ist nur und ausschließlich bei TCP Protokollen möglich und sinnvoll:
-p TCP -s 192.168.1.1 -y
Hier werden alle TCP Pakete zugelassen, die von dem internen Host
192.168.1.1 ausgehen, und an beliebige Hosts im Internet adressiert sind.
Für diesen Host werden dann Antwortpakete aus dem Internet zurück erwartet.
Ein direkter Zugriff aus dem Internet auf den Host im Intranet ist nicht
möglich.
Auch hier kann der Sinn der Option logisch invertiert werden. Ein
vorangestelltes Ausrufezeichen, wie hier im Beispiel:
-p TCP -s 192.168.1.1 ! -y
besagt, daß alle Hosts aus dem Internet auf den Host im Intranet zugreifen
dürfen, von diesem aber keine Verbindung zu einem Host in das Internet
aufgebaut werden darf. Das macht immer dann einen Sinn, wenn z.B. ein
Datenbankserver im Internet gesichert werden soll. Für den Fall, daß es
einem Angreifer gelungen ist, mit einem buffer overflow an eine Rootshell
unter UNIX zu gelangen. Will er nun mit einer FTP-Verbindung die Daten
entführen, so wird dies von der Firewall unterbunden. Der Angreifer muß also
noch erhebliche Mühen investieren. Die Firewall hätte den Entführungsversuch
dann aber bereits registriert.
IP-Fragmente
In vielen Fällen ist ein Paket zu groß, um direkt von dem Interface
aufgenommen werden zu können. Daher wird es in kleine Fragmente aufgeteilt
und versendet. Am anderen Ende müssen diese Fragmente wieder
zusammengesetzt, also reassembliert werden, wie es in Fachsprache heißt.
Es gibt eine Reihe von Angriffsvarianten, die auf verschachtelten,
IP-Fragmenten mit verschiedenen Offsets beruhen. Um diese Angriffe zu
verhindern, ist es unerläßlich, daß der der Kernel diese IP-Fragmente vor
der Weiterleitung an die Filter vollständig reassembliert. Bei der
Kompliation des Kernels ist also beim Aufbau einer Firewall strengstens
darauf zu achten, daß die Option: IP: always defragment aktiviert
wird. Beim Einsatz als Router oder Switch wird sich diese Option negativ
auf die Performance aus.
Dieser Tatsache wird in den Filterregeln Rechnung getragen. Das erste
Fragment trägt den Header mit allen Informationen über IP-Adresse, Ports,
Flags, Protokoll.....Alle weiteren Pakete sind für die Firewall nicht
zuzuordnen und werden daher generell abgelehnt. Falls es also Probleme mit
der Übertragung von Paketen kommt, ist die fehlende Defragmentierung auf der
IP-Ebene die Ursache.
Es ist aber möglich, mit Hilfe des -f flag Regeln für TCP Pakete
ohne SYN-Flag das Passieren der Firewall zu erlauben. Dies kann insbesondere
dann der Fall sein, wenn die Firewall als Router oder als Firewall-Switch eingesetzt wird.
Eine Invertierung mit dem Ausrufezeichen ist für die Option -f
erlaubt.
Short Frames, oder auch malformed packets werden vom Kernel als
Fragmente behandelt. Diese können auch bei defekten Netzwerkkarten
auftreten. Hier werden Logeinträge vorgenommen, also Vorsicht bei der
Interpretation dieser Einträge.
Folgendes Beispiel beschreibt eine Firewallregel, die alle Fragmente
verwirft, die als Zieladresse die interne IP - Nummer 192.168.1.1 beinhalten.
ipchains -A output -f -D 192.168.1.1 -j DENY
Pakete, die über große Strecken aus dem Internet an z.B. die Firewall
herangetragen werden, sind häufig fragmentiert. Pakete aus der unmittelbaren
Nähe sind niemals fragmentiert. Ein Angreifer, der sein Glück mit
verschachtelten Fragmenten versucht, wird aus Gründen des exakten Timings
immer versuchen, diese von einem Host aus nächster Nähe zu generieren, z.B.
direkt von dem Bastion host in der DMZ. Aufgrund der Zuordnung IP-Adresse zu
fragmentierten Paketen läßt sich direkt ablesen, ob ein solcher Angriff
stattfindet, oder ob es nur ein gewöhnliches Paket aus dem Internet ist.
Zugegeben, die Erstellung der Regeln ist nicht gerade trivial, aber es ist
unerläßlich, diese Angriffsmethoden zu kennen, wenn man es mit Profis zu tun bekommt.
|