Jo's Linux Firewall Howto: IP-Filter mit IPChains

Das Routing: Firewall und Masquerading mit IPChains

Hier wird es jetzt doch etwas kompliziert. - Zumindest, wenn man wirklich verstehen will wie das alles funktioniert.

Inhaltsübersicht

– — – — – — – — –

Was sind eigentlich ipchains?

Die ipchains sind eine Kette von Regel zu Filterung und Verarbeitung von IP-Paketen. Damit kann man Pakete zu einzelnen Adressen zulassen oder ausfiltern. Hierbei kann nach Quelladresse, Quellport, Zieladresse, Zielport und Pakettyp unterschieden werden. Das sollte eigentlich für alle Aspekte ausreichen. Für Pakete, welche von einer Regelkette nicht erfaßt werden, wird eine allgemeine Politk (policy) eingestellt. Die kann sein "alles akzeptieren" (also accept) oder "alles abblocken" (also deny).

Neben der Filterung von Paketen erlauben die ipchains auch das Maskieren und Demaskieren von Paketen. Dieses dient dem verstecken lokaler Netzwerkadressen vor dem Internet. Das heißt, daß nach außen alle Pakete vom Gatewayrechner zu kommen scheinen und man nicht (direkt) erkennt, daß dahinter ein ganzes Netz liegt.

– — – — – — – — –

Forwarding

Forwarding bedeuted "Weiterleiten". Das ist der ganze Sinn und Zweck eines Routers - und 1 Firewall ist ja 1 Router mit Filterfunktion. Wenn man den Filter ganz dicht machen will, dann kann man das weiterleiten von Paketen ganz ausschalten! Dann muß die ganze Kommunikation zwischen innen und außen über Proxies bzw. Programme auf der Firewall laufen. Dies ist recht sicher, aber auch recht unbequem, denn viele Angebote im WWW erfodern irgendwelchen speziellen Dienste, die sich in keinem Proxy finden. Schon gar nicht alle in einem. Daher ist es manchmal ganz nützlich, auch den direkten Zugriff aufs Internet zu erlauben.

Wichtig:

In der der Datei /etc/rc.config bzw. mittels Yast, Administration des Systems, Konfigurationsdatei verändern, Die Variable IP_FORWARD auf "yes" setzen. Dies ist die Voraussetzung dafür, das der Rechner überhaupt als Router arbeiten kann. Sonst werden keinerlei Pakete von einem Netzwerk an ein anderes weitergereicht.

Wer ohne Yast lebt, muß einfach die Datei /proc/sys/net/ipv4/ip_forward erzeugen und eine "1" herein schreiben. Damit wird das Forwarding eingeschaltet. Allerdings muß man diese Datei nach jedem Systemstart neu erzeugen. Dies tun die SuSE-Skrips, wenn man wie oben vorgeht, automatisch.

– — – — – — – — –

Network Address Translation (Masquerading)

Eigentlich braucht jede Netzwerkschnittstelle 1 eigene eindeutige IP-Adresse. Diese Adressen sind aber inzwischen relativ knapp. (Unter anderem daher) hat man die sog. Network Address Translation (NAT) erfunden. Eine Form davon kommt unter dem Namen Masquerading bei Gateway wie unserer Firewall zum Einsatz.

Im internen Netz können die Adressen frei vergeben werden - allerdings möglichst ohne Adressen zu verwenden, die auch im Internet auftauchen können. Die Adresse für die Schnittstelle nach außen wird von Zugangsprovider zugewiesen.

Der Router übersetzt die Adressen des lokalen Netzes in Adresse(n), die außerhalb gültig sind. Wie gesagt kann er somit alle Adressen nur in eine einzige übersetzen, den mehr hat er auf der Schnittstelle nach außen ja nicht zur Verfügung. Damit das überhaupt funktionieren kann, bedient er sich der Port-Adressen.

Jedes IP-Paket besitzt außer der Quell- und Zieladresse auch einen Quell- und Zielport. Dabei werden die Portadressen unterhalb 1024 als sog. qualifizierte Ports bezeichnet, die jeweils speziellen Diensten zugeordnet sind. Die Adressen oberhalb 1024 können (mehr oder weniger) frei verwendet werden.

(Stark vereinfachtes) Beispiel: Wenn ein Programm einen Nameserver nach der zu einem Namen gehörenden Adfresse fragen will, so läßt es sich vom Betriebssystem eine freie Portadresse (oberhalb 1024) zuteilen. Nun schickt es ein Paket mit der Anfrage zum Nameserver. Die Quelladresse dieses Paketes ist die IP-Adresse des Rechners auf dem das Programm läuft, der Quellport ist der vom Betriebssystem zugeteilte, also z. B. 192.168.0.12:3097 (IP-Adresse:Port). Die Zieladresse ist die IP-Adresse des Nameservers und der Zielport ist 53 (vgl. /etc/services), also z. B. 192.168.0.1:53 . Die Antwort erfolgt auf genau dem umgekehrten Weg: es werden einfach Quelle und Zieladresse und Port getauscht. Damit weiß das Betriebssystem auch, welches Programm des Paket bekommen soll, welches da von draußen hereinkommt. (nämlich das welches vorher diesen Port zugeteilt bekommen hat.)

Das Masquerading funktioniert recht ähnlich: Der Router erhält ein Paket von 192.168.0.12:3224 für 195.20.225.194:80 (http://www.jwiesemann.de). Er bemächtigt sich eines freien Ports im Bereich zwischen 61000 und 65096 und packt seinen eigenen Absender in das Paket (z. B. 212.101.45.138:62099). Da der angesprochene Webserver an genau diese Adresse mit dem selben Port anworten muß, können die Antworten auch eindeutig zugeordnet werden: aus der Zieladresse 212.101.45.138:62099 wird entsprechend 192.168.0.12:3224.

(Wenn ich mal große Langeweile habe, male ich hierfür noch 1 Bild ;-)

– — – — – — – — –

Filterregeln: Wie funktionieren die IPChains?

Die IPChains sind drei Filter (daher der Plural), die jeweils aus einer Kette (engl. chain) aus Filterregeln bestehen. Dabei durchläuft jedes Paket nacheinander bis zu drei Filterstufen:

Aufbau der IPChains

Als erstes wird das Eingangsfilter (input chain) durchlaufen. Hier kann gefiltert werden welche Pakete aus welcher Quelle überhaupt bearbeitet werden. Anschließend wird im Weiterleitungsfilter geprüft, ob das Paket weitergeleitet werden soll bzw. darf. Zuletzt wird im Ausgangsfilter geprüft, ob an dieses Ziel Pakete gesendet werden dürfen.

Pakete, die für diese Maschine selbst bestimmt sind (localhost), bzw. davon stammen, werden ja nicht weitergeleitet. Sie durchlaufen daher entsprechend nur die input chain oder die output chain.

Nebenbei sei bereits 1 Ausnahme erwähnt, die vermutlich schon beim Betrachten des Bildes aufgefallen ist: Es gibt Pakete, die nicht durch die forward chain gehen, sondern direkt aus der input chain in die output chain. Dies sind Anworten auf maskierte Pakete, die demaskiert werden.
(Na gut, ich gebe zu es gibt da noch mehr Möglichkeiten, aber damit wird das ganze ja nicht übersichtlicher. Und da dies eine einfach Einführung sein soll werde ich hier mehr nicht erklären. Wer mehr wissen will, lerne Englisch und stürze sich auf die Originaldokumentation!)

Für Pakete, welche das gesamte Filter durchlaufen haben, ohne das eine Regel sie traf, gibt es in jedem Filter 1 allgemeine Politik (policy). Dies ist quasi 1 default-Regel.

Dies klingt auf den ersten Blick deutlich komplizierter als ein einzelnes Filter, ist aber deutlich flexibler und dem Problem gut angepaßt. Und wird hoffentlich im Laufe der Lektüre dieser Seite etwas klarer ;-).

Das Programm, welches die einzelnen Regeln der IPChains abarbeitet, ist in den Kernel integriert, läuft also bereits. Es müssen nun zur Laufzeit die Regeln gesetzt werden. Wenn man dies regelmäßig tun will (was ja eigentlich selbstverständlich ist), bietet es sich an, dies von vornherein mit einem Skript zu machen. Die Regeln für die IPChains darf nur root setzen, also muß dieser auch jeweils das Skript starten!

Am Beginn des Skripts setzt man erstmal alles in den Urzustand. Damit kann man dann auch leicht die Einstellungen ändern, indem man 1 zweites Skript verwendet.

#!/bin/sh

# loesche den Inhalt aller Chains
ipchains -F input
ipchains -F forward
ipchains -F output

Danach kann man mit

ipchains -A chain regel [option]

die einzelnen Regeln setzen. Mit -A werden die Regeln jeweils an das Ende der genannten Kette (chain) angehängt und somit in der Reihenfolge abgearbeitet, wie sie im Skript stehen. Um selbst den Überblick zu behalten, ist es sinnvoll, die Regeln 1 chain jeweils zusammen zu schreiben. (Dem Kernel ist dies egal, er bekommt ja jedesmal mitgeteilt, an welche Kette er die Regel anhängen soll.) Die eckigen Klammern um option sollen (wie bei den meisten Syntax-Dokumentationen) anzeigen, das dies eine optionale (!) Angabe ist. Also man kann das angeben, muß es aber nicht.

Die eigentliche Regel besteht dann aus der Maske und der Anweisung, was mit dem Paket zu tun ist. Paßt das Paket zu der Maske, wird die Anweisung ausgeführt.

Die Maske mit der bestimmte Pakete erkannt werden können, kann sich aus verschiedenen Teilen zusammensetzen: Dies sind die Quell- und Zieladresse, der Quelle- und Zielport, das Interface und das Protokoll.

-s adresse
--source adresse

Die Quelladresse kann als Hostname (www.jwiesemann.de), als Netzname oder als IP-Adresse (192.168.0.0) angegeben werden. Bei IP-Adressen kann zusätzlich noch die Netzmaske (192.168.0.0/255.255.255.0) oder die Anzahl der gültigen Bits von links (192.168.0.0/24) angegeben werden.

Zusätzlich zur (IP-) Adresse des Ziels kann auch, durch ein Leerzeichen getrennt, die Portnummer des Ziels, oder ein Portnummernbereich (port:port) angegeben werden. Dies ist allerdings nur möglich, wenn als Protokolltyp (s.u.) tcp oder udp angegeben wird.

Vor der Adresse und / oder vor dem Port kann die Maske jeweils durch 1 Ausrufungszeichen ! negiert, also in ihr Gegenteil verkehrt werden. Das heist: !192.168.0.3 bedeutet, das alle Pakete gemeint sind, die NICHT von 192.168.0.3 kommen.

-d adresse
--destination adresse

Die Zieladresse wird wie die Quelladresse angegeben.

-p protokolltyp
--protocol protokolltyp

Hiermit können Pakete nach ihrem Protokolltyp gefilter werden. Zulässig sind tcp, udp, icmp oder der jeweilige numerische Wert (tcp = 6, udp = 17). Die Protokollnamen und die numerischen Werte sind in /etc/protocols definiert.

-i interface
--interface interpace

Das Interface ist die Schnittstelle an der das Paket ankommt, bzw. an welcher es ausgegeben werden soll. Dies ist abhängig von der Queue in der die Bedingung steht! In der Input Queue ist die Eingangsschnittstelle gemeint, in der Forward Queue und der Output Queue die Ausgangsschnittstelle.

Durch ein angehängtes + können mehrere Schnittstellen zusammen gefaßt werden: ppp+ meint alle Schnittstellen, die mit ppp beginnen. Das Interface kann durch 1 Ausrufungszeichen ! negiert werden: -i !eth+ meint alle Pakete, die nicht durch eth0 ... ethx gehen.

Pakete vom bzw. zum lokalen Rechner haben als Schnittstelle lo.

-y

Hiermit können Pakete gefiltert werden, die bei TCP zum Verbindungsaufbau verwendet werden. Daher ist diese Option auch nur zulässig, wenn als Protokolltyp tcp spezifiziert wird.

--source-port adresse

Hiermit kann nur die Portadresse oder ein Portadressbereich unabhängig von der IP-Adresse gefilter werden. (Diese Option gibt es nur in der Langform)

Ein Port darf nur spezifiziert werden, wenn als Protokolltyp tcp oder udp angegeben wird.

--destination-port adresse

Hiermit kann nur die Portadresse oder ein Portadressbereich unabhängig von der IP-Adresse gefilter werden. (Diese Option gibt es nur in der Langform)

Ein Port darf nur spezifiziert werden, wenn als Protokolltyp tcp oder udp angegeben wird.

--icmp-type typ

Hiermit kann ein ICMP Typ gefiltert werden. ICMP Pakete dienen der Steuerung u. a. des Netzwerkverkehrs. Daher sollte hier sehr vorsichtig vorgegangen werden. Es dürfen z. B. auf keine Fall alle ICMP Pakete vom Typ 3 ("destination-unreachable") ausgefiltert werden, da sonst das Routing zusammenbricht. (Diese Option gibt es nur in der Langform)

Ein ICMP-Typ darf nur spezifiziert werden, wenn als Protokolltyp icmp angegeben wird.

Mit

ipchains -h icmp

gibt ipchains eine Liste der Namen für die ICMP-Typen und Codes aus.

Jede Regel kann den Kernel anweisen, ein Paket zu akzeptieren (accept), zurückzu weisen (reject), zu verwerfen (deny), zu maskieren (masq), umzuleiten (redirect) oder an eine weitere Regelkette (chain) weiterzuverweisen. Alle Anweisungen werden mit -j oder --jump eingeleitet.

-j ACCEPT

Wenn ein Paket akzeptiert wird, wird es an das nächste Filter weitergeleitet bzw. wenn es sich um das Ausgangsfilter handelt, dann wird das Paket ausgegeben. Es werden keine weiteren Regeln in diesem Filter mehr abgearbeitet.

-j REJECT

Wenn ein Paket zurückgewiesen wird, wird der Inhalt verworfen und dies dem Sender dies mitgeteilt. Es werden keine weiteren Regeln in diesem Filter mehr abgearbeitet. Dies ist für Pakete aus dem lokalen Netz ganz nützlich, weil dann der Sender merkt, wo das Problem liegt.

-j DENY

Wenn ein Paket verworfen wird, wird es einfach "vergessen". Der Sender bekommt keine Information darüber! Es werden keine weiteren Regeln in diesem Filter mehr abgearbeitet. Dies ist sinnvoll bei Paketen von außerhalb, denn wenn jemand bei einer unerlaubten Aktion (z. B. einem Portscan) auf unser Eingangsfilter trifft, sollte man ihn nicht daraufhinweisen, das es unter dieser IP-Adresse überhaupt 1 Rechner gibt. Dann probiert er nur umso intersiver, welche Ports nicht gesperrt sind.

-j MASQ

Wenn ein Paket maskiert wird, so wird es akzeptiert und von der forward chain in die output chain übertragen. Dabei wird allerdings die Absenderadresse (IP Nummer und Port) so geändert, als käme es von der Firewall selbst. Es werden keine weiteren Regeln in diesem Filter mehr abgearbeitet. Maskieren ist daher nur in der forward chain zulässig

-j REDIRECT

Die Umleitung von Paketen beschreibe ich hier nicht.

-j name

Wird keines der vordefinierten Sprungziele angegeben, so wird das Sprungziel als Name einer weiteren Kette definiert und das Paket an diese übergeben. (Man kann nämlich neben den drei vordefinierten auch weitere Ketten, quasi als Unterprogramme definieren) Durchläuft das Paket die aufgerufene Kette, ohne daß dort 1 Anweisung greift, so wird es zur nächsten Regel der aufrufenden Kette zurückgegeben.

Beispiele

ipchains -A input -i eth0 -d 192.168.0.1 -j ACCEPT
Hiermit werden in der input chain alle Pakete akzeptiert, die an eth0 ankommen und zu 192.168.0.1 sollen.
ipchains -A input -i !eth -p tcp -y -j DENY
Hiermit werden in der input chain alle Pakete verworfen, die eine TCP-Verbindung aufbauen wollen und nicht von einer Netzwerkschnittstelle kommen.
– — – — – — – — –

Die einfachste Routerkonfiguration

Die einfachste Routerkonfiguration besteht aus 2 Zeilen: Alles was nach außen will maskieren und alles andere ignorieren:

#!/bin/sh

# die absolut einfachste Routerkonfiguration
ipchains -P forward DENY
ipchains -A forward -i ppp0 -j MASQ

(Im offiziellen ipchains HowTo werden drei Zeilen benötigt, da dort jeweils noch das IP-Forwarding eingeschaltet wird.)

Wenn man sicher sein will, daß dies auch beim Hin- und Herschalten zwischen verschiedenen Konfigurationen funktioniert, sollte man zuerst den Urzustand wiederherstellen. Dann wir das Skript etwas länger, bleibt aber doch sehr einfach und übersichtlich:

#!/bin/sh

EXTERN=ppp0
# loesche den Inhalt aller Chains
ipchains -F
# die einfachste Routerkonfiguration
ipchains -P input ACCEPT
ipchains -P forward DENY
ipchains -P output ACCEPT
ipchains -A forward -i $EXTERN -j MASQ

(Beide Beispiele gehen davon aus, das die Schnittstelle zum Internet über ppp0 läuft. Dies ist bei Modem und zum Teil auch bei DSL meist so. Bei ISDN wird dies meist ippp0 sein. Dies ist natürlich in obigen Skripts entsprechend anzupassen.)

Es bilde sich aber niemand ein, daß ihn diese Filtereinstellung nennenswert vor irgendwas schützt! Das lokale Netz ist vielleicht halbwegs geschützt, da nur Antworten auf maskierte Pakete möglich sind, aber der Router selbst ist völlig ungeschützt. Immerhin ist mit dieser Konfiguration bereits das Surfen von allen Rechnern aus möglich, so die Clients korrekt konfiguriert sind.

Ein wenig Schutz erreicht man schon dadurch, das man alle Pakete, welche einen Verbindungaufbau durchführen wollen, abwehrt. Damit hat man dann schon 1 ganz ganz einfache Paketfilter-Firewall. (Das ist immerhin schon deutlich besser, als einfach mit 1 Windows 9x-Rechner über das DFÜ-Netzwerk zu surfen, da ist auch von außen ein Verbindungsaufbau möglich.)

#!/bin/sh

EXTERN=ppp0
# loesche den Inhalt aller Chains
ipchains -F
# die allereinfachste Firewall
ipchains -P input ACCEPT
ipchains -P forward DENY
ipchains -P output ACCEPT
ipchains -A input -i $EXTERN -p TCP -y -j DENY
ipchains -A forward -i $EXTERN -j MASQ
– — – — – — – — –

Wie die Pakete wandern: Quellen und Ziele

Netze und Verbindungen

Um eine wirkliche Firewall zu bauen muß man doch ein etwas komplexeres Filter verwenden. Dazu hier noch ein bißchen Einführung. (Nur für die, die auch verstehen wollen, was sie da tun, der Rest darf dieses Kapitel überscrollen ;-)

Durch die Paketfilter werden (im einfachen Beispiel) drei Netze miteinander Verbunden:

Das externe Netz, welches hier das Internet eine ppp-Verbindung ist und an ppp0 oder ippp0 angeschlossen ist.

Das lokale Netz, welches an der Netzwerkkarte nach innen angeschlossen ist. Es ist an eth0 angeschlossen und hat den Adressbereich 192.168.0.0, sowie die Netzmaske 255.255.255.0.

Und das interne Netz, welches alle Netzwerkdienste auf dem Gateway abbildet. Es wird auf dem Gatway selbst über "localhost" oder 127.0.0.1 oder auch 192.168.0.1 angesprochen.

Damit ergeben sich 6 verschiedene Richtungen, in die Pakete wandern können. Diese müssen im allgemeinen jweils getrennt gefiltert werden, da sie unterschiedlichen Anforderungen genügen sollen. Die höchsten Sicherheitsanforderungen ergeben sich meist für den Gateway, da dieser u. U. auch vom lokalen Netz aus gehackt werden kann. Hier spielen natürlich die lokalen Gegebenheiten (z. B. privates Netz mit 1 PC oder kleines Firmennetz mit 10 PCs) eine entscheidende Rolle.

– — – — – — – — –

Welche "Politik" ist die richtige?

Im Gegensatz zur echten Politik läßt sich das bei den ipchains recht eindeutig klären: Man kann mit den ipchains alle Pakete durchlassen (policy accept) und nur einzelne Ports blockieren. Davon rate ich aber ab! Besser ist es, die bekannten Ports zu erlauben und als policy deny zu setzen.

Man kann dann für die Anfangsphase als vorletzte Regel

ipchains -A input -j ACCEPT -l

setzen (und entsprechend in den anderen chains).

Damit werden alle Pakete, welche bisher nicht explizit erlaubt waren, akzeptiert und im syslog gelistet! Damit findet man relativ schnell die Ports, welche noch zu erlauben sind. Hier können auch Port-Bereiche angegeben werden. Nach einer Zeit, wenn alles soweit funktioniert und keine weiteren Ports auftauchen, kann man diese Regel dann auskommentieren.

Als letzte Regel sollte jede chain alle Pakete explizit abweisen und im syslog listen:

ipchains -A input -j DENY -l

(und entsprechend in den anderen chains) Damit erfährt man (hoffentlich), wenn etwas nicht stimmt. (Die policy sollte zusätzlich auf deny stehen, aber damit wird man nicht informiert, daß und welche Pakete abgewiesen wurden.)

Mit dieser Methode ist man dann auch relativ(!) sicher gegen Trojaner, welche auf irgendeinem neuen Port auftauchen. Ich habe damit bei meinem Arbeitgeber zu Beispiel den real-player (Browser Pug-In für Videos) auf einigen Rechnern finden können, welcher in einigen Versionen regelmäßig Daten über das System und das Benutzerverhalten an seinen Hersteller schickt. Dies wäre nicht aufgefallen, wenn ich nur bestimmte Ports blockiert hätte. Aus diesem Grunde sollten auch für den Weg nach draußen nur die wirklich benötigten Ports freigeschaltet werden. (Dies alles hilft natürlich nur, wenn man die log files auch regelmäßig prüft ;-)

– — – — – — – — –

Filterregeln für das Beispielsystem

Da dies schon eine recht komplexe Firewall ergibt, ist es sinnvoll die einzelnen Chains noch weiter aufzuteilen. Hierzu werde für die einzelnen Richtungen bzw. für die ICMP Pakete jeweils eigene Chains definiert. Dies erleichter am Ende zum einen den Überblick, zum anderen werde die Chains damit auch schneller, da nicht immer alle Regeln abgearbeitet werden müssen.

Zum Download - oder vergleichen: eine vollständige Datei (in einem eigenen Brauserfenster): ipchains.jo

Im ersten Teil des Skripts werde die benötigten Voreinstellungen getroffen und ein paar Variablen definiert, die das Ganze einfecher Wart- und Lesbar machen.

#!/bin/sh
#
# /usr/etc/ipchain/ipchain.jo
#
# Dieses Skript konfiguriert einen einfachen Firewall mit IP-Maskerading
# fuer ein lokales Netz $LOCAL und eine externe Verbindung zum Internet
# $EXTERN. Es werden die ueblichen Dinste (www, ftp, ...) erlaubt, alles
# uebrige wird abgeblockt
#
# Weitere Information:
# c't 17/99, Seite 194
# ipchains HowTo
# http://www.jwiesemann.de/linux/ipchains.html
#

# setze Variablen: Interface und Netz fuer internes Netz (loopback)
INTERN=lo
INTERNADR=127.0.0.1
INTERNNET=127.0.0.0/255.255.255.255
# setze Variablen: Interface, Adresse und Netz fuer lokales Netz
LOCAL=eth0
LOCALADR=192.168.0.1
LOCALNET=192.168.0.0/255.255.255.0
# setze Variablen: Interface und Adresse fuer externes Netz
# fuer DSL #EXTERN=ppp0
# fuer ISDN EXTERN=ippp0
EXTERNADR=192.168.17.42

# setze ipchains vollstaendig zurueck
# loesche alle chains und setzte "Politik" auf nicht akzeptieren
logger setze ipchains fuer firewalling a la Jo
ipchains -F
ipchains -P input DENY
ipchains -P forward DENY
ipchains -P output ACCEPT

# erzeuge chains zur einfacheren Verwaltung
ipchains -N loc2ext 2>/dev/null
ipchains -N loc2int 2>/dev/null
ipchains -N ext2int 2>/dev/null
ipchains -N any2ext 2>/dev/null
ipchains -N int2loc 2>/dev/null
ipchains -F loc2ext
ipchains -F loc2int
ipchains -F ext2int
ipchains -F any2ext
ipchains -F int2loc
# fuer ICPM Error Packete
ipchains -N icmp-acc 2>/dev/null
ipchains -F icmp-acc

Die input chain

Die input chain ist die erste Kette, die durchlaufen wird. Hier sind entsprechend die meisten Filter untergebracht. (Je eher man schlechte Pakete los ist, desto besser.) Alle Pakete, die die Firewall selbst meinen, durchlaufen nur diese Chain.

Pakete, die nach draußen gehen sollen, werden in der forward chain gefiltert. Alle anderen Pakete müssen in der input chain gefiltert werden. Hierbei wird je nach Richtung eine eigene Kette verwendet.

#-----------------------------------------------------------------------------
# setze input chain
# akzeptiere Fehlermeldungen von ueberall
ipchains -A input -p ICMP -j icmp-acc
# Kommunikation zwischen extern und intern / lokal (kein return)
ipchains -A input -i $EXTERN -j ext2int
# Kommunikation zwischen lokal und intern (kein return)
ipchains -A input -i $LOCAL -d $LOCALADR -j loc2int
# Kommunikation zwischen lokal und extern (wird in forward chain gefiltert)
ipchains -A input -i $LOCAL -j ACCEPT
# Kommunikation zwischen intern und extern / lokal
ipchains -A input -i $INTERN -j ACCEPT
# Schluss mit lustig!
ipchains -A input -j DENY -l

Die forward chain

In der forward chain erscheinen eigentlich nur Pakete, welche vom lokalen Netz ins extern wollen. (Demaskierte Pakete gehen an der forward chain vorbei und Pakete von extern nach local sollte es nicht geben.)

#-----------------------------------------------------------------------------
# setze forward chain
# Teile Pakete in die einzelnen Chain (je nach Richtung)
# was uebrigbleibt wird abgelehnt und ge"logged"
# (in forward chain ist Interface das, wo es rausgeht!)
ipchains -A forward -s $LOCALNET -i $EXTERN -j loc2ext
# Schluss mit lustig!
ipchains -A forward -j DENY -l

Die output chain

#-----------------------------------------------------------------------------
# setze output chain
# Kommunikation nach extern (kein return)
ipchains -A output -i $EXTERN -j any2ext
# Kommunikation von intern nach lokal (kein return)
ipchains -A output -i $LOCAL -s $LOCALADR -j int2loc
# restliche Pakete (demaskierte Antworten) werden ueber Policy akzeptiert

Die icmp chain

Diese Kette dient der Filterung der ICMP Pakete. Diese dienen im wesentlichen der Steuerung des Netzwerkverkehrs. Hier ist also besondere Vorsicht geboten.

Ein vollständiges herausfiltern dieser Pakete legt in kurzer Zeit das gesamte Netzwerk lahm. Andererseits läßt sich mit diesen Paketen auch ziemlich viel Ärger verbreiten. Die hier gezeigten Regeln lassen alles durch, was normalerweise benötigt wird, aber nicht mehr. (Selbstverständlich ist die Grenze nicht ganz so scharf.)

# setze chain fuer ICPM-Error Packete -----------------------------------------
# Fehlermeldungen werden akzeptiert, sonst klappt keine Kommunikation
# der anderen Protokolle, der Rest geht wieder zurueck in die aufrufende
# chain
ipchains -A icmp-acc -p ICMP --icmp-type destination-unreachable -j ACCEPT
ipchains -A icmp-acc -p ICMP --icmp-type source-quench -j ACCEPT
ipchains -A icmp-acc -p ICMP --icmp-type time-exceeded -j ACCEPT
ipchains -A icmp-acc -p ICMP --icmp-type parameter-problem -j ACCEPT
# akzepiere Anworten auf Ping von ueberall
ipchains -A icmp-acc -p ICMP --icmp-type pong -j ACCEPT

Das Programm ping ist ein sehr nützliches Hilfsmittel um Netzwerkverbindungen zu testen. Man sendet ein Ping zu einer Ip-Adresse und erhält ein Pong (als Echo) zurück. Damit kann man prüfen ob eine Adresse ansprechbar ist und welche Zeit das Paket benötigt. Auch mit Ping läßt sich ein Rechner angreifen! Daher wird hier nur der Pong hereingelassen (und der Ping hinaus). (Das Programm tracert verwendet die selben Pakete)

Die extern to intern chain (ext2int)

Dies ist tendenziell die gefährlichste Richtung. (Auch wenn sog. trojanische Pferde dafür sorgen, das die Richtung von drinnen nach draußen auch nicht ganz ohne ist).

#-----------------------------------------------------------------------------
# setze chain extern to intern
# wird aus input chain aufgerufen:
# ipchains -A input -i $EXTERN -j ext2int
# verhindere spoofing (vortaeuschung falscher Adressen)
ipchains -A ext2int -s $INTERNNET -j DENY -l
ipchains -A ext2int -s $LOCALNET -j DENY -l
# verhindere Verbindungsaufbau von aussen
ipchains -A ext2int -p TCP -y -j DENY -l
# akzepiere Anworten auf Ping nach extern
ipchains -A ext2int -p ICMP --icmp-type pong -j ACCEPT
# akzeptiere Antworten auf maskierte Pakete (gehen nach local!)
ipchains -A ext2int -p TCP --dport 61000:65096 -j ACCEPT
ipchains -A ext2int -p UDP --dport 61000:65096 -j ACCEPT
# verhindere Zugriff auf X-Windows
ipchains -A ext2int -p TCP --dport 6000:6063 -j DENY -l
ipchains -A ext2int -p UDP --dport 6000:6063 -j DENY -l
# akzeptiere Anwortenen auf Pakete von intern
ipchains -A ext2int -p TCP --dport 1024: -j ACCEPT
ipchains -A ext2int -p UDP --dport 1024: -j ACCEPT
# Schluss mit lustig!
ipchains -A ext2int -j DENY -l

Die local to intern chain (loc2int)

Hier geht es primär um die Ver(Be-?)hinderung von Angriffen von innen. Zumindest in einem Firmennetz sollte man die Firewall nicht ungeschützt gegen unbefugte Eingriffe lassen. Auch trojanische Pferde sind inzwischen teilweise soweit, daß sie versuchen Firewalls auzutricksen.

#-----------------------------------------------------------------------------
# setze chain local to intern
# wird aus input chain aufgerufen:
# ipchains -A input -i $LOCAL -d $LOCALADR -j loc2int
# kein spoofing
ipchains -A loc2int -s ! $LOCALNET -j DENY
# akzepiere Nameserveranfragen von lokal
ipchains -A loc2int -p TCP --dport domain -j ACCEPT
ipchains -A loc2int -p UDP --dport domain -j ACCEPT
# akzepiere email von /nach lokal
ipchains -A loc2int -p TCP --dport pop3 -j ACCEPT
ipchains -A loc2int -p TCP --dport imap -j ACCEPT
ipchains -A loc2int -p TCP --dport smtp -j ACCEPT
# akzeptiere www / proxy von lokal
ipchains -A loc2int -p TCP --dport http -j ACCEPT
ipchains -A loc2int -p TCP --dport https -j ACCEPT
ipchains -A loc2int -p TCP --dport 8080 -j ACCEPT
# akzeptiere telnet von lokal
ipchains -A loc2int -p TCP --dport telnet -j ACCEPT
ipchains -A loc2int -p TCP --dport ssh -j ACCEPT
# akzeptiere netbios von lokal
ipchains -A loc2int -p TCP --dport netbios-ns -j DENY -l
ipchains -A loc2int -p UDP --dport netbios-ns -j DENY -l
ipchains -A loc2int -p TCP --dport netbios-dgm -j ACCEPT
ipchains -A loc2int -p UDP --dport netbios-dgm -j ACCEPT
ipchains -A loc2int -p TCP --dport netbios-ssn -j ACCEPT
ipchains -A loc2int -p UDP --dport netbios-ssn -j ACCEPT
# akzepiere ICMP nachrichten an lokal
ipchains -A loc2int -p ICMP -j ACCEPT
# akzepiere Anworten auf Authentifikationsanfragen nach lokal
ipchains -A loc2int -p TCP --sport auth -j ACCEPT
# akzeptiere alles, aber logge -> damit koennen die fehlenden
# Service vielleicht gefunden werden
# ipchains -A loc2int -j ACCEPT -l
# Schluss mit lustig! (Lokal werden abgeblockte Pakete gemeldet)
ipchains -A loc2int -j REJECT -l

Die local to extern chain (loc2ext)

Hier können alle Dienste explizit erlaubt werden, die von drinnen nach draußen erlaubt sind.

Die vorletzte Regel, welche hier auskommentiert ist, ist für die Inbetriebnahme recht nützlich und sollte anschließend wieder auskommentiert werden.

#-----------------------------------------------------------------------------
# setze chain local to extern (masqerading)
# wird aus forward chain aufgerufen:
# ipchains -A forward -i $EXTERN -j ext2loc
# www -> maskieren und weiterleiten
ipchains -A loc2ext -p TCP --dport http -j MASQ
ipchains -A loc2ext -p TCP --dport https -j MASQ
# akzepiere email von /nach extern
ipchains -A loc2ext -p TCP --dport pop3 -j MASQ
ipchains -A loc2ext -p TCP --dport smtp -j MASQ
# secure shell -> maskieren und weiterleiten
ipchains -A loc2ext -p TCP --dport ssh -j MASQ
# ftp -> maskieren und weiterleiten (Kommandos und Daten passiv)
ipchains -A loc2ext -p TCP --dport ftp -j MASQ
ipchains -A loc2ext -p TCP --dport 1024: -j MASQ
# ping -> maskieren und weiterleiten
ipchains -A loc2ext -p ICMP --icmp-type ping -j MASQ
# AOL -> maskieren und weiterleiten
ipchains -A loc2ext -p TCP --dport 5200 -j MASQ
ipchains -A loc2ext -p UDP --dport 5190 -j MASQ
# akzeptiere alles, aber logge -> damit koennen die fehlenden
# Service vielleicht gefunden werden
#ipchains -A loc2ext -j MASQ -l
# Schluss mit lustig! (Lokal werden abgeblockte Pakete gemeldet)
ipchains -A loc2ext -j REJECT -l

Die any to extern chain (any2ext)

Zugriffe von der Firewall selbst nach draußen lassen sich nur in der output chain Filtern. Dummerweise lassen diese sich nicht direkt nach ihrer Quelle unterscheiden.

#-----------------------------------------------------------------------------
# setze chain any to extern
# wird aus output chain aufgerufen:
# ipchains -A output -i $EXTERN -j any2ext
# akzepiere Nameserveranfragen nach extern
ipchains -A any2ext -p TCP --dport domain -j ACCEPT
ipchains -A any2ext -p UDP --dport domain -j ACCEPT
# akzepiere email von /nach extern
ipchains -A any2ext -p TCP --dport pop3 -j ACCEPT
ipchains -A any2ext -p TCP --dport smtp -j ACCEPT
# akzeptiere www nach extern
ipchains -A any2ext -p TCP --dport http -j ACCEPT
ipchains -A any2ext -p TCP --dport https -j ACCEPT
# akzeptiere ftp nach extern (Kommandos und Daten passiv)
ipchains -A any2ext -p TCP --dport ftp -j ACCEPT
ipchains -A any2ext -p TCP --dport 1024: -j ACCEPT
# akzeptiere ping nach extern
ipchains -A any2ext -p ICMP --icmp-type ping -j ACCEPT
# akzeptiere AOL nach extern (nur von lokal!)
ipchains -A any2ext -s $LOCALNET -p TCP --dport 5200 -j ACCEPT
ipchains -A any2ext -s $LOCALNET -p UDP --dport 5190 -j ACCEPT
# akzeptiere alles, aber logge -> damit koennen die fehlenden
# Service vielleicht gefunden werden
#ipchains -A any2ext -j ACCEPT -l
# Schluss mit lustig! (nach intern/lokal werden abgeblockte Pakete gemeldet)
ipchains -A any2ext -j REJECT -l

Die intern to local chain (int2loc)

Zugriffe von der Firewall selbst nach drinnen lassen sich (ebenfalls) nur in der output chain Filtern.

#-----------------------------------------------------------------------------
# setze chain intern to local
# wird aus output chain aufgerufen:
# ipchains -A output -i $LOCAL -s $LOCALADR -j int2loc
# akzepiere Antworten auf Nameserveranfragen von lokal
ipchains -A int2loc -p TCP --sport domain -j ACCEPT
ipchains -A int2loc -p UDP --sport domain -j ACCEPT
# akzepiere Antworten auf email von /nach lokal
ipchains -A int2loc -p TCP --sport pop3 -j ACCEPT
ipchains -A int2loc -p TCP --sport imap -j ACCEPT
ipchains -A int2loc -p TCP --sport smtp -j ACCEPT
# akzeptiere Antworten auf www / proxy von lokal
ipchains -A int2loc -p TCP --sport http -j ACCEPT
ipchains -A int2loc -p TCP --sport https -j ACCEPT
ipchains -A int2loc -p TCP --sport 8080 -j ACCEPT
# akzeptiere Antworten auf telnet von lokal
ipchains -A int2loc -p TCP --sport telnet -j ACCEPT
ipchains -A int2loc -p TCP --sport ssh -j ACCEPT
# akzeptiere Antworten auf netbios von lokal
ipchains -A int2loc -p TCP --sport netbios-ns -j DENY -l
ipchains -A int2loc -p UDP --sport netbios-ns -j DENY -l
ipchains -A int2loc -p TCP --sport netbios-dgm -j ACCEPT
ipchains -A int2loc -p UDP --sport netbios-dgm -j ACCEPT
ipchains -A int2loc -p TCP --sport netbios-ssn -j ACCEPT
ipchains -A int2loc -p UDP --sport netbios-ssn -j ACCEPT
# akzepiere ICMP nach lokal
ipchains -A int2loc -p ICMP -j ACCEPT
# akzepiere Authentifikationsanfragen nach lokal
ipchains -A int2loc -p TCP --dport auth -j ACCEPT
# akzeptiere alles, aber logge -> damit koennen die fehlenden
# Service vielleicht gefunden werden
# ipchains -A intloc -j ACCEPT -l
# Schluss mit lustig! (Lokal werden abgeblockte Pakete gemeldet)
ipchains -A int2loc -j REJECT -l
– — – — – — – — –

Weitere Dokumentation zu Ipchains findet sich in:

– — – — – — – — –
 

Spezielle NAT Probleme: aktives FTP und diverse Spiele.

Die Network Adress Translation, also das Maskieren der lokalen Adressen ist ein ganz nützlicher Trick, um ein lokales Netz ohne zugeteilten Adressraum zu betreiben. Leider hat dies auch ein paar Nachteile.

Alle Verbindungen, die von innen nach außen aufgebaut werden, können problemlos mittels Masquerading betrieben werden: Beim Verbindungsaufbau bekommt der Router die Pakete von der internen Adresse und kann diese entsprechend übersetzen. Wenn er 1 Antwort erhält, weiß er somit wohin er sie schicken muß. Dies funktioniert z. B. bei den Protokollen http, pop und bei passivem ftp mit Servern im externen Netz.

Wenn nun ein Server im lokalen Netz betrieben werden soll, so stellt sich das umgekehrte Problem: Das Paket zur Kontakaufnahme kommt aus dem externen Netz zu der einzigen außen bekannten IP-Adresse, dem Router. Aber woher soll dieser nun wissen, zu welchem Rechner im internen Netz er dieses Paket weiterleiten soll? Bzw. woher soll er überhaupt wissen, das dieses Paket nicht für ihn selbst ist?

...

Weitere Dokumentation zu diesen Problemen:

– — – — – — – — –
 

Sicherheit der Firewall

So, nach dem nun alles abgedichtet ist, ist man ja sicher ...

... NEIN! Wirklich sicher wird man mit einem Paketfilter nie.

Jeder offene Port bietet die Möglichkeit für 1 Angriff. Allerdings bieten die hier vorgestellten Regeln eine relativ hohe Sicherheit für Privatanwender und m. E. n. auch für kleine Firmen. Insbesondere wenn der Zugang zum Internet über eine Wählverbindung mit dynamischer IP-Adresse erfolgt, bleibt einem Angreifer nur wenig Zeit einzudringen. Und nach dem nächsten Verbindungsaufbau hat man ja wieder 1 neue Adresse, die niemand kennt.

Deutlich sicherer ist die Firewall bereits, wenn man das IP-Forwarding ausschaltet und alle Zugriffe nach außen über einen Proxy müssen. Allerdings funktionieren damit einige Dienste nicht mehr optimal. Hier muß man halt einen Kompromiß zwischen Sicherheit und Nutzen schließen. Wirklich sicher isterst 1 vollständige Trennung vom Internet. So prüfe also 1 jeder, welche Dienste er wirklich baucht.

Auch sollte man regelmäßig 1 Blick in die Log-Dateien werfen, ob sich da ungewöhnliches zeigt.

Links zum Thema Sicherheit:

– — – — – — – — –

Weiter mit: Der eigene Nameserver!

Urheber © Dr. Joachim Wiesemann

Letzte Aktualisierung: 28.5.2006