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:
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.
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/0 -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:
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/0 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/0 ü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/0 -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.