Linux-Router/-Server im Eigenbau

ein Projekt der Infinity-Community


Routing- und Firewall-Konfiguration


1. Grundbegriffe

Als erstes möchte ich hier einige Grundbegriffe einführen, deren Kenntnis weiter unten entscheidend zum Verständnis beitragen kann. - Wer allerdings sofort loslegen möchte, kann natürlich auch direkt mit dem Einrichten des DNS-Servers und der Firewall beginnen.

DNS-Server:

Zitat [!] aus Wikipedia, der freien Enzyklopädie:
Das Domain Name System (DNS) ist eine hierarchische Datenbank zur Benennung von vernetzten Rechnern. Damit beim Benutzen des Internets statt unhandlicher IP-Adressen (z.B. 195.34.89.100) leicht merkbare Namen (z.B. wikipedia.de) verwendet werden können, wird das Domain Name System verwendet. Auf einem so genannten DNS-Server werden Rechnernamen den zugehörigen IP-Adressen zugeordnet und dem anfragenden Rechner mitgeteilt.

Damit auch die Rechner innerhalb unseres lokalen Netzes die Domain-Namen z.B. von Webseiten auflösen können, wird auf einem Internet-Router ein solcher DNS-Server benötigt. Eine Alternative währe zwar, den Rechnern innerhalb des lokalen Netzes den DNS-Server des Providers mitzuteilen, dieser kann sich jedoch (u.U. von Einwahl zu Einwahl) ändern.

Unter Linux wird als DNS-Server vorwiegend der Dämon "bind" in der Version 8 eingesetzt.

Routing:

Unter Routing versteht man die Vermittlung von Datenpaketen zwischen zwei (logisch) voneinander unabhängigen Netzen.
Ein Router muß, um Pakete vermitteln zu können, an beide Netze angeschlossen sein - benötigt im Normalfall also mindestens zwei Netzwerk-Interfaces (Netzwerkkarten, Modems, etc.).

Vergleichbar ist die Arbeit eines Routers mit der einer Hotel-Telefonistin Mitte des letzten Jahrhunderts.
Hier liegen zwei getrennte Telefonnetze vor - ein Hausinternes und ein öffentliches. Ein Gast kann nicht ohne weiteres nach "draußen" telefonieren oder angerufen werden.
Jeder Anruf, ob nach draußen oder drinnen, landet zunächst bei der Telefonistin. Erst diese sorgt dann für die erforderliche Verbindung zwischen den zwei Geschprächspartnern bzw. Telefonnetzen.

Unter Linux ist die Routing-Funktionalität im Linux-Kernel verankert und wird durch eine sogenannte Routing-Tabelle gesteuert. In der Routing-Tabelle befinden sich Informationen darüber, welches Netz sich hinter welchem Netzwerk-Interface verbirgt - und somit auch an welches Interface die Datenpakete für ein bestimmtes Netz weitergeleitet werden müssen.

In unserem Fall sind die zwei getrennten Netze unser Heimnetzwerk und das Internet. Die zwei Netzwerk-Interfaces sind die Netzwerkkarte zum LAN und das DSL-Modem. - Die Netzwerkkarte zum Modem fungiert in unserem Fall nur als "Modem-Anschluß".

NAT, Masquerading und Portforwarding:

Für die Kommunikation von Rechnern über's Internet ist es notwendig, daß diese jeweils eine öffentliche, weltweit gültige IP-Adresse besitzen. - Dies ist bei den in unserem Heimnetz angeschlossenen Rechnern jedoch nicht der Fall. Der einzige Rechner der seitens unseres Providers eine öffentliche IP-Adresse zugeweisen bekommt ist unser Router.

Um trotzdem Verbindungen aus unserem Heimnetz ins Internet zu ermöglichen, wird auf einem Internet-Router das sogenannte Masquerading eingesetzt, eine Ausprägung von NAT (Network Adress Translation).

Beim Masquerading werden in ausgehenden Paketen die privaten IP-Adressen unseres Heimnetzes duch die weltweit eindeutige IP-Adresse des ins Internet eingewählten Routers ersetzt. Dabei merkt sich der Router, welche Pakete er von welchem Rechner im Heimnetz zu welchem Rechner im Internet geschickt hat. Bei eingehenden Paketen schaut der Router in seinen Aufzeichnungen nach, welcher Rechner im lokalen Netz die Danten angefordert hat, überschreibt die Zieladresse der Pakete mit der privaten Adresse des entsprechenden Rechners und leitet sie weiter.

NAT - diesmal in der Ausprägung DNAT (Destination NAT) - benötigen wir auch dann, wenn wir bestimmte aus dem Internet kommende Pakete an einen bestimmten Rechner im lokalen Netz weiterleiten möchten. Dieses sogenannte Portforwarding dient z.B. dazu, eingehende HTTP-Anfragen an einen Web-Server innerhalb des lokalen Netzes weiterzuleiten.

(Peket-) Firewall:

Eine Firewall ist eine Software, welche alle ein- und ausgehenden Verbindungen auf bestimmte Eigenschaften hin überprüft und anhand eines Regelsatzes entscheidet, was mit ihnen zu geschehen hat. Meist ist dabei die Entscheidung zu treffen, ob eine Verbindung akzeptiert oder zurückgewiesen wird. Duch die Definition eines sinnvollen Regelsatzes ist es so möglich, einen Rechner oder ein komplettes Netzwerk vor unerwünschten oder gefährlichen Anfragen beispielsweise aus dem Internet zu schützen.

Eine Paket-Firewall, wie sie beispielsweise unter Linux implementiert ist, zeichnet sich dadurch aus, daß sie auf Paket-Ebene arbeitet - d.h. sie untersucht einzeln alle ein- und ausgehenden Datenpakete.

Netfilter und Iptables:

Netfilter ist ein Kernel-Modul, welches dem Kernel das beobachten, filtern und manipulieren von Paketen ermöglicht. Bei den gängigen Distributionen ist es im Standard-Kernel bereits enthalten.
Iptables ist eine allgemeine Tabellenstruktur zur Definition von Regelsätzen. Außerdem existiert ein gleichnamiges tool "iptables" mit dessen Hilfe die Regelsätze bearbeitet werden.
Zusammen mit einigen zusätzlichen Modulen bilden Netfilter und Iptables ein Framework zum Filtern und Manipulieren von Netzwerk-Paketen.
Mit Hilfe dieses Frameworks können wir unsere Firewall aufbauen und das Masquerading und Portforwarding verwirklichen.

Weiterführende Links:


2. DNS-Server einrichten

Wie weiter oben bereits erwähnt, wird als DNS-Server unter Linux vorwiegend "bind8" verwendet.

Unter SuSE kann dieser mit der Anweisung "rcnamed start" gestartet werden. Die Eingabe "rcnamed status" zeigt uns den momentanen Status des Dämons an. Weitere Optionen von rcnamed sind (wie bei anderen Init-Skripten auch) beispielsweise stop und restart.
Standardmäßig ist bind8 unter SuSE so vorkonfiguriert, daß er eingehende DNS-Anfragen (ins Internet) weiterleitet und zwischenspeichert. - Um die Konfiguration des DNS-Servers müssen wir uns also nicht weiter kümmern.

Nachdem wir den DNS-Server mit "rcnamed start" gestartet haben, kann unser Linux-Rechner als DNS-Server für andere Rechner in unserem lokalen Netzwerk dienen. Dazu müssen wir lediglich in der Netzwerkkonfiguration der Clients unter "DNS-Server" die IP-Adresse des Linux-Rechners eintragen.

Damit wir den DNS-Server (bind8) nicht nach jedem Linux-Neustart erneut starten müssen, gehen wir unter SuSE wie folgt vor:

Der DNS-Server wird ab jetzt bei jedem Bootvorgang automatisch gestartet.


3. Routing, Masquerading und Firewall einrichten

Im Folgenden geht es darum, ein Skript zu erstellen, welches alle für das Routing, das Masquerading und die Firewall notwendigen Einstellungen vornimmt.

Dazu werden wir uns zunächst anschauen, wie die einzelnen Funktionen aktiviert und konfiguriert werden. Später werden wir dann ein von mir bereitgestelltes Firewall-Skript so einrichten, daß es bei jedem Start des Rechners ausgeführt wird und so die benötigten Funktionen (Routing, Masquerading und Firewall) bereitstellt.


3.1. Routing aktivieren

Um das Routing zu aktivieren, müssen wir im Allgemeinen folgende zwei Dinge tun:

Forwarding aktivieren:

Zum Aktivieren des Forwarding genügt die folgende Anweisung auf der Kommandozeile:

echo 1 >> /proc/sys/net/ipv4/ip_forward
Routing-Tabelle füllen:

Um die Routing-Tabelle müssen wir uns in unserem Fall nicht kümmern, da beim Verbindungsaufbau zum Internet automatisch eine passende Route eingetragen wird.


3.2. Masquerading aktivieren

Um das Masquerading zu aktivieren, müssen wir lediglich die folgenden Anweisungen ausführen:

modprobe ipt_MASQUERADE
iptables -t nat -A POSTROUTING -o ppp0 -s 192.168.0.0/16 -j MASQUERADE

Damit haben wir unsere erste Regel im iptables-Regelsatz erzeugt. - Diese besagt, daß alle Pakete, die zum Interface ppp0 gehen (-o ppp0) und aus dem lokalen Netzwerk kommen (-s 192.168.0.0/16) maskiert werden (-j MASQUERADE).
Die erste der beiden Anweisungen dient lediglich dazu, die für's Masquerading benötigten netfilter-Module zu laden.

Im Prinzip ist ab diesem Zeitpunkt unser Router (zumindest bedingt) einsatzfähig und wir können auf einem beliebigen Rechner im lokalen Netz die Adresse des Routers als "Default Gateway" und "DNS-Server" eintragen und lossurfen.

Mit der Zeit würden wir allerdings feststellen, daß bestimmte Internet-Dienste wie z.B. FTP oder IRC nicht korrekt funktionieren.
Dies liegt daran, daß bei einigen Protokollen bestimmte Eigenarten beachtet werden müssen. - Beispielsweise besteht die Verbindung zu einem FTP-Server nicht (wie etwa bei HTTP) aus einer einzelnen Verbindung zum Server. Vielmehr existiert hier eine ausgehende Steuerungs-Verbindung zum FTP-Server und eine eingehende Daten-Verbindung vom Server zu unserem Client.
Solche Eigenarten beherrscht Netfilter nicht von Haus aus und benötigt für solch spezielle Protokolle daher zusätzliche Module.

Bei SuSE standardmäßig verfügbar sind die Module für FTP und IRC. Weitere einfachere Protokolle beherrscht das ebenfalls vorhandene generische Modul ipt_conntrack.
Mit den folgenden Anweisungen werden die eben genannten Module geladen:

modprobe ip_conntrack
modprobe ip_conntrack_ftp
modprobe ip_conntrack_irc
modprobe ip_nat_ftp
modprobe ip_nat_irc

Ein weiteres Problem stellt sich wie in unserem Fall beim Routing über eine DSL-Verbindung:
Jede Netzwerkschnittstelle besitzt einen speziellen Parameter namens MTU - Maximum Transfer Unit. Dieser Parameter bestimmt, wie groß einzelne Datenpakete sein dürfen, damit sie an einem Stück durch das Interface und die dahinterliegende Verbindung transportiert werden können. Die MTU kann von Interface zu Interface unterschiedlich groß sein.
In einem Ethernet-Netzwerk wird meist die MTU 1500 verwendet, die DSL-Verbindung weist dagegen eine MTU von 1492 auf. So kann es vorkommen, daß über das lokale Netzwerk Datenpakete ankommen, welche 1500 Byte groß ist. Damit diese nun durch die DSL-Verbindung mit einer MTU von 1492 ins Internet geroutet werden können, müssen diese zu großen Pakete fragmentiert werden.
Und genau hier entsteht das Problem: Manche Internet-Server mögen nämlich keine fragmentierten Pakete und halten es nicht einmal für nötig, den Sender hierüber zu informieren (diese Erklärung entspringt meinem waagen Verständnis der Zusammenhänge - wenns jemand besser weiß: bitte eMail an mich schreiben).
Um dieses Problem zu vermeiden, werden auf dem Linux-Router die ins Internet gerouteten Pakete auf eine für's DSL passende MTU "umgemünzt". Das bewerkstelligen wir mit der folgenden Anweisung:

modprobe ipt_TCPMSS
iptables -A FORWARD -o ppp0 -p TCP --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu


3.3. Firewall-Regeln festlegen

Hier zu erläutern, wie Netfilter im einzelnen funktioniert und wie man eine Firewall sinnvollerweise aufbaut, würde bei weitem den Rahmen dieser Anleitung sprengen.
Daher werde ich mich im Folgenden darauf beschränken, die wichtigsten Stellen meines Firewall-Skripts zu besprechen und verweise auf die weiter untern aufgeführten Links sowie die Manual Page zu iptables (man iptables).

Im Grundzustand verwendet Netfilter drei iptables-Tabellen für Filter-Regeln: "filter", "nat" und "mangle".
Die Tabelle "nat" wird für die NAT-Regeln verwendet, also für das Masquerading (wie weiter oben bereits gezeigt) und das Port-Forwarding.
Fast alle für die eigentliche Firewall-Funktionalität wichtigen Regeln gehören in die Tabelle "filter".
Die Tabelle "mangle" nimmt Regeln für das Bearbeiten von Paketen auf und wird von uns nicht verwendet.

Wie bereits beim Masquerading gezeigt, müssen zunächst die benötigten Netfilter-Module geladen werden:

modprobe ip_tables
modprobe iptable_filter 
modprobe iptable_nat
modprobe ipt_unclean 
modprobe ipt_LOG

Vor der Deninition neuer Regeln sollte man die bereits bestehenden löschen:

iptables -t filter -F
iptables -t nat    -F

Zum Bearbeiten der iptables-Tabellen wird das Tool iptables verwendet. Die Option -t gibt den Namen der zu bearbeitenden Tabelle an (keine Angabe = "-t filter"). Die Option -F sorgt dafür, daß die entsprechende Tabelle geslöscht wird (flush).

Als nächstes wird die sog. "Default Policy" festgelegt. Diese entscheidet darüber, was mit Paketen geschieht, auf die keine der Regeln in den Tabellen passt.
Im Folgenden wird festgelegt, daß alle Pakete standardmäßig passieren dürfen, von Netfilter also nicht verworfen oder beeinflußt werden.

iptables -t filter -P INPUT       ACCEPT
iptables -t filter -P FORWARD     ACCEPT
iptables -t filter -P OUTPUT      ACCEPT
iptables -t nat    -P PREROUTING  ACCEPT
iptables -t nat    -P POSTROUTING ACCEPT

Standardmäßig enthalten die Tabellen vordefinierte sog. Chains (Ketten). - Tabelle filter enthält die Chains "INPUT", "FORWARD" und "OUTPUT". Tabelle nat nthält die Chains "PREROUTING", "POSTROUTING" und "OUTPUT".
Diese Chains werden zu den folgenden Zeitpunkten verarbeitet:

ChainZeitpunkt der Abarbeitung
PREROUTINGunmittelbar nachdem ein Paket den Rechner duch eine Netzwerk-Schnittstelle erreicht hat
INPUTbevor ein Paket an einen lokalen Port (z.B. Port 80) geliefert wird
FORWARDwährend ein Paket zwischen zwei Netzwerk-Schnittstellen vermittelt wird (Routing)
OUTPUTnachdem ein Paket von eim lokalen Port erzeugt wurde (zuerst nat, dann filter)
POSTROUTINGbevor ein Paket den Rechner durch eine Netzwerk-Schnittstelle verläßt

Um bestimmte Angriffsversuche aus dem Internet abzuwehren, definieren wir einige Regeln, die ungewöhnliche oder gefälschte Pakete verwerfen:

#-- ungewöhnliche/defekte Pakete verwerfen --
iptables -A FORWARD -m unclean -j DROP
iptables -A INPUT   -m unclean -j DROP

#-- Pakete aus I-Net mit privaten (gefälschten) Absenderadressen verwerfen --
iptables -t nat -A PREROUTING -i ppp0 -s 192.168.0.0/16 -j DROP
iptables -t nat -A PREROUTING -i ppp0 -s 10.0.0.0/8 -j DROP
iptables -t nat -A PREROUTING -i ppp0 -s 172.16.0.0/12 -j DROP
iptables -t nat -A PREROUTING -i ppp0 -s 127.0.0.0/8 -j DROP

Die Option -A (append) besagt, daß und zu welcher Kette eine Regel hinzugefügt wird. Die Optionen -i (Interface; ppp0 ist in unserem Fall das DSL-Modem) und -s (Source; hier private Adressbereiche) geben an, welche Pakete die Regel betrifft. Schließlich gibt -j (jump) an, wo die Bearbeitung des Pakets fortgesetzt wird. - DROP gibt in diesem Fall an, daß das Paket "fallen gelassen", also verworfen wird.

Jetzt bestimmen wir, welche eingehenden Verbindungen aus dem Internet erlaubt sind. Im Folgenden sorgen wir z.B. dafür, daß ein auf dem Router laufender HTTP-Server vom Internet aus erreichbar ist, der Router auf Ping-Anfragen antworten sowie selbst Ping-Antworten empfangen kann und das Port-Forwarding für's lokale Netz funktioniert.

#-- HTTP --
iptables -A INPUT -i ppp0 -p TCP --dport 80 -j ACCEPT

#-- Ping --
iptables -A INPUT -i ppp0 -p ICMP --icmp-type ping -j ACCEPT

#-- Destination-NAT für lokales Netzwerk erlauben --
iptables -A FORWARD -i ppp0 -d 192.168.0.0/16 -j ACCEPT

Das Sprungziel "ACCEPT" gibt hier an, daß die betreffenden Pakete akzeptiert, also nicht verworfen werden.

Nachdem wir alle eingehenden Verbindungen angegeben haben, die wir erlauben möchten, definieren wir im nächsten Schritt Regeln, die alle übrigen eingehenden Verbindungen aus dem Internet verbieten:

iptables -A FORWARD -i ppp0 -m state --state NEW,INVALID -j LOG
iptables -A FORWARD -i ppp0 -m state --state NEW,INVALID -j DROP
iptables -A INPUT   -i ppp0 -m state --state NEW,INVALID -j LOG
iptables -A INPUT   -i ppp0 -m state --state NEW,INVALID -j DROP

Wenn wir jetz noch das Port-Forwarding aktivieren möchten, müssen wir pro Port je noch eine Regel hinzufügen. Im Folgenden werden Regeln definiert, die einen TCP- und einen UDP-Port (wie z.B. für eMule benötigt) zu einem Rechner im lokalen Netz mit der Adresse 192.168.1.5 weiterleiten:

iptables -t nat -A PREROUTING -i ppp0 -p TCP --dport 4662 -j DNAT --to-destination 192.168.1.5
iptables -t nat -A PREROUTING -i ppp0 -p UDP --dport 5662 -j DNAT --to-destination 192.168.1.5

Wir haben hiermit einen Firewall-Regelsatz definiert, welcher nur diejenigen Verbindungen aus dem Internet zuläßt, die wir uns wünschen, und alle anderen verhindert. Dieser Regelsatz schützt den Router und das lokale Netz also vor unerwünschten Zugriffen aus dem Internet. - Dem lokalen Netz gegenüber gibt sich der Router jedoch genauso offen wie ohne eine Firewall.

Weiterführende Links zu Netfilter/Iptables, NAT, Firewall:


3.4. Firewall-Skript installieren

Als erstes laden wir das nachfolgende Tar-Archiv mit dem benötigten Firewall-Skript herunter und speichern es auf dem Linux-Rechner im Verzeichnis "/tmp".

Download: dslfirewall.tgz

Im diesem Archiv sind folgende Dateien enthalten:

dslfirewall_start.rc das Firewall-Skript zum aktivieren von Routing, Nat und der Firewall
dslfirewall_stop.rc ein Skript zum löschen aller Firewall-Regeln
dslfirewall_status.rc ein Skript zum Anzeigen der Firewall-Regeln in 'nat' und 'filter'
dslfirewall ein Init-Skript, welches z.B. das starten der Firewall während des Bootvorgangs ermöglicht

Wir öffnen eine Shell (XTerm) und entpacken die im Archiv enthaltenen Dateien mit der folgenden Anweisung (vergleiche man tar) nach "/etc/init.d":

tar -xzf /tmp/dslfirewall.tgz -C /etc/init.d

Da wir die Dateien aus einem Tar-Archiv entpackt haben, sind die ursprünglich beim Archivieren vorhandenen Datei-Rechte erhalten geblieben und die Skripte sind somit bereits ausführbar.
Sollten die Skripte jedoch zuerst z.B. unter Windows bearbeitet und erst dann auf den Linux-Rechner kopiert worden sein, so müssen die Datei-Berechtigungen noch auf "ausführbar" gesetzt werden. - Das erledigen wir mit dem folgenden Kommando (vergleiche man chmod):

chmod +x /etc/rc.d/dslfirewall*

Jetz können wir die Firewall bereits manuell starten, stoppen und uns die aktiven Firewall-Regeln anzeigen lassen:

/etc/init.d/dslfirewall startstartet die Firewall (führt das Firewall-Skript aus)
/etc/init.d/dslfirewall statuszeigt die in den Tabellen filter und nat gespeicherten Firewall-Regeln
/etc/init.d/dslfirewall restartstartet die Firewall neu (z.B. nach Veränderungen am Firewall-Skript)
/etc/init.d/dslfirewall stopschaltet die Firewall ab (löscht alle Firewall-Regeln)

Damit das Firewall-Skript bei jedem Neustart des Rechners ausgeführt wird, gehen wir unter SuSE wie folgt vor:

Ab jetz wird das Firewall-Skript bei jedem Bootvorgang ausgeführt und die benötigten Funktionen (Routing, NAT, Firewall) stehen ständig zur Verfügung.

Hat zuvor die DSL-Konfiguration geklappt, haben wir jetzt einen vollwertigen DSL-Router.

Weiterführende Links zu Init-Skripten und Bootprozeß: