Firewalls unter Linux
von Thomas Avieny (t_avieny@informatik.uni-kl.de),
Klaus Knopper (knopper@unix-ag.uni-kl.de)
Es werden die grundsätzlichen Konzepte und Ideen hinter Firewalls
dargestellt. Anhand von Beispielen wird
auf die Vor- und Nachteile der verschiedenen Ansätze eingegangen.
Außerdem werden die Möglichkeiten beleuchtet, die Linux hier dem
Anwender zur Verfügung stellt.
Inhalt
Theorie
Warum werden Firewalls benötigt?
Grundsätzliche Überlegungen
Paketfilter (Screening Router)
SOCKS-Server
Application-Level Gateways
Beurteilung von Firewalls
Konfigurationsbeispiele unter Linux
Voraussetzungen
Ausstattung
Festlegungen
ipchains
Forwarding
Kernel IP-Forwarding
Default-Policies
Masquerading
Paketfilter
Default-Policies
Forwarding für interne Netzwerkadressen erlauben
Anti-Spoofing und Verbindungaufbau nur in eine Richtung
Zugriff auf gewünschte Dienste erlauben
Umleitung (redirect) auf lokale Ports
Nachwort
Literatur und Links
Heute besteht häufig die Notwendigkeit ein firmeneigenes Netz mit der
Außenwelt
zu verbinden. Dabei bestehen für jeden Rechner innerhalb des eigenen
Intranet
Risiken wie Attacken oder Datendiebstahl bzw. Datenverlust.
Somit ist es durch gezielte Angriffe von außerhalb möglich, den
(Rechner-)Betrieb lahmzulegen, aber auch an firmeninterne, sensible Daten zu gelangen.
Verhindern lässt sich dies mit Hilfe von sogenannten Firewalls.
Allerdings sind
Firewalls auch kein Allheilmittel, sondern bieten nur einen gewissen Schutz
und müssen an die jeweiligen Bedürfnisse angepasst und dauerhaft
betreut
werden.
Im allgemeinen Sprachgebrauch bezeichnet man mit einem Firewall einen
einzelnen Rechner, der als Schnittstelle Intranet und Außenwelt verbindet
und den ein- und ausgehenden Datenfluss überwacht und gegebenenfalls
filtert bzw. blockiert. Dazu muss entschieden werden, ob der Firewall eher
restriktiv (alles verbieten, was nicht ausdrücklich erlaubt wird) oder
freizügig
(alles erlauben, was nicht explizit verboten wird) gestaltet werden soll.
Grundsätzlich gibt es verschiedene Konzepte, um auf ein- und ausgehende
Aktivitäten Einfluss zu nehmen. Jedes Konzept stellt einen
Kompromiss zwischen
Sicherheit und Zugänglichkeit dar. Dies zeigt sich daran, dass ein
Konzept transparent,
und somit auch komfortabel für den Anwender, oder sicher ist, was sich
meist in
zusätzlichen Passwortabfragen äußert.
Paketfilter (engl. Screening Router) stellen das einfachste Firewall-Konzept
dar,
indem sie jedes einzelne Paket untersuchen und nach bestimmten Kriterien
weiterleiten oder abblocken. Dazu verwenden sie Informationen aus dem IP-
und TCP-Header der einzelnen Pakete. In erster Linie sind das Absender- und
Empfängeradresse, Absender- und Empfängerport sowie der Pakettyp,
also
Informationen,
die der Transportschicht des Internet-Schichten-Modells entsprechen.
Um einen Paketfilter zu erzeugen werden die Kriterien in sogenannte Regeln
gefasst und diese später der Reihe nach bearbeitet. Damit wird es
möglich, den
Datenfluss von bzw. zu bestimmten Rechnern zu kontrollieren. Über die
Portnummern
können verschiedene Dienste/Programme berücksichtigt werden.
Screening Router sind für den Anwender völlig transparent, d.h. im
Normalfall merkt er nichts
von einem solchen Filter. Allerdings bieten sie auch nur einen sehr einfachen
Schutz.
Es ist beipielsweise nicht möglich, sogenannte "flooding attacks" (viele
kurz aufeinander geschickte
Pakete) zu erkennen. Darüber hinaus ist die Filterliste anfällig
für Fehler und kann nur von
Administratoren mit genauen Kenntnissen erstellt werden. Die wichtigste
Einschränkung ist
jedoch, dass sich praktikabel gewisse Dienste und Programme nur für alle
oder keinen Benutzer
zugänglich machen lassen!
Mit Hilfe von SOCKS-Servern wird es nun möglich, Dienste bzw. Programme
nur
für bestimmte
Benutzer zugänglich zu machen. Ein vollständiges SOCKS-System besteht
aus dem eigentlichen
SOCKS-Server der auf dem Bastion-Host, d.h. dem Firewall-Rechner, installiert
wird, sowie einer Bibliothek
auf jedem Client. Die zu benutzenden Programme müssen alle angepasst
werden, was allerdings durch das
einheitliche Protokoll kein hoher Aufwand ist.
Die zusätzliche Funktionalität wird hier durch eine zusätzliche
Passwortabfrage und somit einem
gewissen Komfortverlust erkauft. Außerdem ist der Aufwand gegenüber
Paketfiltern natürlich höher!
Mit SOCKS-Servern ist es immer noch nicht möglich, bestimmte Aktionen oder
Befehle einzelner Programme, d.h. auf
Anwendungsebene, zu erlauben bzw. zu verbieten.
Durch Application-Level-Gateways wird es nun möglich, wirklich jede Aktion
eines Programms zu kontrollieren.
Dazu wird allerdings für jede Applikation ein eigener, sehr spezieller
Server benötigt, der die entsprechende
Funktionalität bietet. Somit benutzt jeder dieser Server ein eigenes
Protokoll, das die Kommandos des Programmes
berücksichtigt. Diese Lösung bietet damit auch den besten Schutz, ist
allerdings am aufwendigsten.
Firewalls sind zwar kein Allheilmittel, bieten bei sinnvoller Anwendung aber
schon einen brauchbaren Schutz.
Außerdem erleichtern sie den Aufwand gegenüber Lösungen für
jeden einzelnen Rechner ganz
beträchtlich, bieten sie doch eine zentralisierte Stelle für
Installation, Konfiguration und Administration.
Zu beachten ist weiterhin:
- Ein Firewall setzt ein sicheres Betriebssystem vorraus, außerdem sollte
nur Firewall-Software auf diesem Rechner installiert sein!
- Durch die gleichzeitige Verwendung und Kombination der verschiedenen
Systeme
kann die Sicherheit gesteigert werden.
- Firewalls bieten nur einen sehr eingeschränkten Schutz gegenüber
Viren und Trojanischen Pferden.
- Schon ein einziges Modem innerhalb des Intranet kann einen noch so sicheren
Firewall umgehen!
Der Linux-Kernel unterstützt bereits ohne Zuhilfenahme
von Daemon-Prozessen statisches Routing, IP-Forwarding, IP-Paketfilter,
IP-Accounting, Port-Umleitung und Masquerading (auch oft im Zusammenhang mit
NAT - Network Address Translation - genannt).
Diese Eigenschaften werden in Form von kernelinternen Tabellen bzw. Ketten von
Regeln (Chains) konfiguriert. Zur Verwaltung dieser Regeln dienen die Programme
ipfwadm (Kernel bis 2.0.36) und ipchains
(Kernel ab 2.2.0). ipchains bietet gegenüber
ipfwadm durch ein neues Konzept von Regel-Verkettungen (siehe
Skizze) eine höhere Flexibilität sowie einige
neue Optionen, die erst mit den neuen Kernels verwendet werden können.
Im Folgenden werden Konfigurationsbeispiele mit ipchains
betrachtet, wovon die meisten - mit abgewandelter Syntax - prinzipiell auch
auf ipfwadm übertragbar sind.
Für die folgenden Beispiele müssen einige
Mindestanforderungen an das Hostsystem erfüllt sein.
- Linux ab Kernel 2.2,
- Mehrere Netzwerkinterfaces (z.B. zwei Netzwerkkarten oder
eine Netzwerkkarte plus Modem/ISDN),
- TCP/IP-Support im Kernel (Standard)
- IP-Forwarding-Support im Kernel,
- IP-Firewall-Support im Kernel,
- evtl. IP-Masquerading-Support im Kernel und spezielle Masquerading-Module,
- installierte Programmpakete ipfwadm bzw. ipchains.
Die ipfwadm/ipchains-Pakete sind üblicherweise Standard-Ausrüstung
in der Contrib der jeweiligen Linux-Distribution und als freie Software
inklusive Quelltext erhältlich.
Falls der Kernel keinen Firewall-Support hat, muss er neu
übersetzt werden. Hierzu sind bei make menuconfig die Optionen
Network firewalls, IP: firewalling und bei
Masquerading IP: always defragment sowie möglichst alle
Masquerading-Optionen im Menüpunkt Networking options
auszuwählen.
Der Einfachheit halber sei in folgenden Beispielen angenommen, dass ein
internes Netzwerk mit IP-Adressen im Bereich 192.168.1.1 bis
192.168.1.254 vorhanden sei, wobei der als Router/Firewall
einzusetzende Linux-Rechner auf der Netzwerkkarte eth0
mit der Adresse 192.168.1.254 konfiguriert und mit dem
internen Netz verbunden ist.
Als externe Schnittstelle des Linux-Rechners wird im Beispiel ein analoges
Modem verwendet, das vom Provider über PPP eine dynamische IP-Adresse
zugewiesen bekommt, über die es Daten ins Internet schicken und vom
Internet entgegennehmen kann. Da die IP-Adresse von ppp0
nicht konstant ist, müssen die ipchains-Regeln
entsprechend flexibel ausgelegt werden, da sonst bei jedem Dialout
die Konfiguration der Filter- und Forwardingregeln geändert werden
müsste.
Für ein- und ausgehende IP-Pakete (TCP, UDP und ICMP) können
Regeln definiert und miteinander verkettet werden. Bei einer Kette von
Regeln (Chain 1 in der Skizze) wird nacheinander überprüft, ob auf
ein Paket die angegebenen Eigenschaften (Source/Destination-Adresse,
Source/Destination-Port, Art des Paketes, Interface) zutreffen. Treffen die
von einer Regel angegebenen Eigenschaften zu, wird zu einer vordefinierten
Behandlung des Paketes (Tabelle) oder in eine für
diesen Fall definierte weitere Kette von Regeln (Chain 2 in der Skizze)
verzweigt.
Die vordefinierten und vom Kernel direkt umsetzbaren Behandlungen eines
IP-Paketes, auf das eine Regel zutrifft, sind:
ACCEPT | Akzeptieren des Paketes |
DENY | Das Paket wird ohne Rückmeldung
an den Absender verworfen (dieser bekommt eventuell einen Timeout, wenn es sich
um ein TCP-Paket handelte) |
REJECT | Das Paket wird verworfen und der
Absender erhält per ICMP eine Rückmeldung, dass die Verbindung
abgebrochen
wurde. (Dies führt auf der Absender-Seite zu der bekannten Meldung
"connection refused", die auch im Normalfall auftritt, wenn auf dem Zielport
kein Server-Dienst läuft.) |
MASQ | Das Paket wird nach Umschreiben der
Source-Adresse in die des Routers an den Zielhost weitergeleitet |
REDIRECT | Das Paket wird auf eine
andere IP-Adresse/Port umgeleitet |
RETURN | Rücksprung zur nächsten
Regel in der vorigen Regelkette |
---|
Folgende Chains sind vordefiniert:
input | Regeln für
ankommende Pakete |
output | Regeln für
abzuschickende Pakete |
forward | Regeln für
weiterzuleitende Pakete |
neuer_name | Benutzerdefinierte Regeln,
die in die bereits gesetzten eingeklinkt werden können (z.B. Chain 2
in der obigen Skizze) |
Per Default ist bei den älteren Kernels 2.0.x das
Forwarding von IP-Paketen zwischen Netzwerkinterfaces aktiviert, d.h.
der Kernel leitet automatisch aufgrund von Source- und Destination-IP eines
Paketes die Daten an die entsprechenden Netze, sofern über seine lokalen
Interfaces erreichbar, weiter.
Mit dem Kommando
echo 0 > /proc/sys/net/ipv4/ip_forward
lässt sich das Forwading, unabhängig von gesetzten Firewall-Regeln
oder Routing-Tabellen, deaktivieren. mit
echo 1 > /proc/sys/net/ipv4/ip_forward
lässt es sich aktivieren.
Wenn noch keine Regeln definiert wurden oder nach Aufruf von
ipchains -F input
ipchains -F output
ipchains -F forward
sind üblicherweise die Default-Behandlungen alle gleich ACCEPT, d.h.
es werden Pakete in ein- und ausgehender Richtung akzeptiert und je nach
Herkunft- und Zieladresse weitergeleitet. Daher genügt es, mit
route die statischen Routes und das Defaultgateway zu setzen, um einen
Linux-Rechner als Router zu betreiben. Wird dynamisches Routing verwendet, so
müssen die Kernel-Routingtabellen durch einen Daemon (routed,
gated) aktualisiert werden.
Ein privates Netz mit den üblicherweise nicht gerouteten,
reservierten IP-Adressen 192.168.1.x soll über einen Linux-Rechner
Zugang zum Internet erhalten. Durch Masquerading ist es
möglich, den Netzzugang über die Modem-Schnittstelle des
Linux-Rechners (ppp0) gemeinsam für alle Rechner im privaten Netz zu
nutzen. Die Rechner im privaten Netz müssen hierfür lediglich die
ins interne Netz zeigende IP-Adresse 192.168.1.254 des Linux-Rechners als
Default-Gateway eintragen. Auf dem Linux-Rechner wird mit der Regel
ipchains -A forward -s 192.168.1.0/24 -d 0/0 -j MASQ
das IP-Masquerading für das private Netz aktiviert. Erkennt der
Linux-Kernel ein IP-Paket, das aus dem internen Netz stammt und eine
Zieladresse im externen Netz besitzt, so merkt er sich die Adresse des
sendenden Rechners, ersetzt diese im IP-Paket durch seine eigene und
leitet das Paket über sein externes Interface ppp0
weiter. Der externe, angerufene Host sieht also nur die derzeit weltweit
gültige
externe IP-Adresse des Linux-Rechners. IP-Pakete, die anschließend vom
angerufenen Host auf den Source-Port des vermeintlichen "Anrufers"
zurückgeschickt werden, werden vom Linux-Router so
umgeschrieben, dass als Zieladresse wiederum die Adresse des Rechners im
internen Netz eingetragen wird, der die Verbindung ursprünglich initiiert
hat. Auf diese Weise entsteht über den masqueradenden Linux-Router eine
bidirektionale Verbindung zwischen den beiden Rechner im internen und externen
Netz.
Dieses Feature hat den Vorteil, dass (fast) alle
Dienste des Internet uneingeschränkt aus dem Intranet genutzt werden
können, sofern sie keinen Verbindungsaufbau in Rückrichtung
erfordern. Ein direkter Verbindungsaufbau aus dem externen
ins interne Netz ist nicht möglich, da der IP-Bereich des internen
Netzes vor
dem externen "versteckt" wird. Im Zusammenspiel mit den weiter
unten erwähnten Anti-Spoofing-Regeln ist dies
bereits eine sehr komfortable Lösung, um in vielen Fällen
ausreichende Sicherheit für das interne Netz zu gewährleisten.
Dienste wie FTP, die einen Verbindungsaufbau aus dem externen
ins interne Netz erfordern (ftp-data), sind mit Masquerading allein
zunächst problematisch. Hierfür gibt es jedoch Lösungen mit
Hilfe von zusätzlichen Kernel-Modulen, die dienstspezifisch bei einer
bereits bestehenden Steuerverbindung Pakete zu Ports des dienstanfordernden
Rechners im internen Netz weiterleiten. Beispiel:
modprobe ip_masq_ftp
modprobe ip_masq_irc
modprobe ip_masq_raudio
Eine weitergehende Kontrolle der im Kernel implementierten
Masquerading-Funktionen bietet das Utility ipmasqadm, das
ebenso wie ipchains zur Standardausrüstung eines Linux-Routers
gehört.
Zum Betrieb eines komplexeren Firewalls - vor allem dann eingesetzt,
wenn das interne Netz nicht per Masquerading versteckt, sondern mit weltweit
gültigen IP-Adressen versehen wird - gibt es je nach
Sicherheitsbedarf in der Praxis zwei Fälle:
- Fall 1:
- Die Default-Policy für die Annahme/Weiterleitung von
IP-Paketen bleibt auf ACCEPT und der Zugriff auf unerwünschte Ports wird
gezielt gesperrt.
- Fall 2:
- Zunächst wird der gesamte durch den Linux-Router
gehenden Netzwerkverkehr gesperrt und dann gezielt für bestimmte
Adressen und Ports wieder geöffnet.
Im Fall 1 wird, falls beispielsweise der Telnet-Dienst
vom externen ins interne Netz gesperrt werden soll, folgende Regel angewendet:
ipchains -I input -i ppp0 -d 192.168.1.0/24 23 -p tcp -j DENY
Vom (Modem-)Interface ppp0 kommende TCP-Pakete mit Zieladresse im internen
Netz und Zielport 23 (Telnet) werden hiermit verworfen. Ein telnet zum
Firewall-Rechner selbst wäre hierbei aber immer noch möglich, da
dessen externe Adresse nicht mit der angegebenen Maske 192.168.1.0/24
übereinstimmt!
Im Fall 2 wird im Beispiel die Default-Policy für die
Input-Regeln auf DENY gesetzt. Hierdurch werden sämtliche
ankommenden IP-Pakete verworfen, wenn keine der noch zu definierenden
ipchains-Regeln greift.
ipchains -P input DENY
(Hinweis: Man sollte dies aus
verständlichen Gründen nicht über das Netz versuchen, sondern
an der Konsole oder mit einem vorher ausgiebig getesteten Script arbeiten.
Falls Folgeregeln zum Wiederöffnen von Ports fehlschlagen, sperrt man sich
sonst selbst aus.)
Die meisten der im Folgenden kommentierten ipchains-Regeln beziehen sich auf
Fall 2.
Pakete aus dem internen Netz sollen den Firewall passieren dürfen.
# Lokale Verbindungen erlauben (X-Window, lokale daemons etc.)
ipchains -A input -i lo -j ACCEPT
# Privates Netz hinter eth0 hat uneingeschränkten Zugriff
ipchains -A input -i eth0 -j ACCEPT
Obwohl die Netzwerkadressen 192.168.x.x normalerweise nicht von Providern
geroutet werden (sollten), ist ein Angriff möglich, in dem der Angreifer
vortäuscht, seine IP-Pakete stammten aus dem internen Netz und dürften
wegen der oben behandelten Masquerading-Regeln
den Linux-Router passieren. Hier muss der Linux-Firewall erkennen, dass die
Pakete nicht aus dem internen Netz stammen, sondern aus dem externen Netz
über das Interface ppp0 geschickt wurden, und muss diese
verwerfen.
ipchains -A input -i ppp0 -s 192.168.1.0/24 -j DENY
Diese Regel sollte vor denjenigen Regeln stehen,
die Verbindungen erlauben.
Nach den oben definierten Regeln können bereits Pakete aus dem internen
Netz das externe Netz erreichen. Nun muss ein "Rückweg" ermöglicht
werden, wobei darauf geachtet werden muss, dass hierdurch keine Angriffspunkte
entstehen. Beispielsweise ist es günstiger, auf dem Firewall einen Caching
Nameserver zu betreiben, der vom internen Netz aus abgefragt werden kann, als
den Zugriff auf externe Nameserver (und den Rückweg!) für das interne
Netz zu erlauben.
Im folgenden Beispiel wird das Entgegennehmen von WWW-Daten (TCP, Port 80)
erlaubt, jedoch nur, falls die Verbindung aus dem internen Netz initiiert
wurde.
ipchains -A input -i ppp0 -s 0/0 80 -p tcp ! -y -j ACCEPT
Diese Regel funktioniert aufgrund der Tatsache, dass beim Aufbau von
TCP-Verbindungen ein Handshake wie unten abgebildet erfolgen muss.
Im ersten TCP-Paket beim Verbindungsaufbau von Host A zu Host B ist das
Synchronize-Flag gesetzt. In der Antwort des angerufenen Host
B sind sowohl Synchronize als auch Acknowledge gesetzt,
woraufhin Host A mit dem Senden eines weiteren Acknowledge und den
eigentlichen Daten beginnen kann. Es genügt also, diejenigen Pakete
auszufiltern, die lediglich SYN gesetzt haben, um den Aufbau einer
TCP-Verbindung zu verhindern. Beim UDP-Protokoll besteht diese
Möglichkeit nicht.
Folgende ipchains-Regel leitet alle Verbindungen, die vom internen Netz
aus an externe WWW-Server gehen, auf den Port 3128 des Firewalls
um, auf dem ein Squid-Cache läuft. Der Linux-Firewall wird hierdurch zu
einem transparenten (von den Clients unbemerkten) Proxy.
ipchains -A input -i eth0 -d 0.0.0.0/0 80 -p tcp -j REDIRECT 3128
Neben dem nützlichen Effekt, dass unabhängig von der
Browser-Einstellung immer der Cache des Linux-Gateways verwendet wird,
kann man sich so das Zulassen direkter WWW-Verbindungen auf Port 80
zwischen Rechnern im internen und externen Netz ersparen. Der Firewall
selbst muss natürlich so eingestellt werden, dass er entsprechende
WWW-Daten von Port 80 externer Rechner entgegennimmt.
Ein weiterer Anwendungsfall ist die Umleitung einer Verbindung
auf einen lokalen Port, auf dem ein verschlüsselnder Proxy läft, der
eine für den Benutzer transparente Verbindung zu einer Gegenstelle
herstellt. Die Daten werden auf der Strecke zwischen den beiden Proxies
verschlüsselt übertragen, der Anwender erhät auf seiner Seite
jedoch die vom Firewall bereits entschlüsselte Fassung, ohne sich um
technische Details der abhörsicheren Übertragung kümmern zu
müssen.
Die hier vorgestellten ipchains-Regeln dienen nur zur Veranschaulichung und
sind zum Betrieb eines auf eine konkrete Anwendung bezogenen Firewalls in
den wenigsten Fällen ausreichend. Da Firewalls sehr individuell auf den
Benutzerkreis abgestimmt werden müssen, ist es nicht möglich,
ein auch nur annähernd allgemeingültiges Init-Shellskript mit
ipchains-Regeln für einen Firewall anzugeben, auch wenn dies bei vielen
Distributionen mittlerweile versucht wird. Zur Konfiguration eines Firewalls
und zum komfortablen Aufstellen der Regeln gibt es jedoch diverse
graphische Tools, mit denen das Einrichten eines Firewalls ohne genaue Kenntnis
der Syntax von ipchains oder Kenntnis von Abläufen im Kernel möglich
gemacht werden soll. Links hierzu sind u.a. auf den unten angegebenen
Web-Seiten zu finden.