Private Feuerwände

Paketfilter-Firewall

Eine Firewall kontrolliert, welche Daten Ihren Computer passieren. Sie überwacht ankommende ebenso wie abgehende Pakete. So verhindert sie einerseits den Zugriff fremder Personen auf Ihr System. Gleichzeitig schützt sie vor Fehlern der eigenen Software sowie vor unerwünschten Programmen: Auch der eigene Computer muss sich an die Regeln halten. Der Informationsfluss wird so in beiden Richtungen reglementiert.

Dank der exzessiven Konfigurationsoptionen der Linux-eigenen Firewall-Mechanismen haben Sie alle Möglichkeiten zur beliebig exakten Abdichtung Ihres Systems. Leider heißt das auch, dass eine wirklich sichere Firewall gar nicht so einfach zu bekommen ist.

Wie arbeitet eine Firewall?

Wenn ein Computer Daten mit anderen Rechnern austauscht, verpackt er sie immer in Paketen. Die im Linux-Kernel eingebaute Firewall-Funktionalität sieht sich jedes dieser Pakete an und entscheidet anhand bestimmter Kriterien, was mit ihm geschehen soll. Im überwiegenden Fall wird sie es ganz normal annehmen und an die zuständige Stelle weiterleiten (auf Befehlsseite heißt das ACCEPT), alternativ kommt das Verwerfen eines unerwünschten Paketes (DROP) in Betracht. Eine ganze Reihe zusätzlicher Aktionen sind vor allem für fortgeschrittene Anwender interessant.

Die Firewall selbst besteht aus zahlreichen Regeln, die nacheinander abgearbeitet werden. Jedes Datenpaket wird wie in einer Checkliste mit ihnen verglichen. Die erste passende Regel entscheidet, was mit ihm geschieht.

Für die Entscheidung, ob ein Paket akzeptabel ist oder nicht, können Sie in den Firewall-Regeln verschiedene Parameter abfragen. Die wichtigsten sind das verwendete IP-Protokoll (zum Beispiel TCP, UDP oder ICMP), die IP-Adressen von Absender und Empfänger, die Port-Nummern und das Netzwerk-Interface, über das ein Paket empfangen beziehungsweise verschickt wird.

Exkurs: IP-Protokolle

Jedes der über IP abgewickelten Protokolle hat seine Besonderheiten. In welchem Verhältnis sie zu den Protokollen der Anwendungsebene stehen, zeigt Abbildung 1. Dieses Wissen benötigen wir für die Konstruktion der Firewall.

Abbildung 1

Abbildung 1: IP-Protokolle

Das "Transmission Control Protocol" (TCP) zählt momentan zu den meistgenutzten Protokollen; fast alle klassischen Internet-Dienste verwenden es. TCP kennt den Begriff der Verbindung, die vor der Übertragung aufgebaut und hinterher wieder abgebaut werden muss. Innerhalb einer bestehenden Verbindung garantiert TCP die Integrität der Daten: Falls einzelne Pakete verloren gehen, werden sie automatisch nochmal übertragen. Auch sortiert TCP die Daten richtig, bevor es sie an die Anwendung übergibt.

Für eine Firewall ist TCP insofern praktisch, als man den Aufbau einer Verbindung anhand spezieller Flags im Kopf eines Paketes sehr leicht erkennen kann. So lassen sich Datenströme beurteilen: Gehören sie zu einer Datenübertragung, die durch ein eigenes Client-Programm initiiert wurde, zum Beispiel durch Netscape? Oder versucht jemand aus dem Internet einen (vermutlich unerwünschten) Zugriff auf unseren Computer?

Mit dem "User Datagram Protocol" (UDP) werden einzelne Datenpakete von einem Computer zum anderen verschickt. Die beteiligten Programme identifizieren sich durch Port-Nummern. Bei UDP gibt es keine langwierige Aushandlung einer Verbindung; Pakete können sofort verschickt werden. Damit eignet sich das Protokoll sehr gut für Anwendungen, bei denen es auf die Performance ankommt, beispielsweise vernetzte Dateisysteme oder Multimedia-Übertragungen.

Der Nachteil: Pakete können bei diesem Protokoll verloren gehen; ebenso ist die Reihenfolge, in der die Pakete beim Empfänger ankommen, undefiniert. Das Anwendungsprogramm darf sich also nicht auf vollständige Datenintegrität verlassen beziehungsweise muss dafür eigene Mechanismen implementieren. Auch für die Firewall hat UDP Nachteile: Bei ankommenden Paketen ist primär unklar, ob sie eine Reaktion auf eine lokale Anfrage darstellen oder ob ein Fremder einen Zugriff versucht.

Das "Internet Control Message Protocol" (ICMP) ähnelt UDP insofern, als immer nur einzelne Pakete übertragen werden. Allerdings dient ICMP praktisch nie dem Versand von Nutzerdaten; stattdessen transportiert es Statusinformationen über das Netzwerk oder Fehlermeldungen. Umso wichtiger ist es, dass eine korrekt arbeitende Firewall auf ICMP-Pakete eingeht.

Designfragen

Beim Design sicherheitsrelevanter Algorithmen – also auch einer Firewall – gibt es immer zwei diametral entgegengesetzte Ansätze: Beim ersten versucht man, unerwünschte Ereignisse zu erkennen und auszuschalten, und erlaubt alles andere.

Diese Methode ist nicht nur ziemlich weit verbreitet, sondern auch außerordentlich gefährlich: Vergisst man ein unerwünschtes Ereignis, ist es durch die Voreinstellung erlaubt. Das gilt auch für Angriffe, die man zum Zeitpunkt des Firewall-Designs noch gar nicht kennt, und das sind schließlich die eigentlich gefürchteten! (Bekannte Sicherheitslücken sollte man so möglich ohnehin korrigieren.)

Jede sinnvolle und sichere Sicherheitslösung folgt daher dem zweiten Weg: Ein unbekanntes Ereignis ist immer verboten; ein unbekanntes Paket wird nicht angenommen. Alles, was erlaubt ist, muss explizit definiert werden.

Das bringt einen riesigen Nachteil mit sich: Solange eine neu entwickelte Firewall unvollständig oder fehlerhaft ist, funktioniert der Netzwerkzugriff nicht vernünftig. Jedes neue Anwendungsprogramm, das ein neues Netzwerkprotokoll verwendet, muss in der Firewall erst einmal aktiviert werden. Für diese Mühen erhält man jedoch ein recht zuverlässig abgeschirmtes System.

Bei Linux-Firewalls werden diesen beiden Prinzipien durch Policies umgesetzt. Die im Folgenden vorzustellende Lösung verwendet eine DROP-Policy und verwirft somit alle unbekannten Pakete. Firewall-Regeln definieren wir für alle von uns verwendeten Protokolle so, dass die entsprechenden Pakete durch eine ACCEPT-Regel angenommen werden.

Kernel-Tuning

Eine ganze Reihe von Kernel-Parametern beeinflusst das Verhalten Ihres Linux-Systems im Umgang mit IP-Paketen. Streng genommen gehört das zwar nicht zur Firewall-Funktionalität; trotzdem passt es ganz gut hierher.

Diese Variablen sind über das so genannte sysctl-Interface zugänglich: Besondere Dateien in /proc/sys/net/ipv4 zeigen die aktuelle Konfiguration beziehungsweise erlauben Modifikationen. Zum Auslesen der momentan gültigen Einstellungen lassen Sie sich die Dateien mit cat anzeigen. Neue Werte speichern Sie einfach in der entsprechenden Datei ab. Im Allgemeinen aktivieren Sie ein Feature, indem Sie eine 1 in die entsprechende Datei schreiben; 0 schaltet es wieder aus.

Für uns sind folgende Einstellungen besonders wichtig:

conf/*/accept_source_route regelt den Umgang mit Paketen, deren Routing-Weg vom Absender festgelegt wurde. Diese IP-Option ist im Allgemeinen unerwünscht. (Der * steht für die einzelnen Verzeichnisse unterhalb von /proc/sys/net/ipv4/conf. Sie steuern die verschiedenen Netzwerk-Interfaces Ihres Computers und setzen Voreinstellungen. Soll eine Änderung für alle Interfaces gelten, schreiben Sie sie in alle gleichnamigen Dateien.)

  • conf/*/accept_redirects legt fest, ob Linux fremden Systemen die Änderung der eigenen Routing-Tabellen gestattet.
  • icmp_echo_ignore_broadcasts unterbindet die Reaktion auf pings, die an alle Rechner in einem Netzwerk verschickt werden. Einen Schritt weiter geht icmp_echo_ignore_all, das alle ping-Pakete ignoriert. Natürlich ließe sich ein ähnliches Verhalten erreichen, indem man entsprechende Firewall-Regeln definiert.
  • tcp_syncookies schaltet einen Schutzmechanismus ein, der einen Angriff durch unzählige gefälschte Verbindungsanfragen erschwert. * ip_forward entscheidet, ob der Kernel Pakete an andere Rechner weiterleitet oder nur als Endknoten agiert. Diese Option ist für den Aufbau eines privaten LANs mit Linux als Router wichtig.
  • icmp_ratelimit, tcp_fin_timeout, tcp_max_orphans und tcp_max_syn_backlog sind Beispiele für zusätzliche Schutzmechanismen, die in erster Linie Denial-of-Service-Angriffe erschweren, also einem Angreifer die Erschöpfung unserer Systemressourcen verwehren. Das Tuning dieser Parameter kann auch für große Serversysteme hilfreich sein.

In der Firewall könnte man die Kernel-Parameter beispielsweise mit folgendem Fragment setzen:

for i in /proc/sys/net/ipv4/conf/*/{accept_source_route,accept_redirects,send_redirects}; do
  echo 0 >$i
done
echo 1 >/proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
echo 1 >/proc/sys/net/ipv4/ip_forward
echo 1 >/proc/sys/net/ipv4/tcp_syncookies

Die Netfilter-Firewall in Linux 2.4

Die folgenden Erklärungen beziehen sich ausdrücklich auf den so genannten Netfilter aus Linux 2.4. Die Kernel der 2.0- und 2.2-Serien benutzen mit IPFW (ipfwadm beziehungsweise ipchains) einen teilweise deutlich anderen Firewall-Mechanismus.

Eine Netfilter-Firewall kann drei verschiedene Tabellen verwenden: filter enthält die eigentlichen Firewall-Regeln; nat kann Absender und Empfänger von Paketen ändern; mangle erlaubt zusätzliche Modifikationen für Spezialzwecke. Praktisch alle für uns interessanten Regeln gehören in die filter-Tabelle. Da diese voreingestellt ist, werden wir sie nicht jedesmal extra angeben.

Innerhalb jeder Tabelle gibt es verschiedene Chains oder Ketten. Je nachdem, woher ein Paket kommt und wohin es geht, wird nur eine davon darauf angewendet. Abbildung 2 zeigt die Chains der filter-Tabelle, die für ein Einzelplatzsystem relevant sind. (Kasten 3 behandelt die Besonderheiten eines lokalen Netzwerks.)

Abbildung 2

Abbildung 2: Die Firewall-Chains für ein Einzelplatzsystem

Dabei durchlaufen alle Netzwerkpakete, die für den Linux-Rechner bestimmt sind, die Regeln der INPUT-Chain. IP-Pakete, die ein Programm auf dem Linux-Rechner erzeugt hat, müssen die OUTPUT-Chain passieren.

Alte Regeln weg und neue her

Beim Aufsetzen der Firewall vermeidet es Komplikationen, wenn man eventuell bereits systemseitig vorgefertigte Firewall-Konfigurationen abschaltet. Damit lautet der erste Eintrag in der Datei, in der wir die Firewall bauen

iptables -F

Anschließend sperren wir, unserer Default-Policy folgend, alles ab. Da davon der komplette Netzwerkverkehr betroffen ist, sollte man beim Erstaufruf des Firewall-Skripts direkt an der Konsole des Firewall-Rechners sitzen:

iptables -P INPUT   DROP
iptables -P FORWARD DROP
iptables -P OUTPUT  DROP

Unsere erste Regel gilt dem WWW. Beim dort verwendeten HTTP baut ein Client auf unserem Computer, beispielsweise Netscape, eine Verbindung zu einem Web-Server auf. Dieser arbeitet in der Regel hinter dem Port 80. Anhand dieser Nummer erkennt die Firewall, dass es sich vermutlich um eine HTTP-Verbindung handelt.

Zum Erstellen der Regel kommt wieder der Befehl iptables zum Einsatz. Um TCP-Datenverkehr (-p tcp) an den "Destination Port" 80 (--dport 80, in der Regel also HTTP-Server) rauszulassen (-j ACCEPT), gibt man Folgendes ein:

iptables -A OUTPUT -p tcp --sport 1024: --dport 80 -j ACCEPT

-A OUTPUT hängt die neue Regel an die OUTPUT-Chain an. --sport 1024: steht für Source Port; dieser muss in der Regel mindestens 1024 sein, aber durch den angehängten Doppelpunkt sind auch alle darüberliegenden Ports erlaubt. Jetzt können wir ein Paket an einen Web-Server schicken, allerdings kommen die Antworten noch nicht zu uns durch.

Theoretisch könnte man für diese Antworten eine exakt symmetrische Regel konstruieren, und viele Leute gehen genau so vor. Diese lautet

iptables -A INPUT -p tcp --sport 80 --dport 1024: ! --syn -j ACCEPT

Absender- und Empfängerports sind vertauscht. Neu ist die Option ! --syn, also "nicht --syn". --syn prüft bestimmte Flags im Header des TCP-Pakets und erkennt damit das allererste Paket einer neuen Verbindung. Die Option ! --syn verweigert also den Aufbau einer neuen Verbindung, während Pakete erlaubt werden, die zu bestehenden Verbindungen gehören. Programme auf unserem Computer dürfen fremde Rechner kontaktieren, aber nicht umgekehrt.

Mir persönlich ist es etwas zu viel Aufwand, alle Regeln doppelt zu halten. Im Bewusstsein, dass ich damit potenziell mehr Pakete zulasse, als ich eigentlich will, begnüge ich mich mit einer einzigen Regel für alle ankommenden TCP-Pakete sämtlicher Protokolle:

iptables -A INPUT -p tcp --dport 1024: ! --syn -j ACCEPT

Sofern ein Paket nicht eine neue Verbindung aufbauen will, sind alle Pakete an unsere Clients erlaubt, egal, von welchem Absender-Port.

Kasten 2: Überwachung von Verbindungen

Über die iptables-Option ! --syn in den Regeln der INPUT-Chain filtert man Pakete heraus, die eine neue Verbindung aufbauen wollen, und lässt nur Daten aus bereits bestehenden Verbindungen zu. So dürfen eigene Clients einen fremden Dienst benutzen, während der umgekehrte Weg blockiert bleibt.

Dabei handelt es sich jedoch um einen ganz primitiven Mechanismus. Theoretisch könnten beliebige fremde Computer Pakete an uns schicken, solange diese nicht einen Verbindungsaufbau initiieren. Wir verlassen uns darauf, dass der Kernel solche zusätzlichen Pakete ignoriert.

Trickreicher ist die Verwendung eines separaten Moduls zur Überwachung des Verbindungszustands. Wenn wir das tun, merkt sich die Linux-Firewall alle bestehenden TCP-Verbindungen. Sobald nun ein Paket ankommt, prüft sie, ob es zu einer bekannten Verbindung gehört, und lässt es gegebenenfalls ohne weitere Rückfragen zu. Auf die Regeln mit ! --syn können wir nun verzichten.

Dieses Modul wird durch zwei iptables-Befehle aktiviert:

iptables -A INPUT  -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

Es werden alle Pakete angenommen, die entweder Teil einer bestehenden Verbindung sind oder als "verwandt" erkannt werden. "Verwandt" sind beispielsweise ICMP-Fehlermeldungen oder auch die besonderen Datenkanäle einer FTP-Sitzung.

Regeln für die üblichen Verdächtigen

Entsprechend gestaltet man die Regeln für die üblichen Netzwerkdienste. Aus Platzgründen finden Sie das komplette Firewall-Skript [3] auf der Heft-CD. Für typische Benutzer interessant sind folgende Ports:

  • 21 – FTP (Dateiübertragung)
  • 22 – SSH (SecureShell)
  • 23 – telnet (unsichere Alternative zu SSH)
  • 25 – SMTP (Mail-Versand)
  • 43 – whois (Verzeichnis der Inhaber und Betreiber von Internet-Domains)
  • 53 – DNS (Zuordnung von Domain-Namen und IP-Adressen)
  • 79 – finger (Abfrage von Benutzerinformationen)
  • 110 – POP3 (Mail-Empfang)
  • 119 – NNTP (Usenet-News-Versand und -Empfang)
  • 143 – IMAP (Mail-Empfang)
  • 443 – HTTPS (abgesicherte WWW-Verbindungen)
  • 554 – RealPlayer G2 (Audio- und Video-Übertragungen)

Die Regeln dafür sehen aus wie das für Port 80 beschriebene Muster. Eine Ausnahme macht FTP: Für jede Dateiübertragung wird hierbei eine eigene TCP-Verbindung unter Verwendung eines der oberen Ports aufgebaut. Im klassischen, aktiven FTP-Modus handelt es sich dabei um Verbindungen vom FTP-Server zurück zu uns. Das ist – außer mit dem in Kasten 2 vorgestellten Modul zur Verbindungsüberwachung – recht unsicher und daher unerwünscht.

Der heute fast ausschließlich eingesetzte passive Modus baut eine Verbindung vom FTP-Client zu einem der oberen Ports auf dem FTP-Server auf. Vom Standpunkt größtmöglicher Sicherheit ist das zwar immer noch nicht ideal, aber zumindest akzeptabel. Hierfür benutzen wir

iptables -A OUTPUT -p tcp --sport 1024: --dport 1024: -j ACCEPT

und die von mir vorgeschlagene "bequeme" INPUT-Regel, die alle Protokolle abdeckt.

Lokale Kommunikation

Für die IP-basierte Kommunikation zwischen verschiedenen Programmen auf dem gleichen Computer gibt es ein besonderes Netzwerk-Interface namens Loopback oder kurz lo. Dieses ist für viele Anwendungen essentiell, stellt umgekehrt aber kein Sicherheitsrisiko dar, weil es nur für die lokale Kommunikation benutzt werden kann. Deshalb erlaubt man üblicherweise jeden beliebigen Datenaustausch über dieses Pseudo-Interface:

iptables -A INPUT  -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

Die Optionen -i beziehungsweise -o schränken die Regeln auf Pakete ein, die über das angegebene Netzwerk-Interface empfangen ("input") oder versendet ("output") werden.

Eigene Server

Manche Leute betreiben auf ihrem Linux-Rechner einen oder mehrere Server, die über das Internet zugänglich sein sollen. Hierfür benötigt man natürlich eigene Firewall-Regeln, und zwar sowohl für ankommende als auch für abgehende Pakete. Wollen Sie auf Ihren Computer von außen per HTTP (Port 80) und SSH (Port 22) zugreifen, so erlauben Sie dies folgendermaßen:

iptables -A INPUT -p tcp -s 172.16.45.0/24 --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 22 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 80 -j ACCEPT

Für jeden Server verwenden wir zwei Regeln: Eine für ankommende (-A INPUT) und eine für abgehende Pakete (-A OUTPUT). Wie Sie sehen, schränke ich den SSH-Zugriff etwas ein: Nur Computer mit einer IP-Adresse zwischen 172.16.45.0 und 172.16.45.255 dürfen SSH-Verbindungen aufbauen.

Der Domain Name Service

Für DNS benötigen wir etwas kompliziertere Regeln – notwendig ist dieser Dienst jedoch immer. Jede Anfrage an einen DNS-Server erfolgt zunächst über das UDP-Protokoll. Sofern die Antwort zu groß ist für ein einzelnes UDP-Paket, wird die Anfrage per TCP wiederholt. Damit sind größere Datenübertragungen möglich. Die Regeln für das Senden der Anfrage an den Nameserver sind relativ einfach:

iptables -A OUTPUT -p udp --sport 1024: --dport 53 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 1024: --dport 53 -j ACCEPT

Wie wir zu Anfang erwähnt hatten, stellen die UDP-Antworten eine besondere Herausforderung an die Firewall dar: Sie kann nicht ohne Weiteres feststellen, ob ein Paket zu einer bereits bestehenden Verbindung gehört.

Spricht ein DNS-Server mit uns, kommt das Paket von Port 53 (domain). Empfänger ist (sofern wir keinen eigenen DNS-Server besitzen) einer der oberen Ports auf unserem Computer. Wenn wir nur einen einzigen fremden DNS-Server benutzen, etwa den des Internet-Providers, erlauben wir UDP-Pakete von genau dieser IP-Adresse, im Beispiel 193.162.1.42:

nameserver=193.162.1.42
iptables -A INPUT -p udp -s $nameserver --sport 53 -j ACCEPT
iptables -A INPUT -p tcp -s $nameserver --sport 53 -j ACCEPT

Falls wir einen eigenen DNS-Server betreiben, können wir den lokal verwendeten UDP-Port konfigurieren. Wir akzeptieren UDP-Pakete aus dem ganzen Internet, aber nur an diesen einen UDP-Port:

iptables -A INPUT -p udp --sport 53 --dport 7531 -j ACCEPT

Ohne eigenen DNS-Server und mit veränderlichem fremdem Server (zum Beispiel bei Modem-Einwahlverbindungen) müssten wir UDP von allen fremden Rechnern freigeben. Das ist natürlich sehr unerwünscht. Abhilfe bietet das in Kasten 2 erwähnte Zusatzmodul zur Überwachung von Verbindungen: Es lässt UDP-Antworten auf unsere Anfragen zu, andere UDP-Pakete jedoch nicht. Leider kann solch ein Modul, insbesondere unter hoher Last, designbedingt nicht immer zuverlässig arbeiten. Wenn Sie möchten, aktivieren Sie das Zusatzmodul mit folgender Regel:

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

Eine Alternative ist die Aktualisierung der Firewall nach jeder neuen Internet-Einwahl. Das Firewall-Skript kann die Adressen der Nameserver aus der Konfigurationsdatei /etc/resolv.conf auslesen und die Regeln entsprechend anpassen. Dazu rufen wir es aus /etc/ppp/ip-up auf: Diese Datei wird vom PPP-Dämon nach erfolgter Einwahl gestartet.

Schreiben Sie das Fragment aus Listing 1 einfach in Ihr Firewall-Skript (z. B. /etc/rc.d/rc.firewall) hinein. Anschließend setzen Sie die DNS-Regeln und nehmen dabei Bezug auf die Variablen $nameserver_1, $nameserver_2 usw. Die Zeile . /etc/rc.d/rc.firewall in /etc/ppp/ip-up sorgt für die Aktualisierung der Firewallregeln. (Der Punkt ruft ein Skript aus einem anderen Skript heraus auf.)

Listing 1

Einlesen der Nameserver-Adressen im Firewall-Skript

awk    'BEGIN { i=1 }
        /^nameserver / { print "nameserver_" i "=" $2; i+=1 }' \
                < /etc/resolv.conf >> /etc/ppp/nameserver.info
. /etc/ppp/nameserver.info

ICMP

Datenpakete, die Internet Control Messages enthalten, bedürfen einer besonderen Behandlung. Anstelle von Port-Nummern enthalten solche Pakete einen Nachrichtentyp (und eventuell einen Subtyp). So erkennt bereits die Firewall, worum es geht, und kann bestimmte Inhalte selektiv herausfiltern.

echo-request und echo-reply sind Frage und Antwort von ping, mit dem man prüft, ob ein Computer eingeschaltet und ordentlich ans Netz angeschlossen ist. Die folgenden Regeln erlauben eine abgehende Anfrage (Request) und die zugehörige Antwort (Reply).

iptables -A OUTPUT -p icmp --icmp-type echo-request -j ACCEPT
iptables -A INPUT  -p icmp --icmp-type echo-reply   -j ACCEPT

Ob Sie auch den umgekehrten Weg öffnen, also anderen Leuten die Überprüfung Ihres eigenen Rechners gestatten, entscheiden Sie selbst. Dafür benutzen Sie gegebenenfalls diese beiden Regeln:

iptables -A INPUT  -p icmp --icmp-type echo-request -j ACCEPT
iptables -A OUTPUT -p icmp --icmp-type echo-reply   -j ACCEPT

Die zahlreichen Subtypen von destination-unreachable teilen einem Computer mit, dass eine bestimmte Ressource nicht erreichbar ist. Diese Nachrichten sollten in beiden Richtungen passieren dürfen. Insbesondere der Subtyp fragmentation-needed, der durch destination-unreachable mit abgedeckt wird, ist in bestimmten Situationen lebenswichtig: Wenn Pakete nicht fragmentiert werden dürfen, kann es zu völlig undurchsichtigen Fehlerzuständen kommen, bei denen Verbindungen willkürlich abzureißen scheinen. Verwenden Sie folgende Regeln:

iptables -A OUTPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
iptables -A INPUT  -p icmp --icmp-type destination-unreachable -j ACCEPT

Bei ankommenden Paketen sollte man noch drei weitere Arten von Fehlermeldungen erlauben, um sich die Fehlersuche zu erleichtern. An andere Computer wird man kaum jemals solche Meldungen übermitteln (außer, man setzt ein Server-System auf), aber es kommt durchaus einmal vor, dass ein fremder Computer einen solchen Fehler zurückschickt.

iptables -A INPUT -p icmp --icmp-type source-quench     -j ACCEPT
iptables -A INPUT -p icmp --icmp-type time-exceeded     -j ACCEPT
iptables -A INPUT -p icmp --icmp-type parameter-problem -j ACCEPT

Abschluss

Die vorletzten Regeln, die wir in unsere Firewall schreiben, sorgen für eine Protokollierung auffälliger Ereignisse. Von manchen Paketen möchten wir gar nichts wissen: Verbindungsversuche zu NetBIOS-Ports für die Windows-Netzwerkumgebung schicken wir kommentarlos ins Nirwana (-j DROP). Alle anderen unerlaubten Pakete zeichnen wir erst einmal auf (-j LOG).

iptables -A INPUT -p udp --dport netbios-ns  -j DROP
iptables -A INPUT -p udp --dport netbios-dgm -j DROP
iptables -A INPUT -p tcp --dport netbios-ssn -j DROP
iptables -A INPUT  -j LOG
iptables -A OUTPUT -j LOG

Zum Schluss verwerfen wir alle Pakete, die noch nicht als erlaubt erkannt und so explizit angenommen wurden. Dabei stehen in INPUT- und OUTPUT-Chain unterschiedliche Regeln: Unerwünschte ankommende Pakete ignorieren wir stillschweigend: Wenn uns jemand angreift, wollen wir ihm möglichst wenig Informationen über unser System zukommen lassen. Einzige Ausnahme sind Pakete für den Auth-Port: Dieser dient z. B. FTP-Servern zu einem legitimen Identifikationsversuch. Wir erlauben ihn zwar nicht, wollen aber auch nicht lange warten, bis der fremde Rechner entnervt aufgibt:

iptables -A INPUT -p tcp --dport auth -j REJECT --reject-with tcp-reset
iptables -A INPUT -j DROP

Bei abgehenden Paketen liegt eine andere Situation vor: Egal, ob es sich um einen Fehler in der Firewall oder in der Anwendersoftware handelt, wir sind es selbst, die vor dem Computer sitzen und das gesperrte Paket verursacht haben. Über diese Situation soll der Computer uns sofort informieren. Deshalb werden abgehende TCP- und UDP-Pakete mit einer Fehlermeldung an das Anwenderprogramm zurückgewiesen:

iptables -A OUTPUT -p tcp -j REJECT --reject-with tcp-reset
iptables -A OUTPUT -p udp -j REJECT
iptables -A OUTPUT -j DROP

Zusammensetzen

Und wie kommen Sie jetzt zu Ihrer fertigen Firewall? Suchen Sie sich alle Regeln heraus, die für Ihren Computer passen, und schreiben Sie sie in eine Datei, beispielsweise /etc/rc.d/rc.firewall.

Nun sorgen Sie dafür, dass Ihr Computer dieses Skript automatisch aufruft. Wenn Sie exakt arbeiten möchten, erstellen Sie dafür ein eigenes Init-Skript in /etc/rc.d/rc*.d, das noch vor der Initialisierung Ihrer Netzwerkschnittstellen abgearbeitet wird, etwa /etc/rc.d/rc3.d/S01firewall. Wenn Sie es nicht ganz so genau nehmen oder ohnehin keine ständige Internet-Anbindung besitzen, hängen Sie eine Zeile . /etc/rc.d/rc.firewall an die Datei /etc/rc.d/rc.local o. ä. an.

Deaktivieren Sie die Firewall-Automatik Ihrer Distribution, wenn Sie eine eigene Firewall installieren! Bei Red Hat und verwandten Distributionen löschen Sie die beiden Konfigurationsdateien ipchains und iptables im Verzeichnis /etc/sysconfig.

Theoretisch können Sie beim Testen einzelne Regeln per Hand setzen und auch wieder löschen. Da es vor allem am Anfang schwer ist, dabei den Überblick zu behalten, korrigieren Sie lieber Ihr Skript und rufen es neu auf, wenn Sie eine Änderung vornehmen.

Bei einer etwaigen Fehlersuche hilft Ihnen am besten das syslog; Meldungen der Firewall über abgewiesene Datenpakete landen bei den meisten Distributionen in der Datei /var/log/messages.

Weitere Einblicke in die Firewall-Konfiguration bietet z. B. [2]. Dort erfahren Sie auch mehr über benutzerdefinierte Ketten, mit denen Sie Ihre Firewall optimieren und beschleunigen können.

Abbildung 3

Abbildung 3: Die Firewall-Chains für einen Router

Kasten 3: Firewalls und lokale Netze

Viele Linux-Anwender betreiben zu Hause ein eigenes lokales Netzwerk. Oft dient dabei ein Linux-Rechner als zentraler Router für den Internet-Zugang, den mehrere Computer mit verschiedenen Betriebssystemen benutzen.

Die Firewall muss in dieser Situation etwas anders konfiguriert werden. Für Pakete, die aus dem LAN ins Internet (und umgekehrt) weitergeleitet werden, existiert eine eigene Firewall-Chain namens FORWARD. Abbildung 3 zeigt die neue Architektur.

Wenn ein Paket – egal ob aus dem Internet oder aus dem LAN – direkt an den Computer mit der Firewall geschickt wird, durchläuft es die INPUT-Chain. Wird eines auf dem Firewall-Rechner generiert, muss es die OUTPUT-Chain passieren. Für Pakete, die lediglich zwischen LAN und Internet weitergeleitet werden, ist hingegen ausschließlich die FORWARD-Chain zuständig. Dies ist ein wichtiger Unterschied zu den Firewall-Implementationen älterer Kernel-Serien!

Die Minimalregeln für weitergeleitete Pakete sehen etwa so aus:

# Abgehende Pakete
iptables -A FORWARD -o ppp0 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
# Ankommende Pakete
iptables -A FORWARD -o eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT

Die FORWARD-Chain kann im Prinzip ganz ähnliche (oder manchmal sogar identische) Regeln enthalten wie INPUT- und OUTPUT-Chains. Tatsächlich lege ich Ihnen auch dringend ans Herz, hier einen entsprechenden Aufwand zu treiben: Nur so können Sie das Maximum an Sicherheit für Ihr LAN herausholen. Besonders Windows-Maschinen werden es Ihnen zu danken wissen. Ein Minimalsystem wie die zwei hier gezeigten Regeln ist heute nicht mehr ausreichend!

Sofern sich Ihr lokales Netz eine gemeinsame IP-Adresse teilen muss, erfüllt die Firewall noch eine weitere Funktion. Sie befördert nicht nur Pakete zwischen LAN und Internet, sondern korrigiert auch die IP-Adressen auf unserer Seite. Diese Funktionalität heißt NAT oder "Network Address Translation" (Netzadressübersetzung).

Dank NAT sieht es für die Computer im LAN so aus, als hätten sie eine direkte Internet-Anbindung ohne Komplikationen. Für Rechner im Internet hingegen wirkt das gesamte LAN wie ein einziger, besonders aktiver Computer mit einer einzigen IP-Adresse.

Statt der lokalen Netzwerkadresse eines angeschlossenen Computers wird in abgehenden Paketen die offiziell zugewiesene IP-Adresse des Routers eingetragen, die zum Beispiel über PPP ausgehandelt wurde. Gleichzeitig wechselt die Firewall die Port-Nummer aus und ersetzt sie durch einen freien Port auf dem Firewall-Computer.

Bei ankommenden Paketen geschieht das Umgekehrte: Diese Pakete sind an die IP-Adresse der Firewall adressiert und tragen auch eine entsprechende Port-Nummer im Header. Anhand dieser erkennt die NAT-Implementation, welchem Computer im LAN die entsprechende Verbindung gehört. Sie trägt wieder seine IP-Adresse und die ursprüngliche Port-Nummer als Empfänger ein und schickt das Paket weiter.

Das Schönste an NAT ist die Einfachheit, mit der man es einschaltet. Dafür reicht nämlich – zusätzlich zu den normalen Weiterleitungsregeln - eine einzige Zeile im Firewall-Skript:

iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE

Statt ppp0 tragen Sie natürlich das Netzwerk-Interface ein, über das Sie Ihre Internet-Verbindung herstellen: ppp0 für Modemverbindungen, ippp0 für ISDN oder eth0 beziehungsweise ein anderes Ethernet-Interface für DSL.

Glossar

IP

Das paketbasierte "Internet Protocol" bildet die Grundlage jeder Kommunikation über das Internet. Jedes IP-Paket enthält u. a. die numerischen Adressen von Absender und Empfänger. Verschiedenste Protokolle setzen auf IP auf und bieten zusätzliche Features.

Port-Nummern

Sie kennzeichnet Programme eindeutig, sowohl Server- als auch Client-Software. Wenn ein Client eine Verbindung aufbaut, weist ihm der Kernel automatisch eine Port-Nummer zu. Dabei gilt unter Unix die Grundregel, dass alle normalen Programme Ports im Bereich ab 1024 erhalten. Die darunterliegenden bleiben für Server reserviert, die root startet. Jedes TCP- und UDP-Paket enthält also zwei Port-Nummern, einen für den Absender und einen für den Empfänger.

Policies

Jede Firewall-Regel kann direkt angeben, dass mit einem Paket etwas geschehen soll. Wird für ein Paket keine passende Regel gefunden, entscheidet die Policy über seinen Verbleib.

Routing-Tabellen

Sie legt fest, über welche Netzwerkverbindungen Ihr Computer Pakete an andere Systeme schickt. Ein Einzelplatzsystem kennt meist nur zwei Verbindungen: lo führt zum eigenen Rechner, ppp0, ippp0 oder eth0 ins Internet. Viele Router oder größere Server besitzen mehrere Netzwerk-Interfaces und damit auch kompliziertere Routing-Tabellen.

Flags

Einzelne Bits im Kopf eines Pakets, die zusätzliche Informationen darüber enthalten, was das Paket erreichen möchte bzw. wofür es gut ist. Flags sagen zum Beispiel "hier beginnt eine neue Verbindung" oder "dieses Paket darf nicht in kleinere Stücke zerlegt werden".

Infos

[1] Robert L. Ziegler: "Linux Firewalls", Markt und Technik München, 2002 (2. Auflage)

[2] "Linux 2.4 Packet Filtering HOWTO" und "Linux 2.4 NAT HOWTO": http://netfilter.samba.org/unreliable-guides/

[3] Das Firewall-Skript aus diesem Artikel zum Download: http://www.seligma.com/linux-user/firewalls/

Der Autor

Marc André Selig hat Humanmedizin studiert. Er arbeitet als wissenschaftlicher Angestellter an der Universität Trier und ist parallel als selbstständiger EDV-Berater und Schriftsteller tätig. Momentan beschäftigt er sich vor allem mit Datenbankprogrammierung für Web-Services auf diversen Unix-Plattformen. Gleichzeitig ist er auf der Suche nach einer AiP-Stelle, die sich für Unix-Fans eignet …

Tip a friend    Druckansicht beenden Bookmark and Share
Kommentare