Autor Thema: Einrichten eines Routers mit Firewall unter Linux  (Gelesen 8611 mal)

0 Mitglieder und 1 Gast betrachten dieses Thema.

Offline Dennis

  • HT4U.net Redakteur
  • 64-Bit-Prozessor
  • *****
  • Beitr├Ąge: 5939
  • Geschlecht: M├Ąnnlich
  • Killerspiele-Spieler!
    • Profil anzeigen
    • Meine :)
Einrichten eines Routers mit Firewall unter Linux
« am: 16. Juni 2005, 19:39:58 »
Einrichten eines Routers mit Firewall unter Linux

Die etwas komplexeren Themen unter Linux, Firewalling und Routing, sind, wenn man sich erst einmal eingearbeitet hat sehr interessant. Ziel dieser Doku soll sein eine Iptables basierende Firewall auf einem Linuxsystem aufzusetzen und dieser noch Routingf├Ąhigkeiten zu vermitteln. Es wird hier aber etwas Grundverst├Ąndnis von Netzwerken vorausgesetzt, man sollte also schon wissen was man an Ports, IPs etc. f├╝r seinen Rechner braucht. Ich werde hier aber nur die notwendigen Befehle dokumentieren und ein Firewall Script anh├Ąngen. Ich werde nicht erkl├Ąren wie dieses Script im einzelnen funktioniert. Wer eine einfache Firewall selbst erstellen will f├╝r den ist diese Doku richtig. Das angeh├Ąngte Script ist ca. 200 Zeilen lang, nach dem durcharbeiten dieser Doku sollte aber klar sein was dort passiert. Aber selbst gemacht ist doch immer noch am besten ;-).

Firewalling unter Linux mit iptables

Die Policies

Als erste muss man sich damit befassen; Was kann iptables? Ich w├╝rde soweit gehen, zu sagen eigentlich alles was man mit IP Traffic anstellen kann: Routen, Ports filtern, Traffic verschleiern etc. Ich werde mich hier nur auf die simplen Regeln bzw. Regelketten von iptables beziehen, da der Umfang von iptables einfach enorm ist. Die Grundketten die immer existieren sind folgende:

INPUTSteht f├╝r alle Pakete die ins System wollen
OUTPUTSteht f├╝r alle Pakete die aus dem System raus wollen
FORWARDSteht f├╝r alle Pakete die weitergeleitet werden wollen

Schauen wir uns doch einfach mal auf einem System ohne aktive Firewall die iptables an. Das geschieht mit dem einfachen Befehl iptables -L. Dieser sollte im Normalfall folgende Ausgabe bringen.

[root@auriga bin]# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
[root@auriga bin]#

Hie sehen wir die o.g. 3 Regelketten. Jede dieser Regelketten ist mit einer Policy versehen, die man ├Ąndern kann. Die Policy ist die globale Regel, die als Standard f├╝r alle Verbindungen gilt, die der jeweiligen Kette entsprechen. D.h. wenn die Policy von INPUT auf DROP stehen w├╝rde, w├╝rde s├Ąmtlicher eingehender Traffic geblockt, egal was und egal woher der Traffic stammt. Genau andersherum sieht es aus wenn die Policy wie hier auf ACCEPT steht. Des Weiteren ist zu erkennen dass in noch keiner der Ketten eine benutzerdefinierte Regel existiert.

Wie man an den Policies sehen kann, wird jede Verbindung, die nur irgendwie hergestellt werden kann, akzeptiert. Das kann f├╝r ein sicheres System so nicht bleiben. Mit dem Befehl iptables -P Policy DROP, Policy steht f├╝r INPUT, OUTPUT oder FORWARD kann ich jede Verbindung blockieren. Setze ich jetzt allerdings die Policies auf DROP, so ist das System komplett abgeschottet. Wenn man also per ssh oder telnet an seiner Maschine arbeitet w├Ąre es eine ganz dumme Idee das jetzt zu testen. Wie man an dieser Stelle gut sieht, sollte man das ganze in einem Script schreiben, das die ganzen Befehle abhandelt. Denn wenn die Policies auf DROP stehen, muss der Maschine danach ja mitgeteilt werden welcher Verkehr denn nun aber trotzdem zugelassen wird.

Die erste benutzerdefinierte Regel

Da wir gerade ├╝ber eine SSH Verbindung arbeiten brauchen wir als erstes einen offenen Port f├╝r SSH, das funktioniert wie folgt:

Die Schalter, die wir f├╝r diesen Befehl brauchen sind folgende:

-A   ADD Rule, Regel in die danach angegebene Kette einf├╝gen (Hier INPUT)
-i   incoming Interface, Angabe ├╝ber welche Karte das Paket kommt (ppp0, ethx ...)
-p   Protocol, Angabe des Protokolls (tcp, udp, icmp)
--dport   Destination Port, nur anwendbar mit vorhergehendem -p tcp oder -p udp
   entsprechender Port der ├╝berwacht werden soll (Hier 22 f├╝r SSH)
-j   jump, was soll mit dem Paket geschehen (ACCEPT, DROP, REJECT, DNAT, SNAT ...)

Der auszuf├╝hrende Befehl:

[root@auriga bin]# iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT
Wenn wir diesen Befehl eingegeben haben, k├Ânnen wir die Policy f├╝r INPUT auf DROP setzen. Jetzt nimmt er aber nur noch Pakete ├╝ber die Netzwerkkarte eth0 auf Port 22 an, denn der gesamte restliche Verkehr wird jetzt blockiert, selbst INPUT Anfragen vom localhost. Localhost kann aber eh nur jemand sein der am Rechner sitzt und Pakete verschickt was im Normalfall der User selbst sein sollte, also lassen wir alle eingehenden Verbindung vom localhost auch zu.

[root@auriga bin]# iptables -A INPUT -i lo -j ACCEPT
Hier sieht man gut, dass man nicht immer mit Protokollangaben und Ports arbeiten muss. Ich sage einfach INPUT vom Interface lo akzeptieren. Lassen wir uns noch einmal die iptables anzeigen.

[root@auriga bin]# iptables -L
Chain INPUT (policy DROP)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere           tcp dpt:ssh
ACCEPT     all  --  anywhere             anywhere

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
[root@auriga bin]#


Hier sehen wir jetzt, dass die Policy f├╝r INPUT auf DROP ge├Ąndert wurde und unsere beiden erstellten Regeln in der Kette Input enthalten sind. Mit dem Befehl iptables -L -v kann man noch eine detailliertere Ausgabe aktivieren, dort sieht man dann auch die Interfaces.

Um aber noch ein Stufe auf der Sicherheitsleiter hoch zu gehen, setzen wir die Policies OUTPUT und FORWARD auch auf DROP. Vorher m├╝ssen wir aber noch angeben, welche Interfaces noch ins Netz senden d├╝rfen. Das sind bei uns die beiden Netzwerkkarten eth0, eth1 und das lo interface, denn raus ist ja erst mal egal, rein darf nichts kommen.

[root@auriga bin]# iptables -A OUTPUT -o eth0 -j ACCEPT
[root@auriga bin]# iptables -A OUTPUT -o eth1 -j ACCEPT
[root@auriga bin]# iptables -A OUTPUT -o lo -j ACCEPT

und danach

[root@auriga bin]# iptables -P OUTPUT DROP
[root@auriga bin]# iptables -P FORWARD DROP

Jetzt ist s├Ąmtlicher Verkehr von innen nach aussen erlaubt, aber es kann nur eine Verbindung ├╝ber Port 22 TCP von aussen nach innen erfolgen der Rest ist blockiert. Um weitere Ports freizugeben einfach an den obigen Befehl f├╝r SSH halten und aus der 22 den gew├╝nschten Port machen, bzw. f├╝r UDP Verbindungen aus dem -p tcp ein -p udp machen und den gew├╝nschten Port ├Ąndern. Falls ihr nicht wisst welche Ports ihr freigeben m├╝sst gibt es in der /etc/services eine sehr gute ├ťbersicht. Hier einmal kurz die wichtigsten Ports.

20,21TCPFTP
22TCPSSH
80TCPHTTP
445TCPSAMBA

Erweiterte Regeln & Zusatzmodule

Hat man seine ganzen Ports korrekt freigegeben, kann man noch folgende 2 Befehle einf├╝gen.

[root@auriga bin]# iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
Damit werden neu ausgehende Pakete geblockt, die nicht zu einer regul├Ąren Verbindung geh├Âren. Eine TCP Paket was eine neue Verbindung anfordert, w├╝rde ein syn Flag haben. Durch das ! wird hier aber abgefragt ob es ein Paket ist, dass kein g├╝ltiges syn Flag hat, aber trotzdem eine neue Verbindung ├Âffnen will. Sollte dies  der Fall sein so wird dieses Paket geblockt.

[root@auriga bin]# iptables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
Dieser Befehl erlaubt Pakete durchzuschleusen auf schon hergestellten (ESTABLISHED) Verbindungen, oder auf Verbindungen, die zu einer anderen offenen Verbindung Bezug hat. (RELATED)

Hier hinzugekommen ist der Schalter -m dieser l├Ądt verschiedene Module, in diesem Fall das Modul state. Als zweiter Schalter, der zu dem Modul state geh├Ârt sieht man --state. Damit kann man verschiedene Statusabfragen an dem aktuellen Paket durchf├╝hren was hier mit NEW, ESTABLISHED und RELATED geschehen ist.

Wer aufmerksam gelesen hat, dem d├╝rfte bei dem Jump Schalter noch das REJECT in Erinnerung sein, dieses hat die gleiche Wirkung wie DROP, schickt aber eine Fehlermeldung zur├╝ck. Sollte also ein Rechner von au├čen auf unseren Router zugreifen und auf eine Regel Treffen, die bei uns mit einem REJECT behandelt wird, so bekommt er eine Fehlermeldung und wei├č das der Rechner da ist. Ist die Verbindung mit einem DROP versehen, so wird das ankommende Paket einfach weggeschmissen und es wird auf den Verbindungsversuch nicht reagiert. Es gibt noch viel mehr als nur ACCEPT, DROP und REJECT f├╝r eine komplette Liste aller m├Âglichen Varianten kann man sich die MAN-PAGES von iptables mit man iptables anschauen.

Das ist eigentliche das Grobe zum Firewalling, iptables ist ein sehr effektives Tool zum Verwalten von IP Verkehr das ich hier in seinen kompletten M├Âglichkeiten nur anreissen kann. Kommen wir dann jetzt zum wirklich interessanten Teil, dem Routing.

Wer noch einen alten lautlosen Rechner herumzustehen hat, f├╝r den d├╝rfte das folgende Kapitel sehr interessant werden. Voraussetzung dazu sind eben dieser Rechner mit einer funktionierenden Linux Installation, 2 Netzwerkkarten, oder die etwas unsch├Âne Variante mit einer Karte und einem Switch.

Routing unter Linux mit iptables

Als erstes m├╝ssen wir aus dem Rechner ein Gateway machen, so dass er ├╝berhaupt als Router fungieren kann. Dazu muss IP Forwarding aktiviert werden, ohne dem w├╝rde dass Ger├Ąt keine IP Adressen durchreichen und w├Ąre einfach nur ein Rechner im Netz. Um das IP Forwarding zu aktivieren muss in der Datei /proc/sys/net/ipv4/ip_forward eine 1 eingetragen werden. Das geht ohne die Datei manuell ├Âffnen zu m├╝ssen ganz einfach mit dem Befehl.

[root@auriga bin]# echo "1" > /proc/sys/net/ipv4/ip_forward
Echo ist nur f├╝r Bildschirmausgabe zust├Ąndig, w├╝rde ich nur echo "1" eingeben so w├╝rde mir auf dem Bildschirm einfach eine 1 ausgegeben werden. Durch das > leite ich die Ausgabe in die dahinter- stehende Datei um. Somit steht jetzt die 1 in der ip_forward Datei.

Jetzt muss noch die IP Verschleierung aktiviert werden, d.h. Pakete die von einem Rechner an den Router geschickt werden erhalten als AbsenderIP die IP des Routers. W├╝rde er das nicht machen, so w├╝rde das Paket mit der Absende IP meines Rechners rausgehen und das Ziel w├╝rde auf diese Adresse versuchen zu antworten was ja unm├Âglich ist. Stattdessen muss die Antwort an den Router erfolgen der sie dann zu mir schickt. Um dieses zu realisieren gibt es noch 2 weitere Tabelle die Nat und die Mangle Tables. In diese m├╝ssen die Eintr├Ąge f├╝rs Routing erfolgen. Um in eine andere Tabelle eine Regel hinzuzuf├╝gen, muss mit dem Schalter -t die Tabelle angegeben werden. Der fertige Befehl sieht wie folgt aus.

[root@auriga bin]# iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
Durch -t nat wird die Regel in die NAT Tabelle, und durch -A POSTROUTING in die Kette POSTROUTING eingef├╝gt. Diese sorgt f├╝r Paket├Ąnderungen an Paketen, die dabei sind aus dem Router rauszugehen. Es gibt dort noch die Ketten PREROUTING und OUTPUT. PREROUTING steht dabei f├╝r ├änderungen an eingehenden Paketen und OUTPUT kann ├änderungen an lokal erstellten Paketen vornehmen.

Ändern von Paketdaten

Die Verschleierung mit MASQUERADE macht aber nur Sinn bei Interfaces, an denen sich die IP des ├ľfteren ├Ąndert, wie z.B. ISDN oder DSL Verbindungen. Die o.g. angegebene L├Âsung ist daher nicht die ganz optimalste, f├╝r das Routen in einem Netzwerk w├╝rde sich eher SNAT anbieten. Hierbei gebe ich dann die IP des Routers direkt an.

[root@auriga bin]# iptables -t nat -A POSTROUTING -o eth1 -j SNAT --to 172.21.18.18
Mit SNAT --to wird festgelegt dass alle Pakete die ├╝ber das Interface eth1, also unsere 2. Netzwerkkarte, rausgehen als Absender IP Adresse die 172.21.18.18 erhalten. Jetzt funktioniert unser Router ohne Probleme f├╝r rausgehende Verbindungen. Dadurch dass die Verbindung von unserem Rechner etabliert wird und durch den Router rausgeht, wei├č der Router auch wo die Antwortpakete hinm├╝ssen. Wenn jetzt aber Anfragen von Au├čen kommen, die auf meinem Rechner landen sollen, so laufen diese Anfragen am Router auf und er wei├č nichts damit anzufangen. Das beste Beispiel ist hierf├╝r ein FTP-Server. Ich habe auf meinem Rechner einen FTP-Server gestartet auf den jemand von Au├čen zugreifen will. Jetzt landet auf dem Router eine Anfrage auf Port 21, da auf dem Router aber kein FTP-Server l├Ąuft und er nichts damit anfangen kann schmei├čt er das Paket weg und gibt an den Anfragenden Clienten zur├╝ck Server nicht erreichbar. Jetzt gibt es ├╝ber die NAT Tabelle die M├Âglichkeiten zu sagen, Pakete die auf einem bestimmten Interface reinkommen und auf Port 21 adressiert sind an eine bestimmte IP zu senden. Diese Regel wird dann verst├Ąndlicherweise in die PREROUTING Kette geschrieben da diese ├änderung an eingehenden Paketen durchgef├╝hrt wird.

Also ├╝bliche Konfiguration das Paket kommt ├╝ber eth1 an und soll auf meinen Rechner, der an eth0 verbunden ist mit der IP 172.21.1.128. Als erstes der Befehl:

[root@auriga bin]# iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 21 -j DNAT --to 172.21.1.128
Anstatt SNAT wird hier als Ziel DNAT eingetragen, da dieses Mal nicht die Source sondern die Destination IP ge├Ąndert wird. Alle Pakete die an eth1 ankommen und auf Port 21 anklopfen, bekommen jetzt als Zieladresse die 172.21.1.128 und erreichen den FTP-Server der auf meinem Rechner l├Ąuft. Jetzt stehen wir aber vor einem Problem. Wir haben am Anfang die Policy f├╝rs IP Forwarding auf DROP gesetzt, d.h. es wird trotz der eingestellten Routen nicht ein Paket weitergereicht, da dass von unserer Firewall blockiert wird. Die einfachste Variante w├Ąre die Policy wieder auf ACCEPT zu setzen, da man ohne Routing Regeln, von au├čen ├╝ber den Router, sowieso nicht an die dahinter liegenden Rechner herankommt. Aber da wir eine sichere Firewall haben wollen und die Policy daher auf DROP lassen, muss es noch einen anderen Weg geben.

Freischalten der Paketweiterleitung

Wir erinnern uns an die 3 Ketten in der Firewall INPUT, OUTPUT und FORWARD. Wir haben Regeln f├╝r INPUT und OUTPUT festgelegt, aber noch keine f├╝r FORWARD. In die FORWARD Kette werden n├Ąmlich genau die Regeln eingetragen die das Routing zulassen. In der FORWARD Kette muss immer ein Interface angegeben werden, ├╝ber das die Pakete hereinkommen und das Interface an das sie weitergeleitet werden. Lassen wir am besten erst einmal die Weiterleitung von meinem PC durch den Router nach Au├čen zu:

[root@auriga bin]# iptables -A FORWARD -i eth0 -o eth1 -j ACCEPT
Verkehr der durch eth0 hereinkommt und an eth1 wieder raus soll wird zugelassen. Jetzt kann von au├čen aber immer noch keiner auf meinen FTP-Server zugreifen. Jetzt kommen wieder die identischen Schalter, wie auch bei INPUT und OUTPUT zum Einsatz und zus├Ątzlich -d mit dem ich die Zieladresse der Pakete angebe.

[root@auriga bin]# iptables -A FORWARD -i eth1 -o eth0 -d 172.21.1.128 -p tcp --dport 21 -j ACCEPT
Pakete die auf eth1 ankommen und ├╝ber eth0 auf die Adresse 172.21.1.128:21 geleitet werden sollen, werden erlaubt. Mit diesen Regeln bewaffnet kann man sich einen sauber funktionierenden Router zusammenbasteln, den man nach Herzenslust selbst konfigurieren kann. Vor allem ist er nicht von der Stange, sondern selbst gemacht.

Sonstige Tipps und Hinweise

Zu beachten ist, dass f├╝r Pakete die weiter geleitet werden sollen, bei INPUT keine Ports ge├Âffnet werden m├╝ssen. F├╝r diese Pakete ist der Router gar nicht da, sie treffen zwar bei ihm ein, werden aber nur durchgeschleust. Beim erstellen der Routing Regeln ist darauf achten, dass auch f├╝r jede eine FORWARD Regel angelegt wird, bzw. man l├Ąsst die Policy auf ACCEPT je nach dem wie sicher man es machen will.

Sollte man auf absolute Sicherheit bedacht sein, so kann man zu jeder Regel noch einstellen dass ein Paket von einer bestimmter Quelle kommen muss. Man k├Ânnte SSH z.B so einstellen dass nur mein Rechner auf diesen Port zugreifen darf. Wir erinnern uns an den ersten Befehl:

[root@auriga bin]# iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT
Jeder der auf eth0 an Port 22 eine SSH Verbindung anfordert wird zugelassen. Wenn jetzt aber nur mein Rechner auf diesen Dienst Zugriff haben soll, so k├Ânnen wir noch explizit die Source IP angeben. Das ganze sieht dann so aus:

[root@auriga bin]# iptables -A INPUT -i eth0 -s 172.21.1.128 -p tcp --dport 22 -j ACCEPT
Jetzt kann nur noch der Rechner mit der IP 172.21.1.128 auf Port 22 zugreifen. Man kann hier alternativ auch ein Netz angeben z.B. 172.21.0.0/18. Dadurch k├Ânnen nur noch Rechner aus meinem Netz auf SSH zugreifen. Verantwortlich daf├╝r ist der Schalter -s (Source).



Und mein pers├Ânliches Firewall Skript

Das habe ich in 2 Tagen Langeweile auf Arbeit erstellt und es gerade auf meinem Rechner hier installier. Es l├Ąuft 1A ;D

Fragen, Anregungen und Kritik k├Ânnt ihr Hier loswerden.
« Letzte ├änderung: 14. November 2005, 14:58:36 von CaBaL »
|| HT4U ||

Offline Dennis

  • HT4U.net Redakteur
  • 64-Bit-Prozessor
  • *****
  • Beitr├Ąge: 5939
  • Geschlecht: M├Ąnnlich
  • Killerspiele-Spieler!
    • Profil anzeigen
    • Meine :)
Diskussion zu Router mit Firewall unter Linux
« Antwort #1 am: 16. Juni 2005, 19:42:01 »
KLICK

Mal wieder ein Excerpt meiner erfolgreichen Testrechnerqu├Ąlerei :P

Wen es interessiert bitte ausreichend Kritik, bin momentan noch am ├╝berarbeiten, finde das Thema aber so interessant da hab ichs heute schon einmal gepostet ;)
« Letzte ├änderung: 16. Juni 2005, 19:43:02 von CaBaL »
|| HT4U ||

deathinjune

  • Gast
Re:Diskussion zu Router mit Firewall unter Linux
« Antwort #2 am: 21. Juni 2005, 23:02:22 »
Mag mich ja irren, aber kann es sein, dass das nur unter Debian funktioniert? Ich hab' das Skript ├╝berflogen und mich gefragt, ob das ├╝berhaupt mit Fedora und Redhead so hinhaut.

Offline Dennis

  • HT4U.net Redakteur
  • 64-Bit-Prozessor
  • *****
  • Beitr├Ąge: 5939
  • Geschlecht: M├Ąnnlich
  • Killerspiele-Spieler!
    • Profil anzeigen
    • Meine :)
Re:Diskussion zu Router mit Firewall unter Linux
« Antwort #3 am: 22. Juni 2005, 18:16:30 »
Hmm, kann ich nicht nachvollziehen.

Was soll denn nicht funktionieren ??? und *hust* das Skript wurde unter RedHat erstellt ;)
|| HT4U ||