Linux als Perimeter-Firewall

18.05.2004 von STEFAN RUBNER 
Angst vor Angriffen aus dem Internet muss nicht sein: Der im Linux-Kernel integrierte Paketfilter erlaubt den Aufbau einer leistungsfähigen Schutzlösung - und gestattet es auch, den internen Anwendern ein wenig auf die Finger zu schauen.

Wer eine Verbindung zum Internet aufbaut, begibt sich potenziell in Gefahr. Kaum eine Woche vergeht, ohne dass in Fernsehen, Radio und Presse über einen neuen Virus, Wurm, Trojaner oder diverse Sicherheitslücken im Betriebssystem des Rechners selbst berichtet wird.

Nun lässt sich das Problem vermeintlich leicht beheben: Schon für recht wenig Geld sind mittlerweile Firewall-Router erhältlich, die für den Schutz der lokalen Rechner sorgen sollen. Trotzdem gibt es gute Gründe, sich selbst näher mit dem Thema zu beschäftigen. Einer davon ist sicherlich das gesparte Geld für den Router, das man anderweitig auch gut anlegen kann.

Nicht zu unterschätzen sind aber vor allem in größeren Netzen die deutlich erweiterten Möglichkeiten, die eine selbst gestrickte Firewall unter Linux bietet. Neben der deutlich flexibleren Konfiguration gehört dazu auch die wesentlich bessere Protokollierung der Vorgänge, was sowohl das Erkennen von Angriffen erleichtert sowie nebenbei eine Abrechnung des Datenvolumens erlaubt. Zudem bietet eine Firewall unter Linux die Option, auch ausgehende Verbindungen effektiv einzuschränken - ein Feature, das unerwünschte Filesharing-Aktivitäten der Anwender im LAN ebenso unterbindet wie die Kommunikation von eventuell im Netz vorhandenen Trojanern mit ihren Heimatservern im Internet.

Diesen Artikel und eine ganze Reihe weiterer Praxis-Themen finden Sie auch in unserem neuesten tecCHANNEL-Compact. Dort erfahren Sie nicht nur, wie Sie einen Apache 1.x unfallfrei auf Apache 2 upgraden, sondern unter anderem auch wie Sie einen Email-Server mit dem Freeware-Tool XMail aufsetzen und via SpamAssassin vor unerwünschten Mails schützen. Auf der Heft-CD finden Sie einen kompletten LAMP-Server von SuSE sowie den Intel C++-Compiler für Linux, mit dem Sie Ihre Programme optimal auf Ihre Prozessor-Architektur abgestimmt compilieren können. Der Compiler ist für den Privatgebrauch sogar kostenlos. Das Compact können Sie hier in unserem Online-Shop für 9,90 Euro versandkostenfrei bestellen.

Setup: Lieber von Hand

Dreh- und Angelpunkt einer Firewall unter Linux ist das Hilfsprogramm iptables. Dieses stellt nicht etwa selbst die Firewall-Funktionen zur Verfügung. Vielmehr handelt es sich dabei um ein Werkzeug, das eine Schnittstelle zu der im Linux-Kernel integrierten Netfilter-Architektur herstellt. Dieses vom Netfilter-Projekt entwickelte System bietet alle Funktionen, die für den Aufbau einer Firewall notwendig sind.

Gesteuert werden diese über diverse Optionen, die dem Utility iptables als Parameter zu übergeben sind. Auf diesem Weg lassen sich Verarbeitungsketten erstellen, die ein Datenpaket passieren muss, um weitergeleitet, verarbeitet oder auch zurückgewiesen zu werden. Die so erstellten Regeln verwaltet der Firewall-Rechner im Hauptspeicher. Auf diese Weise ist sicher gestellt, dass auch im Betrieb Änderungen vorgenommen werden können.

Der große Vorteil der Netfilter-Architektur ist allerdings auch gleichzeitig ihr größter Nachteil: sie ist so flexibel, dass ihre Arbeitsweise für einen Einsteiger nur schwer zu durchschauen ist. Zudem gibt es keine zentrale Konfigurationsdatei, die das zu verwendende Regelwerk festlegt. Es finden sich daher im Internet genügend Hilfsprogramme die versuchen, dem Anwender die Konfiguration der Firewall leichter zu machen. So erfreulich diese Anstrengungen auch sind, sie besitzen alle einen großen Pferdefuss: Funktioniert einmal nicht alles so wie gewünscht, fehlt dem Benutzer nach wie vor das nötige Wissen, um den Fehler lokalisieren zu können.

Speziell wenn es darum geht, nicht nur den lokalen Rechner, sondern ein ganzes Netz zu schützen, sind viele dieser Lösungen überfordert. Das gilt auch für die in SuSE Linux integrierte Firewall. Per YaST2 lassen sich lediglich Einstellungen für den lokalen Rechner treffen. Wer mehr benötigt, muss die Konfigurationsdatei /etc/sysconfig/SuSEfirewall2 von Hand bearbeiten. Eine Aufgabe, die ohne vorhandenes Basiswissen auch mithilfe der aufschlussreichen Kommentare kaum erfolgreich lösbar ist.

Die Arbeitsweise von iptables

Also frisch gewagt und auf ins Getümmel. So schwer, wie es auf den ersten Blick erscheint, ist es wirklich nicht. Für die folgenden Beispiele gehen wir von einem Rechner aus, der als Router zwischen dem Internet und dem lokalen Netz fungiert. Betrachten wir nun zunächst die Wege, die ein Datenpaket durch diesen Computer nehmen kann. Hier gibt es drei Möglichkeiten:

Entsprechend dieser Wege definieren sich die drei Hauptaufgaben: Entgegennehmen (Input), Weiterleiten (Forward) und Versenden (Output) von Daten. Genau für diese drei Aufgaben stellt der Netfilter gleichnamige Regellisten bereit, die über iptables ansprechbar sind. Diese Regellisten nennt man auch Ketten oder neudeutsch Chains.

Bei dieser Betrachtung handelt es sich aber um eine stark vereinfachte Sichtweise, die zwei Sonderfälle nicht berücksichtigt. Der erste ist der Einsatz von Network Address Translation (NAT).

Network Address Translation

Bei NAT gaukelt der Router den Gegenstellen im Internet vor, dass allein er der Absender aller aus dem lokalen Netz stammenden Daten ist. Dazu setzt er seine ihm vom Provider zugeteilte dynamische IP-Adresse als Absenderangabe in jedes ins Internet gehende Datenpaket ein.

Damit die von dort zurück kommenden Antworten auch wieder den richtigen Rechner im LAN erreichen, muss also bei eintreffenden Paketen erst die richtige Empfängeradresse gesetzt werden. Anderenfalls würde der Router die Pakete lokal bearbeiten, anstatt sie wie gewünscht an den Empfänger im lokalen Netz weiter zu leiten.

Es sind also je nach Ziel der Daten zwei unterschiedliche Arbeitsschritte erforderlich: Bei eintreffenden Daten muss die Zieladresse auf den korrekten Empfänger umgestellt werden, bevor entschieden wird, ob das Paket für den lokalen Rechner bestimmt ist. Bei ausgehenden Paketen ist nach allen Verarbeitungsschritten die Absender-Adresse auf die des Routers zu setzen.

Damit auch auf diese Verarbeitungsschritte Zugriff besteht, bietet iptables neben den Ketten der Standardtabelle zusätzlich die Filter der Tabelle nat, die neben den Chains Input, Out und Forward noch die beiden Regelketten Prerouting und Postrouting enthält.

Mangling

Über die Network Address Translation hinaus existiert noch eine weitere Möglichkeit, Paketdaten zu manipulieren. Dieses "Mangling" genannte Verfahren erlaubt es, einzelnen Datenpaketen spezielle Attribute zuzuweisen. Mithilfe dieser Funktion lassen sich beispielsweise besondere Features wie etwa rudimentäre Quality of Services auch unter IPv4 realisieren.

Damit das funktioniert, finden sich diverse Punkte im Verarbeitungsprozess, an denen der Mangling-Prozess einhaken kann: Vor dem Aufruf der NAT-Funktionen sowie vor der Abarbeitung der Input-Filter. Ebenso vor dem Output wie auch dem Forward-Filter. Für den Betrieb einer Firewall sind die Mangling-Funktionen jedoch von geringer Bedeutung, so dass Sie die in der Tabelle mangle vorhandenen Ketten Input, Output, Forward, Prerouting und Postrouting erst einmal ignorieren können.

Übrigens sind nicht nur die beiden Filtertabellen mangle und nat mit einem eigenen Namen versehen, auch die Standardtabelle trägt eine Bezeichnung: filter. Wenn Sie beim Aufruf von iptables keine explizite Angabe der Tabelle vornehmen, landen die neuen Regeln automatisch in der Filter-Tabelle.

Die WWW-Faustregel

Jetzt kennen Sie zwar den generellen Ablauf der Paketfilterung, wissen aber noch nicht, worauf Sie den Filter eigentlich ansetzen können. Als Faustregel sollten Sie sich gleich die drei großen "W" merken: "Wo kommt es her, wo will es hin und was will es eigentlich?". Genau das sind die groben Kriterien, an denen sich iptables orientiert.

Die Frage nach dem "Woher?" lässt sich auf zwei Arten beantworten: Über die Schnittstelle, auf der das Paket eintraf, oder über die IP-Adresse des Absenders. Ähnliches gilt für das "Wohin?". Hier lässt sich feststellen, auf welchem Interface die Ausgabe erfolgen soll, oder aber, wer der Empfänger der Daten ist. Was genau das Paket schließlich will, das bestimmt der Zielport, über den in der Regel die zuständige Applikation identifizierbar ist. Zusätzlich gibt auch der Status des Pakets Aufschluss über seine Intention.

Eine andere Interpretation der Drei-W-Regel ist: "Wer darf was mit wem?". Dies ist die grundlegende Frage, die Sie sich beim Aufsetzen der Firewall-Regeln stellen müssen. Die einfachste Antwort darauf ist: Aus dem LAN heraus darf jeder alle möglichen Anfragen ins Internet senden. Antworten aus dem Internet werden an die Fragesteller weitergeleitet. Unaufgefordert aus dem Internet eintreffende Pakete landen im Datengrab. Zusätzlich ist es ratsam, eine Politik nach dem Motto "Was nicht explizit erlaubt ist, ist verboten" anzuwenden.

Simpler NAT-Router

Ein erster Ansatz für die Firewall wäre daher folgendes Script, das Sie am besten als Superuser root unter /root/fwtest1 anlegen:

#!/bin/bash
LANIF="eth0"
INETIF="ppp0"
IPTABLES=`which iptables`
$IPTABLES -A INPUT -i $INETIF -m state --state NEW,INVALID -j DROP
$IPTABLES -A FORWARD -i $INETIF -m state --state NEW,INVALID -j DROP
$IPTABLES -A POSTROUTING -t nat -o $INETIF -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward

Mit diesem Script weisen Sie den Router an, einen relativ simplen NAT-Router zu realisieren. Dabei gehen wir davon aus, dass über das Interface eth0 die Verbindung zum LAN, über ppp0 die Kommunikation mit Systemen im Internet erfolgt. Die Unterscheidung zwischen erlaubten und verbotenen Paketen geschieht dabei über den Zustand der Verbindung, zu der die jeweiligen Informationen gehören.

Im Netfilter-System existieren genau vier Zustände, die ein Paket haben kann: Neu (New), Bekannt (Established), Verwandt (Related) und Ungültig (Invalid). Von diesen können Sie den letzten Typ schon einmal bedenkenlos ablehnen. Gleiches gilt meistens für Pakete mit dem Status "New", da diese eine neue Anfrage darstellen, also nicht durch eine vorhergehende Anforderung eines Clients aus dem lokalen Netz angefordert wurden.

Es bleiben also die Varianten Established, was zu einer bestehenden Sitzung gehörende Pakete bezeichnet, und Related, welches zu einer bestehenden Sitzung verwandte Pakete spezifiziert. Datenpakete mit diesen beiden Auszeichnungen werden von unserem Skript sowohl für den lokalen Rechner (-A INPUT) wie auch für andere Computer im Netz (-A FORWARD) entgegen genommen und verarbeitet.

Die Zeile mit der Anweisung -A POSTROUTING -t nat schließlich weist den Netfilter an, alle über das Interface ppp0 (-o $INETIF) ausgehenden Pakete mit der IP-Adresse des Routers zu versehen, also eine Network Address Translation vorzunehmen.

Schärfere Variante

Das gerade beschriebene Beispiel arbeitet nach dem Motto "Erlaubt ist, was nicht verboten ist.". Für eine Firewall, die ja dem Schutz des lokalen Netzes dienen soll, ist das sicherlich nicht die optimale Einstellung. Die umgekehrte Arbeitsweise ist auch nicht wesentlich aufwändiger zu realisieren, wie das Script fwtest2 zeigt:

#!/bin/bash
LANIF="eth0"
INETIF="ppp0"
IPTABLES=`which iptables`
$IPTABLES -P INPUT DROP
$IPTABLES -P FORWARD DROP
$IPTABLES -A INPUT -i $INETIF -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A INPUT -i $LANIF -j ACCEPT
$IPTABLES -A FORWARD -i $INETIF -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A FORWARD -i $LANIF -j ACCEPT
$IPTABLES -A POSTROUTING -t nat -o $INETIF -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward

Der Unterschied liegt hier zunächst darin, dass Sie die Standardvorgabe für die Verarbeitung in den Ketten INPUT und FORWARD von "erlaube alles" auf "verwerfe alles" geändert haben (-P ... DROP).

Als Konsequenz daraus müssen Sie den beiden Filterketten nicht nur sagen, dass aus dem Internet kommende Pakete mit Status ESTABLISHED oder RELATED zu akzeptieren sind. Zusätzlich sind auch die aus dem lokalen Netz (-i $LANIF) kommenden Pakete explizit zu genehmigen.

Um die Output-Regel brauchen Sie sich nicht zu kümmern, da das Standardverhalten unverändert beibehalten wird. Ergo akzeptiert diese Regelkette nach wie vor alles, was ihr angeliefert wird.

Eigene Server einrichten

Das bisher vorgestellte Setup erlaubt eine reibungslose Kommunikation der Rechner im lokalen Netz mit Gegenstellen im Internet. Nun gibt es aber durchaus Fälle, in denen es gewünscht ist, dass auch Rechner aus dem Internet Kontakt mit lokalen Gegenstellen aufnehmen. Vielleicht wollen Sie ja einen Web-Server mit Informationen für Geschäftspartner betreiben oder einen FTP-Server zum schnellen Datenaustausch bereit stellen.

Damit das funktioniert, müssen Sie die für die jeweiligen Dienste eintreffenden Daten an die richtigen Rechner im lokalen Netz weiterleiten. Kurz: Löcher in die Firewall bohren. Dazu sind sowohl Änderungen am NAT-Routing wie auch am Forwarding nötig. Ein Beispiel für einen Web- und einen FTP-Server zeigt das deutlich:

#!/bin/bash
LANIF="eth0"
INETIF="ppp0"
IPTABLES=`which iptables`
FTP_SRV="192.168.27.100"
HTTP_SRV="192.168.27.101"
$IPTABLES -P INPUT DROP
$IPTABLES -P FORWARD DROP
$IPTABLES -A PREROUTING -t nat -i $INETIF -p tcp --dport 21 -j DNAT --to-destination $FTP_SRV
$IPTABLES -A PREROUTING -t nat -i $INETIF -p tcp --dport 80 -j DNAT --to-destination $HTTP_SRV
$IPTABLES -A INPUT -i $INETIF -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A INPUT -i $LANIF -j ACCEPT
$IPTABLES -A FORWARD -i $INETIF -d $FTP_SRV -p tcp --dport 21 -j ACCEPT
$IPTABLES -A FORWARD -i $INETIF -d $HTTP_SRV -p tcp --dport 80 -j ACCEPT
$IPTABLES -A FORWARD -i $INETIF -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A FORWARD -i $LANIF -j ACCEPT
$IPTABLES -A POSTROUTING -t nat -o $INETIF -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward

Das Verfahren funktioniert nicht nur, es zeigt auch gleich ein Problem, das generell jedem Firewall-Anwender zu schaffen macht: Will man einen Zugang für externe Rechner legen, dann muss man sich vorab entscheiden, auf welchem lokalen Computer der Dienst landen soll.

Teure Firewalls umgehen das Problem, indem sie spezielle Filter implementieren. Diese erlauben es, für einen Client bei Bedarf ein Loch in die Firewall zu bohren, das sich nach einer gewissen Zeit wieder schließt. Dazu überwacht die Firewall die Zielports des ausgehenden Datenverkehrs. Spricht ein Client einen bestimmten Zielport an, legt die Firewall in Erwartung eingehender Daten auf anderen, zuvor vom Administrator bestimmten Ports entsprechende Weiterleitungsregeln an. Werden die so geöffneten Ports über eine gewisse, ebenfalls definierbare Zeitspanne nicht genutzt, schließt die Firewall das Loch wieder. Mit iptables lässt sich ein vergleichbares Verfahren derzeit nicht realisieren.

Eigene Ketten definieren

Dagegen sind eigene Regelketten innerhalb der Filter-Tabelle durchaus realisierbar. Das ist recht praktisch, wenn zum Beispiel der Datenverkehr nach Protokollen zu bearbeiten ist, oder Sie einfach eine globale Protokollfunktion einrichten möchten. Möchten Sie etwa sehen, welche Dienste abgesehen von HTTP Ihre lokalen Anwender noch aufrufen, dann lässt sich das recht einfach realisieren:

#!/bin/bash
LANIF="eth0"
INETIF="ppp0"
IPTABLES=`which iptables`
FTP_SRV="192.168.27.100"
HTTP_SRV="192.168.27.101"
$IPTABLES -P INPUT DROP
$IPTABLES -P FORWARD DROP
$IPTABLES -N log_it
$IPTABLES -A log_it -j LOG --log-prefix "Kein HTTP: "
$IPTABLES -A PREROUTING -t nat -i $INETIF -p tcp --dport 21 -j DNAT --to-destination $FTP_SRV
$IPTABLES -A PREROUTING -t nat -i $INETIF -p tcp --dport 80 -j DNAT --to-destination $HTTP_SRV
$IPTABLES -A INPUT -i $INETIF -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A INPUT -i $LANIF -j ACCEPT
$IPTABLES -A FORWARD -p tcp ! --dport 80 -j log_it
$IPTABLES -A FORWARD -i $INETIF -d $FTP_SRV -p tcp --dport 21 -j ACCEPT
$IPTABLES -A FORWARD -i $INETIF -d $HTTP_SRV -p tcp --dport 80 -j ACCEPT
$IPTABLES -A FORWARD -i $INETIF -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A FORWARD -i $LANIF -j ACCEPT
$IPTABLES -A POSTROUTING -t nat -o $INETIF -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward

Zugegeben: Recht sinnvoll ist das noch nicht, da zum Beispiel beim Zugriff auf einen externen FTP-Server eine Unmenge von Log-Einträgen entsteht. Es demonstriert aber recht schön eine andere Eigenschaft von iptables: Die Tatsache, dass sich Pakete umleiten lassen, ohne verloren zu gehen. Im obigen Beispiel wurde ja nur die neue Regelkette log_it angelegt und mit einer einzigen Regel versehen - dem Aufruf der eigentlich Protokollierung. Hat das Paket diese durchlaufen, leitet der Netfilter es wieder zu der Kette zurück, von der aus es den Umweg begonnen hat.

Log-Einträge reduzieren

Das Problem der unzähligen Log-Einträge lässt sich auf zwei Arten lösen. Entweder, Sie geben eine weitere Regel an, die FTP-Pakete von der Protokollierung ausnimmt, oder Sie verwenden die Option, Limits zu setzen. Anstelle der einzelnen Protokoll-Regel sähe eine Kombination aus beidem etwa so aus:

$IPTABLES -A log_it -p tcp --dport 21 -m limit --limit 3/minute -j LOG --log-prefix "SSH :"
$IPTABLES -A log_it -p tcp ! --dport 21 -j LOG --log-prefix "Kein HTTP: "

Der explizite Ausschluss des Ziel-Ports 21 in der zweiten Zeile ist notwendig, weil auch die Protokollfunktion wieder an die Stelle zurückspringt, von der aus sie aufgerufen wurde.

Ausgehende Verbindungen beschränken

Etwas komplexer wird es, wenn Sie die ausgehenden Verbindungen noch restriktiver handhaben wollen. Die Versuchung ist groß, einfach die Policy für die Output-Kette auf "Drop" zu setzen und beispielsweise nur ausgehende Pakete zu Web-Servern zu genehmigen:

#!/bin/bash
LANIF="eth0"
INETIF="ppp0"
IPTABLES=`which iptables`
FTP_SRV="192.168.27.100"
HTTP_SRV="192.168.27.101"
$IPTABLES -P INPUT DROP
$IPTABLES -P FORWARD DROP
$IPTABLES -N log_it
$IPTABLES -A log_it -j LOG --log-prefix "Kein HTTP: "
$IPTABLES -A PREROUTING -t nat -i $INETIF -p tcp --dport 21 -j DNAT --to-destination $FTP_SRV
$IPTABLES -A PREROUTING -t nat -i $INETIF -p tcp --dport 80 -j DNAT --to-destination $HTTP_SRV
$IPTABLES -A INPUT -i $INETIF -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A INPUT -i $LANIF -j ACCEPT
$IPTABLES -A FORWARD -p tcp ! --dport 80 -j log_it
$IPTABLES -A FORWARD -i $INETIF -d $FTP_SRV -p tcp --dport 21 -j ACCEPT
$IPTABLES -A FORWARD -i $INETIF -d $HTTP_SRV -p tcp --dport 80 -j ACCEPT
$IPTABLES -A FORWARD -i $INETIF -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A FORWARD -i $LANIF -p tcp --dport 80 -j ACCEPT
$IPTABLES -A POSTROUTING -t nat -o $INETIF -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward

Die Maßnahme hat nämlich nicht nur den gewünschten Effekt. Sie verhindert auch ganz effektiv den Zugriff auf externe Mail-Server und schneidet Sie damit von diesem Kommunikationsweg ab. Je nachdem, wie Sie ihre Mail beziehen und versenden, müssen Sie unterschiedliche Schritte ergreifen.

Mail-Server einbinden

Die einfachste Variante ist die, bei der ein Mail-Server im LAN eingehende Nachrichten von einem externen System bezieht und auch an dieses versendet. Hier sind beide Kommunikationspartner bekannt und können direkt in der Konfiguration berücksichtigt werden:

MAIL_INT="192.168.27.200"
MAIL_EXT="62.146.34.194"
$IPTABLES -A FORWARD -i $LANIF -s $MAIL_INT -d $MAIL__EXT -p tcp --dport 110 -j ACCEPT
$IPTABLES -A FORWARD -i $LANIF -s $MAIL_INT -d $MAIL_EXT -p tcp --dport 25 -j ACCEPT

Wie deutlich zu sehen ist, müssen Sie für ein restriktives Firewall-Setup alle Anwendungen und deren zugehörigen Ports kennen, um ein funktionierendes System auf die Beine stellen zu können. Dabei sind auch die unterschiedlichen Arbeitsweisen der Applikationen zu berücksichtigen.

Sendet beispielsweise Ihr interner Mailserver ausgehende Nachrichten direkt an die zuständigen Mailserver der Empfänger, müssten Sie die zweite der obigen Zeilen etwas abändern:

$IPTABLES -A FORWARD -i $LANIF -s $MAIL_INT -p tcp --dport 25 -j ACCEPT

Traffic-Shaping

Neben den diversen Filteroperationen lässt sich Netfilter auch dazu einsetzen, den Datenstrom flüssiger fließen zu lassen. Normalerweise ist es nämlich so, dass in den aktuell verwendeten IPv4-Netzen keinerlei bevorzugte Datenpakete existieren. Erschwerend kommt hinzu, dass die Leitung ins Internet in der Regel deutlich weniger Bandbreite besitzt als das LAN, über das die Daten beispielsweise beim DSL-Modem angeliefert werden.

Senden nun viele Anwender Daten in Richtung Internet, entsteht eine Warteschlange, in die sich die Pakete in der Reihenfolge ihres Eintreffens einreihen. Jetzt passiert es häufig, dass vor einer eigentlich recht kurzen Bestätigung über ein eingegangenes Paket (ACK) etwa eine ziemlich umfangreiche Mail mit einem großen Dateianhang in der Warteschlange steht. Bis das ACK-Paket endlich an die Reihe kommt, hat die Gegenstelle schon längst aufgehört, auf die Bestätigung zu warten und die Daten erneut gesendet. Mit viel Pech ereilt das nächste ACK-Paket aber dasselbe Schicksal - für den Anwender entsteht der Eindruck, die Internet-Verbindung sei ausgefallen oder zumindest gestört.

Abhilfe schafft hier der Hierarchical Token Bucket (HTB), der in den neueren Kernel-Versionen bereits integriert ist. Mit seiner Hilfe lässt sich die verfügbare Upstream-Bandbreite quasi beliebig in verschiedene Kanäle aufteilen. Zur Verwaltung der Kanäle nutzt HTB eine Baumstruktur, bei der jeder Unterkanal einen eindeutigen Elternkanal besitzt.

Hierarchical Token Bucket

Das Schöne an HTB ist, dass es den Kanälen sowohl eine garantierte Mindestbandbreite bietet wie auch die Option, dass gerade nicht ausgelastete Kanäle ihre freie Kapazität an andere Kanäle abgeben. Um beispielsweise für einen Standard-DSL-Anschluss mit 128 kbit/s zwei Kanäle anzulegen, sind folgende Kommandos notwendig:

tc qdisc add dev eth1 root handle 1: htb default 10
tc class add dev eth1 parent 1: classid 1:1 htb rate 126kbps
tc class add dev eth1 parent 1:1 classid 1:10 htb rate 110kbps ceil 126kbps
tc class add dev eth1 parent 1:1 classid 1:11 htb rate 16kbps ceil 126kbps

Diese Kommandos richten eine so genannte Qdisc für das Netzwerk-Interface eth1 ein, an dem das DSL-Modem angeschlossen ist. Zusätzlich wird eine Wurzelklasse angelegt, für die eine Datenrate knapp unter der Leistungsfähigkeit der Uplink-Verbindung angegeben ist. Der Grund hierfür ist, dass sich auf diese Weise der Flaschenhals vom DSL-Modem zur Netzwerkkarte verlagert. Nur dort können Sie die notwendigen Kanäle einrichten und steuern, in welcher Reihenfolge die Pakete zum DSL-Modem gelangen.

Schließlich erzeugen die Kommandos noch zwei Unterklassen, von denen eine von Haus aus 110 kbit/s zugeteilt bekommt, die andere hingegen 16 kbit/s. Über den nachgestellten Parameter ceil 126kbps teilen Sie dem System mit, dass jede der Unterklassen die volle Bandbreite nutzen darf, sofern diese verfügbar ist.

Pakete einsortieren

Nun müssen Sie lediglich dafür sorgen, dass durch den Router laufende Datenpakete in die richtigen Klassen einsortiert werden. Eine erste Vorauswahl findet sich bereits in der geschilderten Klassendefinition.

Der Parameter default 10 in der ersten Befehlszeile legt fest, dass alle nicht anderweitig markierten Pakete in der Klasse 10 des zur Qdisc 1 gehörenden Kanals landen - also in dem Kanal, dem die höhere Bandbreite zugeordnet ist. Es sind also lediglich noch die Pakete auszufiltern, die über den zweiten Kanal in den Datenstrom einzustreuen sind. Dazu müssen Sie zunächst dem HTB-Filter mitteilen, woran er diese Pakete erkennen kann:

tc filter add dev eth1 parent 1: protocol ip prio 1 handle 1 fw classid 1:11

Wichtig ist hier vor allem die Zahl, die hinter dem Parameter handle steht, in diesem Fall also 1. Für ausgehende Pakete, die den Weg über die spezielle Warteschlange nehmen sollen, muss nun die entsprechende Markierung gesetzt werden. Das kann wieder über den Netfilter erfolgen:

$IPTABLES -A FORWARD -t mangle -p tcp --dport 21 -j MARK --set-mark 1
$IPTABLES -A FORWARD -t mangle -p tcp --dport 22 -j MARK --set-mark 1
$IPTABLES -A FORWARD -t mangle -p tcp --tcp-flags ACK ACK -j MARK --set-mark 1

Damit landen alle Pakete für SSH-Verbindungen, FTP-Steuernachrichten und Bestätigungen für eingetroffene Daten in der speziell für sie reservierten Klasse, da sie per --set-mark 1 das von HTB erwartete Flag gesetzt erhalten.

Ausblick und Warnung

Das Aufsetzen einer funktionierenden Firewall ist nicht sonderlich schwer. Ob das Resultat dann aber auch sicher ist, steht auf einem anderen Blatt. Die Informationen in diesem Beitrag können nur den Grundstein zum Verständnis des Linux-Paketfilters und seiner Arbeitsweise legen. Ohne das Studium weiterer Literatur ist die Wahrscheinlichkeit recht hoch, dass Sie eine Firewall aufsetzen, die unsicherer ist als ein Gerät aus dem Elektromarkt um die Ecke.

Testen Sie Ihre Firewall gründlich - und zwar nicht in einer Produktiv-Umgebung, sondern in einem Test-Szenario. Zwar sind alle hier wiedergegebenen Beispiele so ausgelegt, dass keine Probleme auftreten sollten, eine Garantie dafür gibt es aber nicht. Im Zweifel sind es zunächst Sie, den sich die Kollegen als Sündenbock ausgucken. Denken Sie daran und handeln Sie entsprechend. (jlu)