Linux iptables-Firewall Einführung

Winfried Mueller, www.reintechnisch.de, Start: 20.06.09, Stand: 16.05.13

Iptables ist die zentrale Firewall in Linuxsystemen und im netfilter-System eingebunden. Über damit erstellte Regelsätze wird der Netzwerkverkehr genau geregelt. Wer das erste mal solche Regelsätze sieht, wird dies als sehr kompliziert empfinden. Und so werden ofmals irgendwelche Regelsätze vorgefertigt im Internet aufgesammelt und unverstanden benutzt. Nach dem Motto: "Hauptsache, es funktioniert!" Aber gerade bei Sicherheitsthemen sollte man genau und detailiert wissen, was man tut.

Grundsätzlich arbeitet iptables, wie man das von vielen anderen Firewalls her kennt: Netzwerkpakete werden geprüft. Hierfür gibt es mehrere Regelsätze, die Schritt für Schritt durchlaufen werden. Man spricht auch von einer Kette (Chain), in der die Regeln eingereiht sind.

Eine Regel beschreibt genau, für welche Art von Paketen sie zuständig ist und was passieren soll, wenn so ein passendes Paket auftaucht. Typischerweise gibt es 2 Möglichkeiten: Das Paket wird durchgelassen oder verworfen. Die erste Regel, die passt, ist entscheidend, alle weitere Regeln in der Kette werden nicht mehr berücksichtigt. Dies zeigt auch, dass die Reihenfolge wichtig ist, mit der man Regeln in die Kette ablegt. Denn passen mehrere Regeln auf ein Paket, entscheidet immer die erste Regel.

Trifft keine Regel, ist der Test also am Ende der Kette angelangt, greift eine Default-Regel.

Neben dieser zentralen Funktionalität - Pakete durchzulassen oder zu verwerfen - hat die Firewall weitere Aufgaben. Beim Eintreffen bestimmter Bedingungen kann man Informationen in Logfiles schreiben. Und NAT (Network Address Translation) ist auch ein wichtiges Thema. Hier geht darum, Ziel- oder Absenderadressen von Netzwerkpaketen nach bestimmten Regeln auszutauschen. Die bekannteste NAT ist das Masquerading, was fast jedes Rechnersystem nutzen muss, um lokale Netze ans Internet anzubinden. Nach dem Motto: "Die Verteilung der Pakete aus dem Internet an die einzelnen internen Clients bleibt unsere Sache."

Filterketten INPUT, OUTPUT, FORWARD

Zum Filtern von Paketen gibt es 3 wichtige Ketten, die beliebig viele Regeln aufnehmen können. INPUT kümmert sich um alle Pakete, die reinkommen, OUTPUT um alle Pakete, die raus gehen und FORWARD um alle Pakete, die vom System lediglich weitergeleitet, also geroutet werden. Beginnen wir mit der INPUT-Kette.

Netzwerk-Pakete, die zum Host geschickt werden, gelangen zuerst zur INPUT-Kette. Hier kann eine beliebige Anzahl von Regelsätzen definiert sein, die Schritt für Schritt durchlaufen werden. Greift eine ACCEPT- oder DROP-Regel, wird das Paket durchgelassen oder verworfen. Alle weiteren Regeln in der Kette (=Chain) sind dann nicht mehr relevant. Die Filterkette wird also nach dem Motto durchlaufen: "Regel für Regel, bis ich eine klare Antwort bekomme, was mit dem Paket werden soll."

Beispiel:

 iptables -A INPUT -i eth0 -j ACCEPT

Diese Regel lässt alle Pakete passieren, die über eth0 hereinkommen. "iptables" ist der zentrale Befehl, mit dem wir alle Regeln festlegen können. "-A INPUT" hängt eine neue Regel in die INPUT-Kette. "-i eth0" legt den Bezug nur auf das Netzwerk-Interface eth0 fest. Und "-j ACCEPT" ist die klare Antwort, was mit Paketen passieren soll, auf die die Regel passt: Sie sollen akzeptiert, also durchgelassen werden.

Beispiel:

 iptables -A INPUT -s 192.168.0.7 -d 192.168.0.8 -j ACCEPT

Diese Regel filtert nun etwas konkreter. Es werden nämlich nur Pakete von "192.168.0.7" (-s = Source) nach "192.168.0.8" (-d = Destination) durchgelassen.

Wie man sieht, spezifiziert man im Regelsatz genau, welche Bedingungen es braucht, damit eine bestimmte Behandlung ausgeführt werden soll. Genauso, wie man Regeln hat, die Pakete akzeptieren, kann man auch welche anlegen, die Pakete ablehnen:

 iptables -A INPUT -i eth0 -p ICMP -j DROP

Hier werden also alle Pakete, die über eth0 reinkommen, mit dem Protokoll ICMP (-p ICMP) abgelehnt. So kann man diesen Host über eth0 also nicht mehr anpingen.

Wichtig ist nun noch, dass jede Kette ein Standard-Verhalten hat. Nach dem Motto: "Was soll mit einem Paket passieren, auf das keine Regel passt?" Dies wird als "Default-Policy" bezeichnet und so festgelegt:

 iptables -P INPUT DROP

Weil eine Firewall möglichst restriktiv sein soll, ist die Defaultregel DROP sehr sinnvoll. Was der Bauer nicht kennt, frisst er nicht. Wir wollen uns ja nicht den Magen verderben...

Wenn wir beginnen, mit der Firewall zu experimentieren, braucht es unbedingt noch ein paar weitere Befehle. Wir müssen angelegte Regeln z.B. wieder aus einer Kette entfernen können. Hier eine Zusammenfassung der wichtigsten Befehle:

 
Alle Regeln aus INPUT entfernen: 
iptables -F INPUT 

Alle Regeln der INPUT-Kette auflisten:
iptables -L INPUT -nv

Regel Nr 1 aus der INPUT-Kette entfernen:
iptables -D INPUT 1

Regel nicht anhängen sondern ganz vorne hinzufügen:
iptables -I INPUT 1

Achtung: Arbeitet man nicht direkt an der Console sondern ist über ssh auf dem Server eingeloggt, muss man sehr vorsichtig beim Experimentieren sein. Schnell erstellt man eine Regel, die den ssh-Verkehr abklemmt. Dann hat man den Kontakt zum Server verloren. Spätestens jetzt muss man doch zur Console oder der Rechner braucht einen entfernten Reboot.

Wie wir gesehen haben, kann man beliebig viele Bedingungen in eine Filterregel schreiben. Hier ein paar Möglichkeiten, was es so an Bedingungen gibt:

 
Bestimmter Absender (Absender-IP = 192.168.0.16):
iptables -A INPUT -s 192.168.0.16 ...

Bestimmter Absender nicht (alles, außer 192.168.0.16):
iptabls -A INPUT -s ! 192.168.0.16 ...
(Achtung: Das "!" muss auf der Bash-Eingabezeile maskiert werden "\!")

Bestimmtes Absender-Netzwerk (Absender-Range = 192.168.0.x)
iptables -A INPUT -s 192.168.0.0/24 ...

Bestimmtes Absender-Netzwerk (Absender-Range = 192.168.x.x)
iptables -A INPUT -s 192.168.0.0/16 ...

Bestimmter Ziel-Host (Ziel = 192.168.0.5)
iptables -A INPUT -d 192.168.0.5

Bestimmtes Ziel-Netzwerk (192.168.0.x)
iptables -A INPUT -d 192.168.0.0/24 ...

Bestimmte Netzwerk-Schnittstelle
iptables -A INPUT -i eth0 ...

Bestimmtes Protokoll
iptables -A INPUT -p tcp ...
iptables -A INPUT -p udp ...
iptables -A INPUT -p icmp ...

Bestimmter Absender-Port (Port 80)
(Achtung, Protokoll muss davor angegeben werden)
iptables -A INPUT -p tcp --sport 80

Bestimmter Ziel-Port (Port 22)
(Achtung, Protokoll muss davor angegeben werden)
iptables -A INPUT -p tcp --dport 22

Somit hat man nun schonmal eine ganze Menge an Material, womit man rumspielen und testen kann. Das Vorgehen ist immer gleich: Vor jedem Experiment erstmal die Kette leeren und die Default-Policy setzen, dann eine oder mehrere Regeln in die Kette schieben und dann testen, ob diese tatsächlich so filtert, wie gewünscht. Natürlich kann man mehrere Befehle auch in eine Bash-Skript schreiben.

 
#!/bin/bash


### Init
iptables -F INPUT
iptables -P INPUT DROP

### Test-Regeln
iptables -A INPUT -i eth0 --dport 80 -j ACCEPT


Achtung: Fehler in einem Bash-Skript führen zum Abbruch dessen. Damit hat man die Firewall evtl. in einen sehr ungünstigen Zustand versetzt, weil ein Teil der Regeln schon eingetragen ist, ein anderer Teil noch nicht. Gerade wenn man über ssh arbeitet, kann man sich durch Syntaxfehler im Skript schnell abhängen. Am prüft man die Syntax des Skripts erstmal mit bash -n skriptname.

Die OUTPUT-Kette funktioniert im Prinzip genauso. Alle Pakete, die von diesem Rechner nach draußen gehen sollen, werden in dieser Kette gefiltert. Ein schöner Regelsatz bestimmt hier eine Minimal-Firewall zur Anbindung ans Internet, die schon viel bewirkt:

 
#!/bin/bash

### Init
iptables -F INPUT
iptables -F OUTPUT
iptables -P INPUT DROP
iptables -P OUTPUT DROP

### Nach draußen darf alles...
iptables -A OUTPUT -o eth0 -j ACCEPT

### Nach innen darf nur das, was von innen initiiert wurde
iptables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT


Hier ist eth0 die Schnittstelle, mit der der Rechner ans Internet angebunden ist. Mit der Output-Regel haben wir alles erlaubt. Es darf also jedes Paket von drinnen nach draußen.

Aber was lassen wir von draußen nach drinnen? Nichts? Dann würde keinerlei Information aus dem Internet zurückfließen - keine Webseite und keine Mail würde hereinkommen. Dann alles erlauben? Auch das geht nicht, denn wir wollen uns ja gerade vor vielem aus dem Internet schützen.

Hier kommt jetzt das Konzept zum Einsatz, das iptables die Art von Paketen unterscheiden kann. Hierzu muss man wissen, dass in der Regel Verbindungen aufgebaut werden. Ein Kommunikationspartner startet eine Verbindung, in dem er ein Paket vom Status "NEW" an den Zielpartner schickt. Dieser kann nun antworten, wobei die Antwortpakete den Status "ESTABLISHED" oder "RELATED" haben. Sie beziehen sich also auf eine bereits bestehende Verbindung. Schickt nun der Initiator dieser Verbindung weitere Pakete an das Ziel, sind diese Pakete nun auch vom Typ "ESTABLISHED" oder "RELATED". Sie gehören ja zu einer bereits bestehenden Verbindung.

Nur so ist es möglich, dass wir eine mächtige Regel aufstellen können: "Von außen darf niemand zu unserem Rechner eine Verbindung aufbauen. Wenn wir aber eine Verbindung nach außen aufbauen, dürfen alle Pakete rein, die zu dieser Verbindung gehören."

Wenn ich also sage: "Webserver xyz, gib mir diese Seite.", dann lässt die Firewall die Antwort durch. Wenn aber im Internet irgendein verrückter Webserver meint, mich anzusprechen, dann wird dies verweigert. Genau dies macht die obige Regel:

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

"-m" steht für match und "state" beschreibt genauer, um welchen Match es geht. Es soll hier der Status (state) überprüft werden. Mit "--state" wird genauer angegeben, welche Staties gemeint sind: ESTABLISHED,RELATED. Würden wir hier auch noch NEW hinzufügen, dann dürften auch von außen beliebige Verbindungen initiiert werden.

Der Status NEW ist übrigens für Regeln wichtig, die die Initiierung eine Verbindung definieren. Die also angeben, wer eine Verbindung initiieren darf.

Zurück zur OUTPUT-Kette. Hier können wir genauso Regeln definieren, was ein Host nach draußen schicken darf. Die Möglichkeiten sind ganz ähnlich, wie bei der INPUT-Kette.

Wenn man hier das Interface angibt, muss man -o und nicht -i verwenden. Denn -i steht für Input-Interface und -o für Output-Interface. Wie wir später sehen werden, gibt es Regeln, die auf mehrere Interfaces wirken, deshalb braucht es diese Unterscheidung.

Beispiel:

 iptables -A OUTPUT -o eth0 -p TCP --dport 80 -j ACCEPT

Hier wird also alles, was über eth0 zum Zielport 80 per tcp rausgehen soll, durchgelassen.

Achtung: Viele Programme benötigen den Austausch über das interne virtuelle Interfaces lo (loopback-Interface). Wenn man nun beginnt, mit der Firewall zu experimentieren und die Standard-Policy der INPUT/OUTPUT Kette auf DROP setzt, ist dieser Netzwerkverkehr blockiert. Insofern sollte man immer zuerst einmal den Verkehr über lo freischalten. Dies geht so:

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

Mit den beiden Ketten INPUT und OUTPUT kann man schon sehr viel anstellen. Diese bettreffen aber nur Pakete, die von diesem Rechner aus raus sollen oder an diesen Rechner gerichtet sind, auf dem iptables läuft. Linux-Rechner fungieren aber oft auch als Router, leiten also lediglich Pakete weiter. Typisches Beispiel wären Windows-Rechner, der über einen Linuxrechner ans Internet angekoppelt werden. Pakete vom Windows-Client sind also nicht für den Linuxrechner bestimmt, sondern werden von diesem ins Internet weitergeleitet (geroutet). Der Linuxrechner fungiert hier also nur als Router oder Weiterleiter (Forwarder).

Solche Pakete gehen nicht über INPUT und OUTPUT. Hierfür gibt es die Kette FORWARD.

Routing betrifft typisch 2 Netzwerkadapter - über einen kommt ein Paket rein und es soll über ein anderes raus. Diese gibt man in den Regel mit "-i" (Input-Device) und "-o" (Output-Device) an.

 
### Netzwerkkarten
#   eth0 = Internetanbindung
#   eth1 = internes Netz mit diversen Windows-Clients


### Init
iptables -F FORWARD
iptables -P FORWARD DROP


### Regeln

# Windows-Clients dürfen beliebige Verbindungen nach außen aufbauen
iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT

# Pakete von aufgebauten Verbindungen dürfen an die Windows-Clients
iptables -A FORWARD -i eth0 -o eth1 -m state --state ESTABLISHED,RELATED -j ACCEPT

Diese Regeln sorgen also dafür, dass in die eine Richtung alles fließen darf, in die andere Richtung aber nur die Pakete, die zu bereits bestehenden Verbindungen gehören.

Auch in Forward-Regeln kann man die gleichen Bedingungen nutzen, wie wir sie auch schon von der INPUT/OUTPUT Kette her kennen.

Masquerading

Masquerading ist eine Art Netzwerkverbindung, bei der der Empfänger den Absender nicht direkt kennt. Im realen Leben kennen wir dies:

  • Jemand, der eine Kontaktanzeige aufgibt, nutzt eine Ersatzadresse mit Chiffre, unter der seine Post hingeleitet wird. Der Absender kennt die Empfänger-Adresse nicht.
  • Wenn man in großen Firmen anruft, muss man oft über die Zentrale gehen. Diese ist Vermittler zu konkreten Mitarbeitern. Die direkte Durchwahl erfährt man nicht oder es ist auch gar nicht möglich, eine direkte Verbindung herzustellen.

Hat man ein internes Netz aufgebaut, nutzt man hierfür IP-Adressen, die nicht im Internet vorkommen, typisch z.B. 192.168.0.x. Diese Adresse ist nicht eindeutig, denn es gibt Millionen interner Netze, die diesen Adressbereich verwenden. Ein Host im Internet könnte ein Antwortpaket nicht mehr an uns zurückschicken.

Was wir mindestens im Internet bekommen, ist eine dynamische IP-Adresse und die ist für die Zeit eindeutig, so lange wir Online sind. Diese IP-Adresse wird beim Verbinden einem Netzwerk-Device zugeordnet.

Wenn nun dieser Rechner auch als Router fungiert, um dahinterliegenden Clients den Internetzugang zu ermöglichen, so muss er hierfür sorgen:

  • Bei allen Paketen, die von den Clients kommen, muss die interne Absender-Adresse ausgetauscht werden. Denn diese ist fürs Internet nicht brauchbar. Stattdessen wird die dynamische IP eingetragen, die im Internet eindeutig ist.
  • Pakete, die aus dem Internet an die dynamische IP zurückgeschickt werden, müssen überprüft werden. Handelt es sich dabei um Verbindungen zu internen Clients, muss nun wieder die Zieladresse ermittelt werden, um das Paket entsprechend weiterzuleiten.

Von draußen sieht es so aus, als ob Pakete nur vom Rechner kommen, dem die dynamische IP zugewiesen wurde. Innen jedoch werden die Pakete an die jeweiligen Clients weitergeleitet. Damit iptables so etwas leisten kann, muss es sich natürlich sämtliche offenen Verbindungen merken. Zu jeder dieser Verbindung wird auch festgehalten, zu welchem internen Client diese gehört. Damit ist es iptables dann möglich, die reinkommenden Pakete wieder eindeutig zurückzuverteilen.

Masquerading verwendet eine andere Tabelle. Eine Tabelle ist ein Set von Ketten, die an bestimmten Punkten im System angeordnet sind. Bisher haben wir die Tabelle Filter verwendet, Masquerading verwendet hingegen die Tabelle NAT. NAT steht für Network-Adress-Translation, sie hat also den Zweck, Adressen nach bestimmten Richtlinien zu transformieren.

Diese Übersicht zeigt die Struktur und wie die Ketten untereinander angeordnet sind. Gelb sind die Ketten der Tabelle Filter, blau die Ketten der Tabelle NAT. Genaugenommen gibt es noch 2 weitere Tabellen, aber die werden nur selten verwendet, weshalb ich sie hier der Einfachheit halber aus der der Darstellung herausgelassen habe.

Die Strukturübersicht zeigt, wie ein Paket von links nach Rechts durch die unterschiedlichen Ketten wandert und zum Schluß, wenn dies zugelassen wird, rechts ankommt. Hier zeigt sich auch, dass die Ketten INPUT und OUTPUT nur durchwandert werden, wenn Pakete direkt an den Rechner gehen bzw. von diesem erzeugt werden. Weitergeroutete Pakete, die nicht für diesen Rechner bestimmt sind gehen hingegen durch die FORWARD-Kette. Es zeigt auch, dass jedes eingehende Paket zuerst durch die NAT-Kette PREROUTING geht und das jedes Paket am Schluß durch die NAT-Kette POSTROUTING geht, egal, ob es von einem lokalen Prozess kommt oder einfach nur durchgeroutet wurde. Lediglich die NAT-Kette OUTPUT wird nur von Paketen durchwandert, die direkt auf dem System von einem lokalen Prozess geschickt wurden.

Für das Masquerading wählen wir die Kette POSTROUTING:

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

Diese Regel besagt, dass alle Pakete, die über eth0 den Rechner verlassen als Absenderadresse die von eth0 bekommen. Natürlich merkt sich die Firewall alle Verbindungen, um bei zurückkommenden Paketen wieder den Rückaustausch zu machen: Als Ziel wird nun wieder die IP des Ursprungs-Clients eingetragen und das Paket weitergeschickt.

So gelingt es also, dass beliebige Clients im internen Netz über den Linux-Router Pakete ins Internet schicken können und von dort auch Antwort erhalten.

Es zeigt sich hier auch, dass Masquerading zwar von der Firewall durchgeführt wird, weil sie alle Voraussetzungen dafür hat und es deshalb nahe liegt. Es ist aber nicht die klassische Aufgabe einer Firewall - nämlich als Türsteher zu fungieren, um Pakete anzunehmen oder abzulehnen.

Source-NAT und Destination-NAT

Masquerading hatten wir zuvor besprochen und es ist eine besondere Form des Source-NAT. Es wird ja die Quell-Adresse (bzw. Absenderadresse) ausgetauscht, bevor das Paket weitergeschickt wird. Masquerading setzt hierbei automatisch die Adresse des Ausgangs-Interfaces ein. Man kann mit dem Ziel SNAT aber auch statische Adressen nutzen.

Destination-NAT tauscht hingegen die Zieladresse aus. Hierfür ein typisches Szenario: Vom Internet soll ein Mailserver und Webserver erreicht werden können. Diese nutzen beide die gleiche IP-Adresse, die einem zugeteilt wurde. Pakete, die nun bei uns ankommen, können geprüft werden, um sie dann intern 2 physikalisch getrennten Rechnern (dedizierten Servern) weiterzuleiten. Der externe Teilnehmer kommuniziert also nur mit einer IP und einem Host, intern gibt es aber mehrere Ziel-Hosts, an die verteilt wird. Das ist Destination NAT oder kurz DNAT.

Weil dies fortgeschrittene Techniken sind, möchte ich sie hier nicht vertiefen. Es ist aber gut zu wissen, dass es sie gibt.

Logging

Normal erstellen wir Regeln mit einem Ziel: Ein Paket soll durchgelassen oder verworfen werden. Man kann aber nach dem gleichen Prinzip auch Regeln erstellen, die nur einen Logeintrag machen. Das Besondere an diesen Regeln ist, dass bei Übereinstimmung trotzdem auch weitere Regeln der Kette bearbeitet werden. Denn es wird ja noch nach einer Regel gesucht, die ganz klar angibt, was mit dem Paket geschehen soll.

 iptables -A INPUT -i eth0 -m state --state NEW -p TCP --dport ssh -j LOG

Diese Regel loggt also jeden ssh-Verbindungsaufbau. Im syslog-File kann man nachschauen, was genau geloggt wird. Neben Ziel und Quell-IP findet man noch den Port, die MAC-Adresse, das Protokoll und weitere Infos zum Paket.

Um bestimmte Pakete der Firewall im Log besser zu finden, kann man einen statischen Text angeben, der bei bestimmten Logeinträgen benutzt wird.

 iptables -A INPUT -i eth0 -m state --state NEW -p TCP 
  --dport ssh -j LOG --log-prefix "SSH: "

Damit wir nicht einem Logfile-Spamming zum Opfer fallen, begrenzt man am besten die Einträge z.B. auf maximal 100 pro Stunde.

 iptables -A INPUT -i eth0 -m state --state NEW -m limit 100/hour -p TCP 
  --dport ssh -j LOG --log-prefix "SSH: "

Hiermit geben wir an, dass diese Regel maximal 100 mal pro Stunde greift. Danach ignoriert iptables die Regel einfach. Übrigens: Diese Limitierung ist auch für echte Filterregeln verwendbar. Man könnte z.B. den ssh-Verbindungsaufbau auf 2 pro Minute beschränken.

Accounting - Pakete zählen

Schauen wir uns die Infos an, die über iptables -l -nv ausgegeben werden. Zu jeder Regel findet man die Anzahl Pakete, die darüber gelaufen sind. Und auch die transportierte Datenmenge. Diese Information kann man auf vielfältige Weise nutzen. Beim Debugging erkennt man, ob Regeln überhaupt greifen. Für die Leistungsüberwachung eines Servers kann es wichtig sein, den Datendurchsatz über bestimmte Interfaces zu beobachten. Und bei knappen oder kostspieligen Ressourcen kann es wichtig sein, zu wissen, wer wieviel Netzwerkaufkommen verursacht.

Bisher haben wir nur Firewall-Regeln kennengelernt, die durch "-j" ein Ziel hatten. Wenn also die Regel greift, sollte irgendwas passieren - ein Paket wurde durchgelassen (ACCEPT), verworfen (DROP/REJECT) oder geloggt (LOG).

Man kann nun aber auch Regeln angeben, die kein Ziel haben. Wozu nutzlose Regeln? Der einzige Nutzen besteht darin, die Pakete zu zählen, die über diese Regel gelaufen sind.

Regeln ohne Ziel brechen die Kette (Chain) natürlich nicht ab. Genauso wie Regeln mit dem Ziel "-j LOG". Es wird ja weiter nach einer Regel gesucht, die angibt, was mit dem Paket passieren soll. Wird eine Regel ohne Ziel durchlaufen und greift sie, wird lediglich der zugehörige Paket-Counter um 1 erhöht und die transportierten Bytes zum Bytecounter hinzugerechnet.

Weil man mit Firewall Regeln sehr mächtige Bedingungen festlegen kann, kann man sehr spezifisch die Anzahl von Paket-Transfers überwachen.

Beispiele:

 
# Alle Pakete von eth0 über eth1 zu einem bestimmten Host
iptables -A FORWARD -i eth0 -o eth1 -d 192.168.1.6

# Alle Pakete zu einem Host aus dem WWW
iptables -A FORWARD -i eth0 -o eth1 -d 192.168.1.6 --sport www

# ICMP Pakete zählen
iptables -A INPUT -i eth0 -p icmp

Natürlich kann man sich Skripte schreiben, die die Zählerstände übernehmen und die Infos weiter aufbereiten. Hierfür ist es auch wichtig, die Zählerstände zyklisch zurücksetzen zu können. Dies geht mit dem Befehl iptables -Z.

Wird der Zählerstand ausgelesen und dann zurückgesetzt, hat man eine Beobachtungslücke. Es kann sein, dass zwischen dem letzten Auslesen und dem Zurücksetzen Pakete eingelaufen sind, die man so nun nicht mitbekommen hat. Ist dies kritisch, benutzt man besser iptables -L -v -Z. Dieser Befehl liest aus und setzt dann sofort zurück, so dass keine Lücke entsteht.

Für Skripte ist eine exakte Ausgabe der Paket- und Byteanzahl leichter zu verarbeiten. Standardmäßig wird ja metrisch mit K für Kilobyte und M für Megabyte verwendet. Der Schalter -x bewirkt die exakte Ausgabe.

Sonstiges

FTP

FTP ist ein ekeliges Protokoll, weil es aus dem Rahmen fällt und nicht mit einfachen Firewall-Regeln zu erschlagen ist. Es wird nämlich nicht nur eine Verbindung über einen definierten Port aufgebaut. Vielmehr werden weitere Ports dynamisch vereinbart, über die der Datenverkehr läuft. Und dieser Umstand macht es unmöglich, FTP einfach zu filtern. Desalb gibt es hier auch viel Regelsätze, die die Firewall stark aufweichen, z.B. werden alle höherwertigen Ports grundsätzlich freigeschaltet.

Es gibt aber Abhilfe, wie doch wieder alles ganz einfach und sicher wird. Hierfür muss in den Kernel zuerst einmal das Modul ip_conntrack_ftp geladen werden.

 modprobe ip_conntrack_ftp

Dieses Modul sorgt im Hintergrund dafür, dass ftp funktioniert, lässt also den entsprechenden Austausch zu, insofern man den Verbindungsaufbau zulässt. Es reichen dann die einfachen Regeln:

 
iptables -A FORWARD -i eth1 -o eth0 -m state --state NEW -p TCP --dport 21 -j ACCEPT
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

ICMP

Möchte man nur auf ganz bestimmte ICMP-Pakete antworten, z.B. nur ein Echo-Request von innen nach außen zulassen, so kann man diese Regel nutzen:

 iptables -A FORWARD -i eth1 -o eth0 -p ICMP --icmp-type echo-request -j ACCEPT

Natürlich braucht es eine entsprechende Rückregel, typisch eine pauschale Rückregel, die für alles genutzt wird:

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

Einbindung in Debian/Ubuntu

Am besten schreibt man sich ein Skript, in dem man alle Firewall-Regeln aufnimmt und welches man z.B. unter /etc/fw-init ablegt. Unter /etc/network/if-pre-up.d legt man einen symbolischen Link zum Skript. Dann wird die Firewall beim Bootvorgang gestartet, noch bevor die Netzwerk-Interfaces gestartet werden.

Kurzreferenz

 
Filterregeln auflisten:
iptables -L -nv
iptables -t nat -L
iptables -t mangle -L

Filterregeln löschen:
iptables -F
iptables -t nat -F
iptables -t mangle -F
iptables -X
iptables -t nat -X
iptables -t mangle -X

Filterregel anhängen:
iptables -A <Kette> <Regel>

Filterregel einfügen an bestimmte Stelle:
iptables -I <Kette> <num> <Regel>

Filterregel num ersetzen:
iptables -R <Kette> <num> <Regel>

Filterregel löschen:
iptables -D <Kette> <num>

Default-Filter-Policy setzen:
iptables -P <Kette> DROP|ACCEPT|REJECT

lo-Interface freigeben:
iptables -A INPUT  -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

Ziele:
* ACCEPT     - Paket akzeptieren
* DROP       - Paket verwerfen
* REJECT     - Paket verwerfen, Absender erhält Fehlermeldung
* LOG        - Paket loggen
* MASQUERADE - Nur im Zusammenhang mit NAT/MASQUERADE
* SNAT       - Source NAT (nur für Tabelle nat)
* DNAT       - Destination NAT (nur für Tabelle nat)
* RETURN     - beendet die Kette und nutzt Default-Policy

Ziel-Optionen:
REJECT --reject-with icmp-net-unreachable|icmp-host-unreachable|
                     icmp-port-unreachable|icmp-proto-unreachable|
                     icmp-net-prohibited|icmp-host-prohibited|tcp-reset
LOG --log-prefix string
LOG --log-level debug|info|notice|warning|error|crit|alert|emerg
LOG --log-uid


IP-Adressen:
192.168.0.1      - Eine IP-Adresse
192.168.0.0/24   - Netzwerk 192.168.0.x
192.168.0.0/16   - Netzwerk 192.168.x.x
! 192.168.0.1    - Nicht diese Adresse
! 192.168.0.0/24 - Nicht dieses Netzwerk
-m iprange --src-range 192.168.0.50-192.168.0.100  - IP-Range Quelle
-m iprange --dst-range 192.168.0.50-192.168.0.100  - IP-Range Ziel

MAC:
-m mac --mac-source 50:94:77:fc:23:55  - Quell-MAC testen

Bestimmte Protokolle und Ports:
-p tcp|udp|icmp    - Protokoll
-p tcp --dport 80  - Protokoll mit Zielport
-p tcp --sport 80  - Protokoll mit Sourceport
-p tcp -m multiport --dports 22,25,80 - Mehrere Zielports
-p tcp --sport 20:50 - Portbereich 20...50, auch bei --dport möglich
-p tcp --sport www  - Statt Portnummer Klartextangabe (/etc/services)
-p tcp -m multiport --sports 22,25,80 - Mehrere Quellports
-p tcp -m multiprot --ports 22,25,80  - Mehrere Ports (Ziel oder Quelle)
-p tcp --port 80     - Protokoll 

Logging:
-m limit --limit 100/hour            - limitieren
-j LOG --log-prefix "Bad packet: "   - Präfix festlegen

Verbindungs-Zustände:
ESTABLISHED    - Paket zu bestehender Verbindung
RELATED        - Paket bezieht sich auf eine bestehende Verbindung
NEW            - Verbindungsaufbau
INVALID        - Paket kann zu keiner Verbindung zugeordnet werden


Fallstricke

  • Merkwürdiger Effekt: Änderungen am Masquerading führten nicht sofort zu einer Veränderung im Verhalten. Erst wenn 30s ein bestimmter Zugriff nicht mehr erfolgt, wird das Masquerading dann wirklich geändert. Diese Zeitverzögerung ist bei Test völlig verwirrend. Unter welchen Umständen es zu Zeitverzögerungen kommt, ist mir noch nicht ganz klar.

Buchtipps

  • Linux-Firewalls mit iptables & Co.; Ralf Spenneberg, Addison Wesley, ISBN: 3-8273-2136-0; Auch als pdf hier...

Weblinks

Fehler?

Texte reifen mit eurer Hilfe. Schreibt mir, wenn euch Fehler aufgefallen sind. Künftige Leser werden es euch danken.