Nachdem wir im ersten Teil wie die Axt im Walde gehaust und fast alle Daemons erledigt haben, bauen wir jetzt eine einfache Firewall für den Hausgebrauch auf, die die letzten Mauselöcher stopfen soll.
Wir gehen davon aus, dass Sie wie in der letzten Ausgabe beschrieben die wichtigsten – oder unnützesten – Dienste abgeschaltet haben, und können uns der Absicherung der verbleibenden Daemons zuwenden. Dazu verwenden wir eine Firewall, die Zugriffe von draußen reglementiert.
Das Thema Firewall ist als überaus komplex verschrien – leider zu Recht, doch für den Heimgebrauch ist man mit nur ein paar Zeilen dabei. Administratoren, die große Server bei Firmen und Providern konfigurieren, müssen viele Randbedingungen und Spezialdienste berücksichtigen, die beim Heimanwender keine oder nur eine untergeordnete Rolle spielen.
Für unser Beispiel verwenden wir einen Rechner, der sich via ISDN-Karte ins Internet einwählt. Als Interface verwenden wir hier ippp0, und benutzen 192.168.1.1 als unsere vom Internet-Provider zugewiesene Adresse (IP). Modem-Benutzer brauchen lediglich das “i” im Gerätenamen weg lassen, das Modem-Interface heißt meist ppp0. Auch Netzwerkkarten können benutzt werden, hier wird entsprechend eth0 verwendet, die Vorgehensweise ist stets gleich.
Die Firewall arbeitet als Filter zwischen allen Netzwerk-Geräten wie Modems, ISDN- und Netzwerkkarten und dem internen Bereich. Welche Daten letztendlich wo landen, wird dabei durch Filter-Regeln festgelegt. Für diese Regeln gibt es vier grundlegende Bereiche: Alle in der Sektion input eingetragenen Regeln werden wie eine Kette (chain) nacheinander auf alle ankommenden Datenpakete angewandt, während die unter output stehenden Regeln nacheinander auf alle ausgehenden Datenpakete Anwendung finden. forward-Regeln dienen insbesondere dem Masquerading, und als viertes können eigene Sektionen angelegt und mit Regeln bestückt werden. Dies ist im Heimbereich meist nicht nötig, und auf Masquerading werden wir in einem gesonderten Artikel eingehen.
Die Standard-Kernel der meisten Distributionen sind bereits mit Firewall-Support versehen, so dass ein Neu-Übersetzen entfällt. Auch das benötigte Paket ipchains wird bei fast allen Standard-Installationen eingerichtet, im Zweifelsfall finden Sie es bei den Netzwerk-Utilities und müssen es nachinstallieren.
Wie oben angesprochen wollen wir die “Schotten dicht” machen und nur einzelne, handverlesene Dienste freigeben. Dieses Vorgehen hat prinzipiell Nachteile, doch darauf gehe ich bei den entsprechenden Regeln noch genauer ein. Mit ipchains -n -L können Sie sich jederzeit die jeweils eingerichteten Regeln ansehen. Eingangs ist alles erlaubt:
linux:~ # ipchains -L Chain input (policy ACCEPT) Chain forward (policy ACCEPT) Chain output (policy ACCEPT)
Unter policy ist die grundsätzliche Haltung gegenüber den Datenpaketen zu verstehen: Sind alle Regeln einer Kette (chain) auf das Paket angewandt worden, ohne dass das Paket an eine andere Stelle weiter geleitet wurde, wird es bei ACCEPT akzeptiert oder bei DENY verworfen. Wir wollen in unserem Fall erreichen, dass alles verboten wird, was nicht ausdrücklich erlaubt ist. Deshalb setzen wir die Input-Policy auf DENY:
ipchains -P input DENY
Die Regeln werden stets in Reihenfolge ihres Eintrags abgearbeitet – wir müssen also erst sagen, was wir von ippp0 akzeptieren, bevor wir den Rest verwerfen. Wenn ein Regelsatz, der offensichtlich keinen Fehler enthält, nicht funktioniert, liegt es meist an der falschen Reihenfolge. Ist ein Paket einmal verworfen, kann man es nicht in der nächsten Regel zurück bekommen.
Nun geht erst einmal überhaupt nichts mehr: Alle Daten, egal ob wir sie über Netzwerk, ISDN, Modem oder auch lokal erhalten, werden verworfen. Damit wir lokal alle Dienste benutzen können und auch unsere grafische Oberfläche weiterhin funktioniert, müssen wir uns selbst von der Verwerfung ausnehmen:
ipchains -A input -i lo -j ACCEPT
Der Parameter -A gibt an, dass wir eine Regel hinzufügen wollen, input steht für die gewünschte Sektion – alle ankommende Daten. Danach folgt die eigentliche Filter-Regel. -i lo betrifft alle über das Loopback-Device hereinkommenden Daten – das Loopback-Device können nur Programme benutzen, die auf unserem Rechner lokal laufen und Verbindung zu anderen Programmen oder Diensten auf unserer Maschine suchen. Mit -j sagen wir schließlich, was mit den Paketen geschehen soll: Sie werden akzeptiert.
Die totale Abschottung hat nicht nur positive Effekte. So erhalten wir Nachrichten, dass wir beispielsweise einen Server nicht erreichen können, nicht mehr. Diese Nachrichten sind für einen reibungslosen Internet-Verkehr aber sehr wichtig. Deshalb lassen wir sie als erstes zu, und war aus allen Richtungen:
ipchains -A input -p icmp -j ACCEPT
Der Parameter -p icmp benennt das Protokoll ICMP, das für die Übertragung der Nachrichten zuständig ist; -j ACCEPT steht wiederum für die Verfahrensweise: akzeptieren.
Nameserver freischalten
Ein ebenfalls sehr wichtiger Dienst ist der Domain Name Service, kurz DNS. Die DNS-Server, kurz Nameserver, sorgen für die Auflösung von beispielsweise http://www.linux-user.de in die IP-Adresse des Servers, hier 195.143.20.36. Ohne diese IP-Adresse geht im Internet gar nichts. Deshalb müssen wir auch unsere Nameserver freischalten.
Dazu benötigen Sie das Script aus Listing 1, das Sie unter dem Namen resolv-list im Verzeichnis /usr/local/bin speichern. Bitte vergessen Sie nicht, es anschließend mit chmod a+x /usr/local/bin/resolv-list ausführbar zu machen.
Listing 1
if [ -r /etc/resolv.conf ]; then
set – `grep -i nameserver /etc/resolv.conf`
while
[ $# -ge 2 ];
do
echo $2
shift 2
done
fi
resolv-list liefert uns eine Liste der verwendeten Nameserver, die wir mit folgenden Befehlen in unserer Firewall freischalten:
for ns in `/usr/local/bin/resolv-list`; do ipchains -A input -s $ns 53 -d 192.168.1.1 1024: -i ippp0 -p udp -j ACCEPT ipchains -A input -s $ns 53 -d 192.168.1.1 1024: -i ippp0 -p tcp -j ACCEPT done
Der Unterschied der beiden ipchains-Zeilen liegt in der Protokoll-Angabe mittels -p, hier einmal UDPund einmal TCP. Als Beispiel-Nameserver benutzen wir 192.168.2.1, je nach Internet-Provider unterscheidet sich die IP bei Ihnen. Es könnten aber auch mehrere Nameserver eingetragen sein, Linux verkraftet bis zu drei.
Die Adresse der Datenquelle wird mit -s angegeben, in unserem Beispiel wurde hier die Variable $ns eingetragen. Dahinter haben wir mit “53” die Port-Nummer, oder auch Dienste-Kennung, stehen. Schließlich wird noch das Ziel mit -d benannt, wobei auch hier die erlaubten Port-Nummern eingegrenzt werden können. Durch die Angabe 1024: haben wir alle Port-Nummern ab 1024 aufwärts bis 65535 erlaubt. Ports unterhalb von 1024 haben einen Sonderstatus, doch dazu später mehr.
Wenn Sie nun ipchains -n -L eingeben, sollten Sie folgende Liste erhalten:
Chain input (policy ACCEPT) target prot opt source destination ports ACCEPT all —— 0.0.0.0/0 0.0.0.0/0 n/a ACCEPT icmp —— 0.0.0.0/0 0.0.0.0/0 * -> * ACCEPT udp —— 192.168.2.1 192.168.1.1 53 -> 1024:65535 ACCEPT tcp —— 192.168.2.1 192.168.1.1 53 -> 1024:65535 Chain forward (policy ACCEPT) Chain output (policy ACCEPT)
Erschrecken Sie nicht bei der zweiten Zeile – auch wenn es hier so aussieht, als ob alles überall erlaubt wäre, ist dem nicht so. In dieser Ausgabeform wird der Gerätename, auf den sich die Regel bezieht, nicht angezeigt, und wir hatten bei der Einrichtung mit -i lo das lokale Loopback-Device angegeben.
Zugang erwünscht
Wir wollen zudem erlauben, dass sich bekannte Anwender auf unserem System einloggen können. Damit Benutzername und Passwort nicht ausgespäht werden können, erlauben wir nur die Verwendung der verschlüsselten Secure Shell, kurz SSH. Den dafür zuständigen Daemon sshd haben wir wohlweislich beim Daemon-Killen der letzten Ausgabe ausgespart. Die Freigabe erfolgt mit der Regel:
ipchains -A input -d 192.168.1.1 ssh -p tcp -i ippp0 -j ACCEPT
Mit dem Parameter -i ippp0 betrifft die Regel alle über die ISDN-Karte hereinkommenden Daten. Hätten wir noch eine Netzwerkkarte, an der weitere Linux-Rechner angeschlossen sind, so könnte sich von dort aus niemand mehr bei uns anmelden – wir haben die Regel auf die ISDN-Karte beschränkt und lehnen alles andere standardmäßig ab.
Diese Regel lässt also alle Datenpakete durch, die für den SSH-Dienst des Rechners 192.168.1.1 bestimmt sind und über die ISDN-Karte ippp0 hereinkommen. Da das Paket bereits akzeptiert ist, würden alle anderen Regeln nicht mehr zum Zug kommen. ipchains -n -L liefert uns nun:
Chain input (policy ACCEPT) target prot opt source destination ports ACCEPT all —— 0.0.0.0/0 0.0.0.0/0 n/a ACCEPT icmp —— 0.0.0.0/0 0.0.0.0/0 * -> * ACCEPT udp —— 192.168.2.1 192.168.1.1 53 -> 1024:65535 ACCEPT tcp —— 192.168.2.1 192.168.1.1 53 -> 1024:65535 ACCEPT tcp —— 0.0.0.0/0 192.168.1.1 * -> 22 Chain forward (policy ACCEPT) Chain output (policy ACCEPT)
Web-Server freigeben
Wenn wir nun noch unseren Apache-Webserver von außen erreichbar machen wollen, benötigen wir eine weitere ACCEPT-Regel:
ipchains -A input -d 192.168.1.1 http -p tcp -i ippp0 -j ACCEPT
Wie Sie sehen, ist das Muster das gleiche, lediglich die Dienst-Angabe hat sich geändert. Die Regel-Liste wurde um eine Zeile erweitert:
Chain input (policy ACCEPT) target prot opt source destination ports ACCEPT tcp —— 0.0.0.0/0 192.168.1.1 * -> 80
Ports und Dienste
Alles, was nicht erlaubt wurde, ist verboten – dazu zählt momentan alles, was nicht Nameserver-Antworten oder SSH-Verbindungen sind, auch der normale Surf-Betrieb. Dazu müssen wir uns jetzt überlegen, was wir für die normale Nutzung noch alles erlauben müssen, und das geht nicht ohne das Wissen um die Ports.
Hinter den Angaben der Dienste wie ssh oder http aus unseren Beispielen verbergen sich sogenannte Port-Nummern. Im Beispiel der Nameserver-Freigabe haben wir sogar einmal direkt mit der Port-Nummer 53 gearbeitet.
Man kann sich als Vergleich ein großes Mietshaus vorstellen, in dem die Briefkästen einfach durchnumeriert wurden – alle haben die gleiche Adresse (IP), und die Briefe können nur anhand der Briefkasten-Nummer (Port-Nummer) oder dem Namen am Briefkasten (Dienste-Bezeichnung) richtig zugestellt werden. Welcher Dienst welcher Port-Nummer entspricht, können Sie in der Datei /etc/services nachlesen.
Den Ports 0 bis 1023 fällt hier eine Sonder-Rolle zu: Diese Nummer sind für privilegierte Dienste reserviert, die dahinter stehenden Daemons laufen in aller Regel mit Root-Privilegien. Diese Ports stehen normalen Anwendern generell nicht zur Verfügung.
Antworten auf Anfragen, die der Netscape gestellt hat, gehen immer von Ports ab 1024 aus. Diese müssten wir noch freigeben. Aber wir können das ganze noch etwas einschränken: Es ist im Surfbetrieb nicht nötig, dass jemand Verbindung mit uns aufnimmt, denn wir fragen ja beim Server an und er liefert uns die Antwort über die gleiche Verbindung zurück. Eingehende Verbindungsanfragen werden deshalb nicht akzeptiert (! -y):
ipchains -A input -d 192.168.1.1 1024: -i ippp0 -p tcp -j ACCEPT ! -y
Einen Haken hat die ganze Aktion noch: Der SSH-Client des Anwenders versucht normalerweise, nach Anmeldung beim Server einen zweiten Kanal im Bereich von Port 600 bis 1023 zu öffnen. Dies geht nun nicht mehr, bis einschließlich Port 1023 ist alles dicht. Abhilfe finden Sie im Kasten “SSH & Firewall”.
Praktische Auswirkungen
Noch einmal zusammengefasst: Wir akzeptieren SSH-Verbindungen, die über die ISDN-Karte ankommen, genauso wie Anfragen an unseren Apache-Webserver. Auch ICMP-Nachrichten, Antworten des DNS-Servers und abgerufene Internet-Daten werden durchgelassen. Ein Verbindungsaufbau von außen, der nicht über SSH oder den Webserver geht, wird hingegen immer ignoriert.
Für einen Benutzer, der an Ihrem Rechner sitzt, bedeuten diese Einstellungen nur geringfügige Einschnitte. So kann er, selbst wenn der talk-Daemon aus der letzten Ausgabe nicht abgeschaltet worden ist, nicht vom Internet aus angesprochen werden. Auch die Administration von außen via swat oder linuxconf ist unmöglich, vom eigenen Recher aus funktioniert es problemlos. Einzig im IRC greift eine Einschränkung: Wir können keine Dateien mehr via DCC oder anderweitig schicken. Auch unser FTP-Server ist für Außenstehende nicht erreichbar.
Wir haben Ihnen in Tabelle 1 eine Liste von Erlaubnis-Regeln zusammengestellt, die Sie zur Freigabe einzelner Dienste in die Firewall einbauen können.
Tabelle 1: Regeln zur Dienst-Freigabe
| Nameserver | ipchains -A input -d <§§I>IP<§§I> 53 -p udp -i <§§I>Interface<§§I> -j ACCEPT |
ipchains -A input -d <§§I>IP<§§I> 53 -p tcp -i <§§I>Interface<§§I> -j ACCEPT |
|
| SSH-Zugang | ipchains -A input -d <§§I>IP<§§I> ssh -p tcp -i <§§I>Interface<§§I> -j ACCEPT |
| Telnet-Zugang: | ipchains -A input -d <§§I>IP<§§I> telnet -p tcp -i <§§I>Interface<§§I> -j ACCEPT |
| Sendmail-Zugang | ipchains -A input -d <§§I>IP<§§I> smtp -p tcp -i <§§I>Interface<§§I> -j ACCEPT |
| Apache-Webserver | ipchains -A input -d <§§I>IP<§§I> http -p tcp -i <§§I>Interface<§§I> -j ACCEPT |
| FTP-Zugang | ipchains -A input -d <§§I>IP<§§I> ftp -p tcp -i <§§I>Interface<§§I> -j ACCEPT |
ipchains -A input -s 0/0 ftp-data -d <§§I>IP<§§I> 1024: -p tcp -i <§§I>Interface<§§I> -j ACCEPT |
|
| ICQ | ipchains -A input -d <§§I>IP<§§I> 4000 -p tcp -i <§§I>Interface<§§I> -j ACCEPT |
| IRC mit DCC | ipchains -A input -d <§§I>IP<§§I> 1024: -p tcp -i <§§I>Interface<§§I> -j ACCEPT |
| Diese Regel ist mit Vorsicht zu verwenden, sie erlaubt den Verbindungsaufbau von außen auf nicht-privilegierten Ports. Es darf dann keine andere Regel für Protokoll TCP und Ports ab 1024 aufwärts aktiv sein. |
Automatische Aktivierung
Ein ganz großes Problem für den Aufbau einer privaten Firewall ist, dass sich bei jeder Einwahl die eigene Adresse (IP) ändert – und sie entsprechend in den Firewall-Regeln korrigiert werden muss. Die meisten Konfigurations-Tools für Firewalls sehen die Änderung der IP-Adresse nicht vor und sind so nicht direkt für den Heimgebrauch geeignet.
Optimal wäre, wenn die Regeln nach jeder Anwahl automatisch aktiviert und beim Auflegen wieder deaktiviert würden, natürlich mit der korrekten IP.
Die gesuchten Skripte, in die wir die Regeln einbauen können, lauten /etc/ppp/ip-up und /etc/ppp/ip-down. ip-up wird aufgerufen, sobald die Einwahl erfolgt ist, und nach Auflegen ip-down. Dabei nutzen wir aus, dass uns als Parameter $1 das Modem- beziehungsweise ISDN-Interface und als $4 unsere zugewiesene IP-Adresse mitgeteilt wird. Da für die Einrichtung und Entfernung der Firewall-Regeln fast die selbe Befehlszeile benutzt wird, fassen wir die Regeln in der Datei /etc/ppp/inet_chains zusammen, wobei wir für die IP und das verwendete Interface die entsprechenden Variablen verwenden. Sie finden ein entsprechendes Beispiel auf der Heft-CD unter LinuxUser/firewall/inet_chains. Dort sind auch alle in Tabelle 1 genannten Freigaben vorhanden, jedoch mit einer Raute (#) am Anfang der Zeile auskommentiert und so unwirksam. Möchten Sie einzelne Dienste freischalten, brauchen Sie nur die Raute zu entfernen. Die Datei /usr/local/bin/resolv-list aus Listing 1 wird dafür übrigens nicht mehr benötigt, inet_chains verfügt über eine entsprechende Funktion.
Den Aufruf der inet_chains müssen Sie relativ zu Anfang, am besten gleich als zweite Zeile, in der /etc/ppp/ip-up und /etc/ppp/ip-down eintragen: In /etc/ppp/ip-up:
test -x /etc/ppp/inet_chains && /etc/ppp/inet_chains up $@
In /etc/ppp/ip-down:
test -x /etc/ppp/inet_chains && /etc/ppp/inet_chains down $@
Fazit:
Bei den Distributoren besteht dringender Nachholbedarf, was die Standard-Installationen angeht. Einzig Mandrake verfügt über einen brauchbaren Mechanismus, der bei paranoider Einstellung fast alle Dienste abschaltet. Bei den meisten anderen helfen selbst Sicherheitsprofile wenig. Insbesondere Einsteiger-Distributionen, allen voran die Personal-Edition der SuSE 7.0, sollte jedoch auf die Bedürfnisse der Endanwender abgestimmt werden. Bleibt zu hoffen, dass dies in den nächsten Versionen der großen Distributoren berücksichtigt wird.
Dennoch, einen wirklich sicheren Rechner gibt es nicht. Auch wenn Sie mit den beschriebenen Möglichkeiten einigermaßen gut von außen geschützt sind, wird vielleicht irgendwann der alles außer Kraft setzende Fehler gefunden. Und eins sollten sie wissen: Das Internet ist böse, und irgendwann erwischt es jeden.
SSH & Firewall
SSH versucht normal, über einen Port zwischen 600 und 1023 einen zweiten Kanal aufzubauen. Dies haben wir mit der im Artikel eingerichteten Firewall jedoch unterbunden, SSH würde keine Verbindung hinbekommen. Dafür gibt es zwei Lösungsmöglichkeiten: Entweder, Sie rufen SSH mit dem Parameter “-P” auf, oder sie ändern die Rechte von SSH. Normal wird jede SSH-Verbindung mit Root-Rechten aufgebaut, um eben einen Port unterhalb 1024 verwenden zu können. Durch den Befehl chmod u-s `which ssh` sorgen Sie dafür, dass SSH in Zukunft mit Ihren Benutzer-Rechten gestartet wird – und autmatisch einen Port oberhab 1023 für den Rückkanal benutzt.
Glossar
-
Firewall
-
Brandschutzwand. Eine Firewall wird immer dort eingesetzt, wo vertrauenswürdige und fremde Netzwerke aufeinander treffen, zum Beispiel auf Firmen-Servern, die den Internet-Zugang bereit stellen. Die Firewall soll verhindern, dass Unbefugte von außerhalb auf den internen, vertrauenswürdigen Bereich zugreifen können. Je nach Komplexität und Umfang des Netzwerks kann die Einrichtung mehrere Tage erfordern. Aber auch im Heimbereich sind Firewalls sinnvoll, wenn man den eigenen Rechner vor Zugriffen aus dem Internet schützen möchte.
-
Masquerading
-
Maskierung, Maskerade. Wird vornehmlich auf Servern eingesetzt, die einem privaten Netzwerk Zugang zum Internet vermitteln. Durch das Masquerading bekommen alle Anfragen aus dem internen Netzwerk als Absender die IP-Adresse des Servers. Die Antworten werden dann wieder zurück übersetzt, so dass von innen kein Unterschied zwischen maskierter und unmaskierter Verbindung festzustellen ist. Nach außen hin sind die privaten Rechner jedoch nicht erreichbar, da ihre IP-Adressen nicht bekannt gegeben werden – Anfragen können also nur mit der IP des Masqueraders versehen sein, und diese landen beim Server selbst. Eine häufige Anwendung für Masquerading sind Standleitungen oder Flatrates, bei denen mehrere Rechner angeschlossen werden sollen. Die Provider geben pro Anschluss meist nur eine einzige IP-Adresse heraus, mit der sich auch nur ein Rechner ansprechen ließe. Alle anderen Rechner benutzen private IP-Adressen, und der Masquerader versieht Anfragen ins Internet mit seiner eigenen IP und sorgt für die Zustellung der Antworten.
-
ICMP
-
Internet Control Message Protocol – wird verwendet, um bei Nichterreichbarkeit eine entsprechende Nachricht an den Anfrager zu schicken. Auch ping versendet per ICMP echo-request (Bitte um Rücksenden) kleine Datenpakete an die Gegenstation, um von ihr via ICMP echo-reply (Antwort) die gleichen Daten zurück zu bekommen. Daraus lässt sich die Laufzeit zwischen Senden und Empfangen bestimmen.
-
UDP
-
User Datagram Protocol – ein verbindungsloses Protokoll, Datenpakete werden also vom Empfänger nicht bestätigt. Auch wiederholt der Absender die Daten nicht. Dies wird zum Beispiel bei Abfragen von DNS-Servern benutzt, um zu einem Hostnamen die zugehörige IP-Adresse zu erfragen. Da keine Verbindung aufgebaut wird, ist UDP sehr schnell. UDP-Daten können nicht direkt über das Internet versandt werden, weshalb man sie normal in IP-Pakete verpackt.
-
TCP
-
Transfer Control Protocol – ein sehr häufig verwendetes Protokoll im Internet. Es wird oft fälschlicherweise mit TCP/IP benannt, obwohl es sich hier um zwei Protokolle (TCP und IP) handelt. Das TCP sorgt unter anderem dafür, dass Daten in der richtigen Reihenfolge zusammengebaut werden.
-
IP
-
Internet Protocol – gewährleistet die Übertragung von Datenpaketen im Internet. Hier kommen die IP-Adressen zum Einsatz, die Absender und Empfänger eindeutig identifizieren. UDP-, ICMP- und TCP-Datenpakete werden vor Versand über das Internet in IP-Pakete verpackt und mit der Absender- und Empfänger-Adresse versehen.
Infos
[1] Deutsches Firewall-Handbuch von Guido Stepken mit vielen Beispielen: http://www2.little-idiot.de/firewall/
[2] Anmerkungen und Erweiterungen von Dirk Haase für EasyLinux-Benutzer zum ersten Teil von “Schotten dicht!”: http://members.tripod.de/kridsoft/easyl/ha/ha005.html
