Network Address Translation (NAT) / Masquerading (MASQ) für Linux (iptables)
Vorwort
Wer gerne mit jedem Programm seiner Clients ins Internet gehen würde und bereits einen Linux Server zu Hause hat, aber bloß noch nicht weiß wie; oder einfach das übliche Emule lowid Problem besitzt - für den ist das hier genau das Richtige. Dieses Tutorial erklärt wie wir ein bestimmtes Netz per MASQ ‚maskieren' und wie NAT und MASQ genau funktionieren.
Was ist Network Address Translation, MASQ und Forwarding?
Network Address Translation - zu Deutsch 'Netzwerk Adressen Übersetzung' - bezeichnet die Manipulation eines SYN Paketes bei seinem Verlauf durch die Kernel Firewall von Linux. Das Packet das die SYN Flag trägt ist das erste Packet was versucht eine Verbindung zu einem bestimmten Port herzustellen. Man kann hierbei entweder die Quelle des Paketes manipulieren oder das Ziel. Diese beiden Optionen werden daher auch als SNAT (source = Quelle) oder DNAT (destination = Ziel) bezeichnet.
Eine sehr nützliche Eigenart von NAT ist das Masquerading - zu Deutsch maskieren. Eigentlich macht es genau das selbe wie SNAT. Da es aber viele Dial-In (Einwahl) Benutzer gibt, die lediglich eine dynamische IP haben,ist SNAT hierfür nicht geeignet, da man eine bestimmte IP für das "Manipulieren" angeben muss. Dies ist also unmöglich wenn man keine statische IP hat. Für diesen Fall gibt es MASQ. Hierbei wird die Quell IP aller SYN Pakete durch die IP des eigenen Computers (unser Linux Server) ersetzt. Es ist hierdurch möglich ein Netz oder ein Client zu maskieren und so alle abgehenden SYN Pakete zu maskieren. Alle Folgepakete, ganz egal ob das SYN Paket vorher mit MASQ oder mit NAT manipuliert wurde, werden mit einer bestimmten Regel im Standard Paketfilter weitergeleitet (forewarding). Das Forwarding bezeichnet die Aktion, wenn bestimte eingehende Pakete auf vorher definierte IPs im LAN weitergeleitet werden. Beim Portmapping wird ein Paket, welches auf einem Port empfangen wurde an einen anderen Ziel-Port umgeleitet.
Was benötigen wir?
- ein bereits installiertes und eingerichtetes GNU/Linux System
- Basis wissen IP Subnetze etc.
- Ipv4 Netzwerk Protokoll Unterstützung
- Eine konfigurierte Netzwerkkarte + konfigurierten Internet Zugang
- Einen Kernel der bereits vollständige ‚iptables' Unterstützung bietet
- iptables (8) - administration tool for IPv4 packet filtering and NAT
- Root-Rechte auf dem Linux-Rechner, welcher konfiguriert werden soll
Einrichten des Servers
Zuerst booten wir unser GNU/Linux System falls das nicht bereits passiert ist. Je nachdem ob wir uns bereits in der Shell oder in X (Xfree86) befinden, müssen wir ein Terminal öffnen. Die dritte Möglichkeit ist, dass wir uns erst per SSH auf dem zutreffenden Rechner anmelden müssen. Das tun wir dann mit ssh foo@bar oder
ssh -l foo bar (wobei ‚foo' der Benutzer ist und ‚bar' der zutreffende Rechner) und geben danach unser Passwort ein. Wir werden im ganzen Tutorial lediglich mit einer Shell arbeiten. Wichtig ist, wie bereits angedeutet, dass unser Kernel den Paketfilter unterstützt. Dazu werden wir die bereits geladenen Module mit dem Befehl lsmod | grep ‚ip' abfragen - bitte als root anmelden bzw. su benutzen falls das noch nicht passiert ist. Der erste Befehl ruft lsmod auf um alle Module aufzulisten die bereits geladen sind, der zweite Befehl nach dem | (pipe) filtert alle Einträge heraus die das Muster ‚ip' enthalten.
So sieht das dann bei mir aus:
gateway:~# lsmod | grep 'ip'
ipt_MASQUERADE 1752 1 (autoclean)
ipt_REDIRECT 728 1 (autoclean)
ipt_REJECT 2968 6 (autoclean)
ipt_MIRROR 1368 2 (autoclean)
ipt_LOG 3320 4 (autoclean)
ipt_limit 824 4 (autoclean)
ipt_state 568 2 (autoclean)
ipt_TCPMSS 2296 1 (autoclean)
iptable_nat 21400 1 [ipt_MASQUERADE ipt_REDIRECT]
ip_conntrack 27232 2 [ipt_MASQUERADE ipt_REDIRECT ipt_state
iptable_nat]
iptable_filter 1644 1
ip_tables 14200 12 [ipt_MASQUERADE ipt_REDIRECT ipt_REJECT
ipt_MIRROR ipt_LOG ipt_limit ipt_state
ipt_TCPMSS iptable_nat iptable_filter]
ipv6 146900 -1
Die Module, die wir brauchen werden, sind lediglich ‚ip_tables' ‚iptable_filter' ‚ip_conntrack' und ‚ipt_MASQUERADE'. Es gibt die Möglichkeit das diese bereits in den Kernel implementiert sind. Dann werden sie nicht in dieser Liste auftauchen. Mit dem Befehl modprobe ip_tables laden wir das Modul ‚ip_tables'. Sollte dies funktionieren, verfahren wir in gleicher Weise mit den anderen Modulen. Sollten wir alle geladen haben, werden sie in der Liste auftauchen. Sollten wir Probleme beim Laden der Module bekommen versuchen wir den Befehl modprobe -l | grep ‚ipv4/netfilter' | less.
Wir erhalten eine Liste an Modulen die wir mit den Pfeiltasten runterscrollen können. Sind wir am Ende angelangt (END) können wir die Liste mit Eintippen des Buchstabens ‚q' beenden. Sollte bei dieser Liste nicht die Module dabei sein die wir benötigen gibt es nur noch zwei Möglichkeiten:
- die Module sind bereits fest in den Kernel implementiert
- sie werden überhaupt nicht unterstützt
Wir können trotzdem versuchen die benötigten Regeln zu laden. Bei den meisten unveränderten Kernel wird dies auch funktionieren.
Nun tippen wir iptables --version ein. Die Ausgabe kann z.b. so aussehen:
gateway:/mnt/storage2/ftp/gnu/deb# iptables --version
iptables v1.2.7a
Falls ‚command not found' oder ähnliches als Ausgabe erscheint, ist es eventuell möglich, dass wir das Administrationstool iptables nicht installiert haben. Folgendes können wird tun:
- Wir haben eine Distribution installiert (SuSE, Redhat, Mandrake), welche ein umfangreiches Paket an Software besitzt und können den dazugehörigen RPM Paketmanager benutzen. Dann werden wir dies tun und iptables installieren. Eine andere Quelle wo wir die *.rpm finden könnte entweder unsere Internetseite der Distribution sein oder http://www.rpmseek.com/
Was wir niemals tun sollten, ist eine rpm einer fremden Distribution und/oder Plattform zu benutzen, dies könnte unweigerlich zu Problemen führen. Wenn wir die Distribution SuSE haben und unsere Plattform ist ein PC (x86), dann sollten wir auch nur solche Pakete benutzen, die genau diese Merkmale in ihren Dateinamen aufweisen.
- Wir benutzen *.srpm/ *.src.rpm Pakete. Diese können wir mit dem Befehl rpm --build /foo/bar.src.rpm bauen lassen. Der Pfad sollte natürlich zu dem geändert werden in dem auch die Datei liegt. Das kompilieren kann je nach MHz einige Minuten bis Stunden dauern. Ich gehe aber von Minuten aus.
- Wir benutzen Debian als Distribution, dann können wir apt-cache search iptables eingeben, die Ausgabe kann ein wenig lang werden. Zusätzlich können wir | less nach dem vorherigen Befehl als Zusatz angeben, damit wir eine bessere Ausgabe bekommen. Mit apt-get install iptables installieren wir das Paket. Oder wir laden uns eine *.deb Datei von http://www.debian.org/ runter und installieren diese per dpkg -install /foo/bar.deb - Pfad variert natürlich.
- Wir benutzen Gentoo dann sollte der Befehl emerge iptables bereits genügen. Falls nicht suchen wir per emerge search iptables.
- Wir wollen keine dieser Optionen verwenden, sondern lieber selbst kompilieren:
In diesem Falle laden wir uns auf http://www.netfilter.org/ die iptables passend zu unserem Kernel herunter. Für das entpacken benutzen wir je nachdem ob *.gz oder *.bz2 tar -vzxf path_to_file für *.gz und für *.bz2 tar -vjxf path_to_file. Danach ganz wichtig README oder INSTALL in dem entpackten Verzeichnis lesen. Und die Anweisungen befolgen.
Nun sollten wir aber iptables haben. Die letzte Option dürfte sich als die schwierigste erweisen und auf die möchte ich auch nicht näher eingehen da A) dies den Rahmen dieses Tutorials sprengen würde B) hier mehrere Fehler entstehen könnten. Und es ist für mich unmöglich jeden Fehler abzusehen und für jeden eine Anleitung zu schreiben. Es gibt aber viele Dokus über das Kompilieren und auf http://www.netfilter.org/ müsste es auch eine Anleitung geben.
Danach füttern wir unsere Firewall mit folgenden regeln:
iptables -A FORWARD -t filter -i eth0 -s 192.168.1.0 -j ACCEPT
-A FORWARD fügt in der Forward Chain eine Regel am Ende hinzu
-t filter fügt die Regel der table ‚filter' hinzu, die Standartabelle für Regeln
-i eth0 wählt unsere Netzwerkkarte aus die zum internen Netz (Lan) gehört
Sollte dies eine andere Netzwerkkarte sein, geben wir anstatt eth0 die
zutreffende Netzwerkkarte an. Unsere NICs (Network Interface Card) können wir
mit dem Befehl ifconfig anzeigen lassen
-s 192.168.1.0 besagt das, dass Quell-Netz für eine erfolgreiche Verbindung
192.168.1.0 (192.168.1/24) sein muss.
0 steht für localnet. Das heißt alle Clients die in 192.168.1.x sind, werden
zugelassen. Hier kann man natürlich auch eine andere Adresse eingeben. Das heißt
z.b. bei 192.168.1.1 , daß nur der Client mit dieser IP zugelassen wird und nicht
alle IPs des gesamten Netzes.
-j ACCEPT legt die Aktion der Regel fest - in diesem Fall ACCEPT
So nun werde ich die Regel mal in verständlicher Sprache zusammenfassen.
Alle Pakete werden weitergeleitet, wenn die eingehende NIC durch die, die Pakete kommen ‚eth0' heißt und wenn die Quell Adressen in dem Netz 192.168.1.0 liegen.
So machen wir nun weiter und richten wir per iptables die Masquerading Rule (Regel) ein:
iptables -A POSTROUTING -t nat -s 192.168.1.0 -j MASQUERADE
Dieser Befehl fügt eine neue Regel in die NAT Tabelle unter den Punkt POSTROUTING chain ein. Hier wieder gilt das selbe für 192.168.1.0 wie auch oben. Als letztes geben wir zur Sicherheit noch folgenden Befehl ein:
echo "1" > /proc/sys/net/ipv4/ip_forward
Dieser Befehl aktiviert im Kernel die Verfügbarkeit der "forewarding"-Funktionalität. Es ist möglich, dass diese Unterstützung bereits aktiviert ist. Zur Sicherheit kann der Befehl jedoch ausgeführt werden. Mit dem Befehl iptables -L -t filter und iptables -L -t nat überprüfen wir unsere geladenen Regeln.
Nun sollte unser Linux Server vielmehr ein Linux Router sein.
Einrichten der Clients
So, nun kann fast nichts mehr schief gehen. Das Einrichten unter Windows sollte jedem bekannt sein, das einzige was wir tun müssen ist unseren Router als Gateway in der Netzwerkumgebung einzugeben. Natürlich muss der Client eine andere IP haben, und er muss im selben Subnetz liegen. Zur Netzwerkeinrichtung unter Windows gibt es hier einen gesonderten Beitrag
Unter Linux tippen wir route add default gw 192.168.1.254 ein. Und versuchen eine beliebige Host im Internet zu pingen: ping -c 1 www.google.de.
Dies sollte ungefähr so aussehen:
gateway:/mnt/storage2/ftp/gnu/deb# ping -c 1 www.google.de
PING www.google.com (216.239.39.99) 56(84) bytes of data.
64 bytes from 216.239.39.99: icmp_seq=1 ttl=55 time=2974 ms
--- www.google.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 2974.269/2974.269/2974.269/0.000 ms
Sollte es nicht funktionieren, müssen wir in /etc/resolv.conf unsere Nameserver überprüfen. Wir sollten die IP des Nameservers unseres Providers (t-online zb.) angeben. Alles Weitere entnehmen wir aus dem Manual, welches mit ‚man resolv.conf' aufzurufen ist. Die Nameserver von t-online können herausgefunden werden indem man auf www.denic.de geht und dort unter "Whois - Suche nach Domain Namen" einfach t-online.de angibt. Dort erscheint dann das Register und weiter unten die Nameservers. Dies sind die dazugehörigen IPs 194.25.2.132 194.25.2.131 194.25.0.125. Jede IP geben wir in unsere resolv.conf ein. Nameserver 194.25.2.132 dann neue Zeile. Und so machen wir das mit den anderen zwei auch danach nur noch abspeichern. Ich gehe nun davon aus das dies funktioniert.
Nun kommen wir zu dem Fakt, das jedes Mal, wenn wir unseren Server neustarten er alle seine Regeln im Kernel verliert. Dies kann per Startscript automatisiert werden. Wir gehen hierzu in unser Home Verzeichnis per cd . Als nächstes erstellen wir eine leere Datei mit dem Befehl touch iptables.sh Jetzt öffnen wir die Datei mit einem Editor unserer Wahl zb. vi, vim, nano, joe, pico, mcedit. Oder wir editieren diese Datei ganz einfach in einem X basierenden Editor zb. kedit.
#! /bin/sh
case "$1" in
start)
echo "Starting NAT/MASQ"
modprobe ip_tables && modprobe iptable_filter && modprobe ip_conntrack &&
modprobe ipt_MASQUERADE
echo "1" > /proc/sys/net/ipv4/ip_forward
iptables -F && iptables -X && iptables -nat -F && iptables -t nat -X
iptables -A FORWARD -t filter -s 192.168.1.0 -j ACCEPT
iptables -A POSTROUTING -t nat -s 192.168.1.0 -j MASQUERADE
;;
stop)
echo "Stopping NAT/MASQ"
iptables -F && iptables -X && iptables -t nat -F && iptables -t nat -X
;;
*)
echo "Usage: $0 {start|stop}"
exit 1
esac
Diese Zeilen geben wir in unsere leere 'iptables.sh' ein und speichern die Datei ab.
Als nächstes verschieben wir die Datei per mv iptables.sh /etc/init.d/. Nun geben wir chmod 744 /etc/init.d/iptables.sh ein. Als nächstes müssen wir nur noch einen Link zum RunlevelVerzeichnis erstellen. Mit cat /etc/inittab | grep ‚default' lässt sich herausfinden, in welchem Runlevel der Linux Router normalerweise startet. Bei mir kommt:
gateway:/etc/init.d# cat /etc/inittab | grep 'default'
# The default runlevel.
id:3:initdefault:
Die Nummer nach id: ist der Standard-Runlevel. Wechsle per cd nun in das Verzeichnis /etc/rc3.d wobei die 3 für den Runlevel steht. Ändere diese Zahl wenn Dein Standard-Runlevel ein anderer ist. Hiernach tippen wir ln -s /etc/init.d/iptables.sh /etc/rc3.d/S10iptables ein.
Jetzt sollte diese Datei bei jedem Start gestartet werden. Wir können das mit /etc/rc3.d/S10iptables start testen. So testen wir den Link und gleichzeitig auch die Datei. Hierbei sollte es keine Fehler geben. Die Nummer S10 kann man beim Linken übrigends ändern, jegliche andere Nummer bis 99 wird funktionieren - alle Dienste mit einer niedrigeren Nummer werden davor gestartet alle Dienste mit einer höheren Nummer danach.
Als Letztes werde ich noch ein paar Beispiele für NAT geben. Diese werden sich Anhand des bekannten Emule / eDonkey lowid Problems orientieren:
iptables -A FORWARD -t filter -i ppp0 -s 0/0 -p tcp --dport 4662 -j ACCEPT
iptables -A FORWARD -t filter -i ppp0 -s 0/0 -p udp --dport 4672 -j ACCEPT
Hier sollen alle Pakete mit dem Port Ziel tcp/4662 und udp/4672 die durch das Device ppp0 kommen weitergeleitet werden. ppp0 ist hier mein Point-to-Point over Ethernet (PPPoE) Device, also meine Verbindung zu meinem ADSL Provider. Bei ISDN sollte es ippp0 sein. Aber es kann theoretisch auch ein ganz anderes Gerät sein.
iptables -A PREROUTING -t nat -i ppp0 -p tcp --dport 4662 -j DNAT --to-destination 192.168.1.1:4662
iptables -A PREROUTING -t nat -i ppp0 -p udp --dport 4672 -j DNAT --to-destination 192.168.1.1:4672
Hier sind die eigentlichen DNAT Reglen die, das Ziel des SYN Paketes verändern. 192.168.1.1 ist hier mein Client zu dem sie weitergeleitet werden sollen.
Die Funktionen von iptables sind wirklich sehr komplex. Mit man iptables können alle aufgerufen werden.
Ich hoffe nun, dass der Router funktioniert. Falls Du bei einem Fehler nicht weiterkommst, mail mir einfach. Du kannst das iptables.sh Script natürlich auch noch mit mehreren Regeln erweitern bzw. ausbauen. Ports blocken usw.
|