Kapitel 3:

Firewalls unter Linux



Firewalls sind vielleicht die wichtigsten Tools zur Absicherung von Netzwerken oder PCs gegen Angriffe aller Art. Eine Firewall arbeitet nach dem Prinzip eines Paketfilters, dass heißt jedes Datenpaket wird untersucht und, falls Gefahr droht, geblockt. In diesem Kapitel erkläre ich grundlegende Konzepte für Paketfilter-Firewalls und wie Firewalls gestaltet und installiert werden.


 

      Zurück zur Inhaltsangabe

      3.1 Grundlegende Erklärungen - Ports und Pakete

      3.2 Konzepte für Paketfilter

      3.3 Gestaltung und Installation einer Firewall





3.1 Grundlegende Erklärungen


Ports identifizieren netzwerkbasierende Programme auf einem Computer, auf die andere17 Computer über das Netzwerk zugreifen können. Es sind also numerische Namen für die unterschiedlichen Netzwerkdienste. Die Port-Zahlen liegen im Bereich von 0 bis 65535. Server-Programme warten auf dem ihnen zugewiesenen Port auf eingehende Verbindungen. Den wichtigsten davon wurden die Ports im Bereich von 1 bis 1023 zugewiesen, die sogenannten Privilegierten Ports. Webserver sind z.B. immer dem Port 80 zugeordnet. Wenn man also in einem Browser einen Host als Adresse eingibt, wird man automatisch mit Port 80 verbunden. Läuft auf dem Zielhost aber kein Webserver, gibt es keinen Port 80 und man erhält eine Fehlermeldung, dass der gewünschte Dienst nicht angeboten wird. Diese Ports sind aber keine Garantie dafür, dass man mit dem gewünschten Dienst verbunden wird. Man kann nie absolut sicher sein, dass das Programm am anderen Ende wirklich das ist, für das es sich ausgibt.


Die Internet Assigned Numbers Authority (IANA) ist für das Reservieren von Ports zuständig. Sie hat auch einige der oberen, unprivilegierten Ports registriert, z.B. für den X-Window-Server.


Ein Paket ist eine einzelne Nachricht oder Informationseinheit, die über das Internet Protocol (IP) läuft. Es enthält einen Informationskopf oder Header und den eigentlichen Nachrichtentext oder Body. Ein IP-Paket kann entweder eine komplette Nachricht eines übergeordneten Protokolls oder ein Fragment davon sein. Im Header eines Pakets befindet sich immer die Absender- und die Empfänger-IP, je nach Typ auch eventuell die Ports der beiden Computer und oft auch noch zusätzliche Informationen.


Wichtig sind vor allem drei IP-Nachrichtentypen: ICMP, UDP und TCP:


Ein ICMP-Paket (Internet Control Message Protocol) stellt eine Kontroll- oder Statusnachricht dar. Es enthält Informationen über die Kommunikation zwischen zwei Computern. Ein Beispiel dafür wäre eine Fehlermeldung.


Ein UDP-Paket (User Datagram Protocol) transportiert Daten zwischen 2 Programmen. Dabei ist allerdings nicht garantiert, ob das Paket tatsächlich ankommt und ob die richtige Reihenfolge der Pakete während der Übertragung beibehalten wird. Ein Beispiel dafür wäre das Network Time Protocol, mit dem die aktuelle Uhrzeit von einem Server abgefragt werden kann.


Statt UDP werden aber meist TCP-Pakete verwendet (Transmission Control Protocol). Der Header so eines Paketes enthält zusätzliche Informationen , die die Aufrechterhaltung einer kontinuierlichen und verlässlichen Verbindung ermöglichen. Zusätzlich zu den in 2.5, Spoofing erwähnten Sequenznummern sind bei einer TCP-Verbindungen auch noch die SYN- und ACK-Flags erwähnenswert. Diese Flags beschreiben den Zustand der Verbindung. Wenn der Client das erste Paket des Verbindungsaufbaus abschickt, ist darin das SYN-Flag enthalten. Der Server schickt darauf eine Bestätigung (ACK) der SYN-Nachricht zurück, zusammen mit einer eigenen Synchronisationsaufforderung (SYN). Die Verbindung ist jetzt halb-offen. Der Client bestätigt den Erhalt dieses Paketes wieder mit einem ACK-Flag. Ab jetzt sind die beiden Computer synchronisiert und es werden nur mehr ACK-Flags ausgetauscht, da keine Synchronisationsaufforderungen mehr gebraucht werden.


Um die Arbeitsweise von Firewalls im Folgenden etwas einfacher erklären zu können, will ich kurz auf das TCP/IP-Referenzmodell eingehen: Man kann die Kommunikation zwischen zwei Computern in vier verschiedene Schichten*) teilen: Als Oberstes steht die Anwendungsschicht, hier läuft die Client - und Serversoftware. „Darunter“ befindet sich die Transportschicht. Hier findet der Nachrichtenaustausch von Programm zu Programm statt und Daten, die verschickt werden sollen, werden von den TCP- bzw. UDP-Protokollen in Pakete „verpackt“. Auch Ports haben hier ihren Sitz. Die nächst-tiefere Schicht wird Netzwerk- oder Vermit- tlungsschicht genannt. Die Kommunikation zwischen Absender- und Empfänger-Computer wird hier abgewickelt. Diese Schicht ist auch der Ursprung von IP-Adressen und ICMP-Nachrichten. Zu unterst befindet sich die Subnetz-Schicht, wo die physikalische Übertragung von Signalen stattfindet. Diese Schicht besteht also aus Übertragungsmedien wie Kabeln oder Funk.



 

 

3.2 Konzepte für Paketfilter



Wie in Kapitel 2 schon besprochen, kann man mit Scans an wichtige Informationen18 kommen, ohne dass man mehr macht als nur Pakete zu versenden. Mit Denial-of-Service Angriffen kann man auf die ähnliche Art sogar erheblichen Schaden verursachen. Um das zu verhindern, verwenden Paketfilter-Firewalls eine Liste von Annahme- und Ablehnungskriterien. Diese Regeln definieren ganz genau, welche Pakete durch das Netzwerkinterface hindurch dürfen und welche nicht. Dabei werden die Informationen im Header eines Paketes, also z.B. Herkunfts-IP, als Kriterium verwendet, ob Pakete angenommen oder abgewiesen werden. Die Informationen im Body eines Paketes können von Paketfiltern nicht verwendet werden. Auf das TCP/IP-Netzwerkmodell bezogen, arbeiten Paketfilter also auf der Netzwerk- und der Transportschicht. Die Bezeichnung Firewall kann zwar auch für Gateways oder Proxy-Server verwendet werden, meistens versteht man darunter aber eine Paketfilter-Software, und so ist der Ausdruck im Rahmen dieser Arbeit auch zu verstehen.


Eine Firewall filtert Input- und Output-Daten separat, es können also völlig unterschiedliche Regeln gelten. Diese Regellisten werden als Chains (= Ketten) bezeichnet, da jeweils eine Regel nach der anderen abgearbeitet wird.


Es gibt zwei grundsätzlich unterschiedliche Strategien, wie man Firewalls implementiert:


Anfangs ist die erste Lösung sicher einfacher zu implementieren, die zweite Methode ist aber weitaus sicherer, obwohl man sicher einige Arbeit damit haben wird, jeden benutzten Dienst extra zu erlauben. Es ist aber auch zu beachten, dass man, um mit der ersten Lösung eine Ähnliche Sicherheit wie mit der zweiten zu erreichen, jeden Zugriff , den man verhindern möchte, explizit angeben muss. Hier ist also der Zeitaufwand im Wahrheit noch größer.


Es gibt grundsätzlich drei Möglichkeiten, wie mit einem Paket verfahren kann: Man kann es akzeptieren (ACCEPT), es ablehnen (REJECT) und verwerfen (DENY). Bei REJECT wird eine ICMP-Fehlermeldung an den Absender geschickt, bei DENY wird es kommentarlos verworfen. Da REJECT verwendet werden kann, um Informationen zu erhalten oder sogar einen DoS herbeizuführen, ist DENY fast immer die bessere Wahl.


Es ist zwar auch möglich, abgehende Pakete zu filtern, weitaus wichtiger ist jedoch das untersuchen der ankommenden Nachrichten. Deshalb will ich mich hier damit beschränken:


Filtern nach Absender-IP

Wie bereits in 2.5, Spoofing, besprochen, können Absender-IPs leicht gefälscht werden. Folgende Adressen sind sicherlich gefälscht, da sie entweder reserviert sind oder zu anderen Zwecken gebraucht werden, sicher aber nicht zur Kommunikation zwischen Computern:



Zusätzlich sollten natürlich Zugriffe von bekannten Übeltätern gesperrt werden.


Für bestimmte Dienste sollte der Zugriff nur einigen Ausgewählten IPs ermöglicht werden, z.B. beim Abholen von Mails, SSH oder finger. Bei anderen Programmen wie Webserver oder FTP sollte aber grundsätzlich jeder Zugriff haben.


Filtern nach Absender-Port

Der Absender-Port ist abhängig von dem Programm auf dem anderen Computer, dass das Paket erzeugt hat. Alle eingehenden Verbindungen fremder Clients auf Server am eigenen Computer sollten eine Port-Nummer zwischen 1024 und 65536 haben. Antworten fremder Server müssen einen Absender-Port haben, der dem benutzten Dienst entspricht, also z.B. 80 von http oder 22 für SSH.


Filtern nach Empfänger-Port

Bei eingehenden Verbindungen fremder Clients muss die Empfänger-Portnummer wieder dem gewünschten Dienst entsprechen. Antwortet dagegen ein fremder Server auf eine Anfrage, sollte der Empfänger-Port im unprivilegierten Bereich liegen.


Filtern nach TCP-Status-Flags

Wenn ein fremder Client eine Verbindung aufbaut, ist im ersten Paket das SYN-Flag gesetzt, das ACK-Flag jedoch nicht. Danach kommen nur noch Pakete mit ACK-Flags. Es sollten also hier beide Flags akzeptiert werden.


Ein fremder Server hingegen wird immer auf ein Paket antworten, es muss also ein ACK-Flag enthalten sein.


Auf diese Weise können viele Arten der in den vorigen Kapiteln besprochenen Angriffe verhindert werden, z.B. ping-Flooding oder andere DoS-Attacken.


Wie schon oft erwähnt, sollte jeder Netzwerkdienst, der nicht unbedingt benötigt wird, deaktiviert werden. Dienste, die angeboten werden müssen, sollten mit einer Firewall auf bestimmte Zugriffe beschränkt werden.


Eine gute Übersicht über die wichtigsten Netzwerkdienste findet man im Buch „linux firewalls“ (siehe Anhang D, Informationsquellen) Kapitel 2.6.2, Auswahl der Dienste.



3.3 Gestaltung und Installation einer Firewall


Jede größere Linux-Distribution enthält eine Firewall names IPFW (IP FireWall). Diese19 Firewall wir mit einem Programm names ipchains verwaltet, mit dem man Regeln aufstellen kann, wie mit welchen Paketen zu verfahren ist.


Die ipchains-Optionen:

ipchains

-A | -I [Chain]

[-i Interface]

[-p Protokoll]

[[!] -y]

[-s Adresse [Port[:Port]]]

[-d Adresse [Port[:Port]]]

-j Policy

[-l]


Option

Beschreibung

-A [Chain]

Hängt eine Regel ans Ende einer Chain an. Folgende Chains sind möglich: input, output oder forward (weiterleiten). Wird keine Chain angegeben, gilt die Regel für alle Chains.


-I [Chain]

Wie -A, die Regel wird aber am Anfang der Chain eingefügt.


-i Interface

Netzwerk-Interface, für das die Regel gilt. Wenn nichts angegeben, gilt die Regel für alle Interfaces. Typisch sind eth0, eth1 oder lo


-p Protokoll

IP-Protokoll, für das die Regel gilt. Wenn die Option nicht benutzt wird, gilt sie für alle Protokolle. Möglich sind tcp, udp, icmp und all.


-y

Das SYN-Flag muss gesetzt, das ACK-Flag darf nicht gesetzt sein -> Das Paket ist also das erste eines Verbindungsaufbaus.


! -y

Das ACK-Flag muss gesetzt sein, es handelt sich also bereits um eine Antwort auf ein TCP-Paket. Ist weder -y noch ! -y gesetzt, werden TCP-Flags nicht überprüft.


-s Adresse [Port]

Absender Adresse des Pakets (optional). Zusätzlich kann auch noch ein Port oder ein Portbereich (z.B. 1024:65535) angegeben sein. Ein Port kann aber nicht ohne Adresse angegeben sein


-d Adresse [Port]

So wie -s, hier muss aber die Empfänger-IP angegeben sein (optional).


-j Policy

Was mit dem Paket geschehen soll: ACCEPT, REJECT oder DENY. In der forward-Chain ist auch MASQ (Verbergen) erlaubt.


-l

Wenn diese Option gesetzt ist, wird jedesmal, wenn die Regel zutrifft, eine Meldung in der Datei /var/log/messages gespeichert.


Um mehrere Regeln zu definieren, muss man das Programm für jede Regel extra aufrufen. Um das zu vereinfachen, bedient man sich eines Scriptes, das jeden dieser Aufrufe automatisch durchführt.


Um die Angabe von IP-Adressen zu erleichtern, kann man mit Hilfe von Bitmasken ganze Adressenbereiche angeben: Eine IP-Adresse ist eine 32-Bit-Zahl, aufgeteilt in vier Bytes zu je acht Bit, also vier Zahlen von 0 bis 255. Eine Bitmaske besteht aus einer Zahl, die man nach einem / an die IP-Adresse anhängt. Sie gibt die Stelle der IP an, bis zu der die IP stimmen muss. Zum Beispiel: 192.168.25.46/16 gibt einen IP-Bereich von 192.168.0.0 bis 192.168.255.255 an, da die IP-Adresse nur bis zum 16. Bit stimmen muss, d.h nur 192.168. ist relevant.


Das folgende Beispiel habe ich von der Seite http://linux-firewall-tools.com/, der Originalautor heißt Robert Ziegler. Ich habe das Script übersetzt und etwas angepasst. Aufgrund der Länge des Scripts ist es aber leider nicht möglich, den gesamten Text in dieser Arbeit abzudrucken, geschweige denn zu beschreiben. Deshalb sind im folgenden nur einige Ausschnitte zu finden, das gesamte, kommentierte Script kann man aber unter http://joschi.scharl.at/linux/rc.firewall downloaden.


Die erste Zeile eines Scripts muss immer den Pfad zum Interpreter beinhalten - in diesem Fall zur Shell, da es sich ja um ein Shell-Script handelt:


#!/bin/sh


Um die Lesbarkeit und die Benutzerfreundlichkeit zu erhöhen, sollte man Konstanten definieren, die man später statt nichtssagenden IP-Adressen oder Portnummern benutzen kann:


# DIESEN ABSCHNITT AN EIGENES SYSTEM UND PROVIDER ANPASSEN!


EXTERNAL_INTERFACE="eth0" # Interface zum Internet

LOOPBACK_INTERFACE="lo" # Loopback

LAN_INTERFACE_1="eth1" # internes LAN-Interface


IPADDR="meine.ip.addresse" # eigene IP-Adresse

LAN_1="192.168.1.0/24" # Adressbereich im LAN

LAN_IPADDR_1="192.168.1.1" # Adresse des internen Interface

ANYWHERE="any/0" # Synonym für jede IP Adresse

LOOPBACK="127.0.0.0/8" # reservierter Loopback-Bereich

CLASS_A="10.0.0.0/8" # private Netzwerke Klasse A

CLASS_B="172.16.0.0/12" # private Netzwerke Klasse B

CLASS_C="192.168.0.0/16" # private Netzwerke Klasse C

CLASS_D_MULTICAST="224.0.0.0/4" # Multicast-Adressen Klasse D

CLASS_E_RESERVED_NET="240.0.0.0/5" # reservierte Adressen Klasse E

BROADCAST_SRC="0.0.0.0" # Broadcast Absender

BROADCAST_DEST="255.255.255.255" # Broadcast Empfänger


PRIVPORTS="0:1023" # privilegierte Ports

UNPRIVPORTS="1024:65535" # unprivilegierte Ports


Als nächstes muss man die vorbestehenden Regeln löschen und die neue Standard-Policies setzen, in diesem Beispiel werden standardmäßig alle Input-Pakete verweigert und Output- sowie Forward-Pakete nicht weitergeleitet, aber eine Fehlermeldung zurückgeschickt:


# Vorherbestehende Regeln löschen

ipchains -F

# Voreinstellung

ipchains -P input DENY

ipchains -P output REJECT

ipchains -P forward REJECT


Diese Firewall lehnt grundsätzlich jedes Paket ab. Jeder Dienst, der aber funktionieren sollte, muss nun explizit erlaubt werden. Bei den Regelketten wird aber die erste Regel, auf die das Paket zutrifft, ausgeführt. Man sollte also am Anfang alle möglichen gespooften oder illegale Adressen herausfiltern (hier: die eigene IP, außerdem sollten externe Pakete von Netzwerken der Klassen A, B, C, D, E und Loopback-Adressen verweigert werden):


# eigene IP:

ipchains -A input -i $EXTERNAL_INTERFACE -s $IPADDR -j DENY -l


Hier werden z.B. abgehende SSH-Verbindungen wieder explizit erlaubt, abgehende Pakete (vom Client) nur von unprivilegierten Ports zu Port 22, ankommende Pakete (vom Server) nur von Port 22 an einen unprivilegierten Port, das ACK-Flag muss gesetzt sein:


pchains -A output -i $EXTERNAL_INTERFACE -p tcp \

-s $IPADDR $UNPRIVPORTS \

-d $ANYWHERE 22 -j ACCEPT


ipchains -A input -i $EXTERNAL_INTERFACE -p tcp ! -y \

-s $ANYWHERE 22 \

-d $IPADDR $UNPRIVPORTS -j ACCEPT


ipchains -A output -i $EXTERNAL_INTERFACE -p tcp \

-s $IPADDR $SSH_PORTS \

-d $ANYWHERE 22 -j ACCEPT


ipchains -A input -i $EXTERNAL_INTERFACE -p tcp ! -y \

-s $ANYWHERE 22 \

-d $IPADDR $SSH_PORTS -j ACCEPT


Man kann auch Zugriffsversuche auf Ports, deren Dienste man nicht anbietet, aufzeichnen lassen:


# finger und WWW auslassen

ipchains -A input -i $EXTERNAL_INTERFACE -p tcp \

-d $IPADDR 81:109 -j DENY -l


Da die Firewall per Voreinstellung ohnehin alle Pakete verwirft, kommen auch Broadcast-Adressen nicht durch die Firewall und müssen - falls erwünscht - explizit erlaubt werden.


Wie man sich vorstellen kann, wächst ein kommentiertes Script dieser Art auf einige Dutzend Seiten an, ich möchte also nochmals auf das vollständige Script unter http://joschi.scharl.at/linux/rc.firewall verweisen.


Die Installation des Scripts ist einfach: Am besten man speichert es unter /etc/rc.d/rc.firewall und setzt es per chown auf 700 für root.


Bei einer statischen IP-Adresse kann man einfach in der Datei /etc/rc.d/rc.local die folgende Zeile dazuhängen:


sh /etc/rc.d/rc.firewall


Bei dynamisch zugewiesenen IPs ist die Sache etwas komplizierter, da man ja auch die Konstante $IPADDR nicht fix definieren kann. Bei Modemverbindungen muss man z.B. statt in rc.local folgende Zeile in die Datei /etc/ppp/ip-up einfügen:


/etc/rc.d/rc.firewall $4


Die Konstantendefinition von $IPADDR in rc.firewall muss dann wie folgt aussehen:


IPADDR=$1


Bei per DHCP-zugewiesenen IPs ist die Konstantendefinition genauso durchzuführen, das Script von dem aus die Firewall aufgerufen wird, ist jedoch von Distribution zu Distribution unterschiedlich. Bei Red Hat muss z.B. die folgende Zeile an /etc/pump.lease angehängt werden:


/etc/rc.d/rc.firewall $3


Somit wird die Firewall bei jedem Mal Booten automatisch gestartet und das System ist optimal geschützt.

 

*)Die Bezeichnungen für die Schichten stammen aus dem Buch „linux firewalls“ (siehe Anhang D). Das Bild ist ebenfalls aus diesem Buch.

17linux firewalls, von Robert Ziegler, erschienen bei Markt und Technik, Kapitel 1 - Gundlegende Konzepte für Paketfilter-Firewalls


18linux firewalls, von Robert Ziegler, Kapitel 2 - Konzepte für Paketfilter


19linux firewalls, von Robert Ziegler, Kapitel 3 - Gestaltung und Installation einer Firewall

Hali Tower, Darkover; URL: http://linux-firewall-tools.com/


Weiters:

Hypertext Glossar informatikbezogener Abkürzungen und ausgewählter Begriffe

URL: http://me.in-berlin.de/~surveyor/perls/cshg-suchen.cgi

Weiter zu den Anhängen