IPTables - from scratch: Unterschied zwischen den Versionen
(→NETMAP) |
(→SNAT) |
||
Zeile 374: | Zeile 374: | ||
Hier aber ein Beispiel: | Hier aber ein Beispiel: | ||
− | + | iptables -t nat -A POSTROUTING -j SNAT -o eth0 -s 172.23.242.0/24 --to-source 192.168.242.100 | |
;Verwendete Syntax | ;Verwendete Syntax |
Version vom 2. August 2011, 09:16 Uhr
Die Verwendung von Firewalls mit iptables
Der Linux-Kernel enthält fortgeschrittene Tools für Packet-Filtering, der Prozess für die Kontrolle von Netzwerkpaketen bei ihrem Versuch einzudringen, durch und aus dem System hinaus zu dringen. Kernels vor der 2.4 Version konnten Pakete mit ipchains manipulieren, die Listen von Regeln verwendeten, die für Pakete in jeder Phase des Filterungsprozesses angewandt werden. Die Einführung des 2.4-Kernels hat iptables mit sich gebracht, die den ipchains gleichen, aber deren Wirkungsbereich und Kontrollmöglichkeiten bei der Filterung von Paketen erweitern.
iptables Allgemein
Iptables beinhaltet das englische Wort tables, was für Tabellen steht, und genauso kann man es sich auch vorstellen, denn in seinen 3 Tabellen: "filter", "nat" und "mangle" die jeweils maßgebend für eine Aktion auf ein Paket sind, sammeln sich die Ketten in denen Regeln zum Kontrollieren, Manipulieren oder Extrahieren von Paketen angegeben werden.
Somit funktioniert es wie eine Art Sammlung von Schablonen die nacheinander auf ein Paket abgebildet werden und bei einem Treffer eine bestimmte Aktion auf das Paket ausführen. Falls keine der Schablonen passen sollte wird eine Standard Aktion ausgeführt die für alle Pakete gilt die nicht auf eine Schablone passen.
Die Momentan gesetzten Regeln kann man sich mit
root@hutze:~# iptables -L
ausgeben lassen, wobei man die Ausgabe noch mit den Operanden
-n # für numerical -v # für verbose
erweitern kann.
Wenn alle Regeln leer sind sollte das so aussehen:
root@hutze:~# 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
Die Tabellen und Regeln von iptables könnte man theoretisch auch alle einzeln nacheinander in der Konsole eingeben was aber nicht ganz Sinn der Sache ist. Also bedienen wir uns für unsere Firewall einem simplen Bash-Skript.
Syntax Allgemein
Wie schon zu erwarten bedient man iptables mit dem Befehl "iptables". Folgende Dinge sind vorab zu beachten:
Die 3 Tabellen von iptables spricht man jeweils mit
iptables -t filter iptables -t nat iptables -t mangle
an.
Dabei ist es wichtig zu bemerken das jede iptables zeile ohne "-t" option von einem "-t filter" ausgeht. Was bedeutet das es in die Filter Tabelle geschrieben wird. Um in die anderen Tabellen zu schreiben braucht man "-t nat" und "-t mangle"
Nun kennt jede dieser Tabellen Anlaufstellen an denen Pakete bearbeitet werden. Diese sind: "INPUT" "OUTPUT" und "FORWARD" sowie ausschließlich für nat und mangle auch PREROUTING und POSTROUTING
- An INPUT kommen alle Pakete an die für Router mit der Firewall sind.
- An OUTPUT kommen alle Pakete an von diesem Router kommen.
- An FORWARD komme alle Pakete an die über diesen Router weiter versendet werden.
- An PREROUTING werden Pakete bearbeitet bevor sie geroutet werden.
- An POSTROUTING werden Pakete bearbeitet nachdem sie geroutet wurden.
Wenn man also Regeln aufstellen will muss man immer die Tabelle und die dazugehörige Anlaufstelle dem Kettenglied übergeben, damit der Router genau weiß was zu tun ist.
Genaueres dazu wird beim aufstellen der verschiedenen Regeln erläutert.
Positionierung der Firewall
Eine Firewall kann man unter Linux ganz einfach mit einem vi-Dokument beginnen. Damit die daraus entstehende Firewall auch ausgeführt wird müssen wir es in den entsprechenden Verzeichnissen vermerken. Das Skript selbst sollte nach /etc/init.d/ mit einem softlink mit dem prefix "S99" in /etc/rc2.d damit es beim Starten automatisch ausgeführt wird.
root@hutze:~# touch firewall root@hutze:~# mv firewall /etc/init.d root@hutze:~# ln -s /etc/init.d/firewall /etc/rc2.d/S99firewall
Der Rumpf
Zuerst wird in dem firewall-Skript ein case start - stop Block angelegt:
#!/bin/bash case $1 in start) echo "starte firewall" ;; stop) echo "stoppe firewall" ;; *) echo "usage: $0 start|stop" ;; esac
Filter Tabelle
flushing und default policy
Bevor wir unsere eigenen Regeln entwerfen, sollten wir sichergehen das sich keine alten Regeln einschleichen und zu unerwarteten Komplikationen führen. Dieses wird durch das sogenannte "flushing" erreicht, welches mit folgender Zeile geschieht:
#!/bin/bash case $1 in start) echo "starte firewall" iptables -F ;; stop) echo "stoppe firewall" iptables -F ;; esac
Ohne flushing kann es auch passieren das sich unsere Regeln bei jedem Neustart der Firewall addieren.
- Verwendete Syntax
- Der Operand -F löst das flushing aus mit dem alle Regeln in der angegebenen Tabelle ( hier "-t filter" da keine angegeben ) entfernt werden
Als nächstes definieren wir was passieren soll falls keine unserer Regeln zutreffen sollte, auch gennannt "default policy"
Dies geschieht mit folgenden Zeilen:
#!/bin/bash case $1 in start) echo "starte firewall" iptables -F iptables -P INPUT DROP iptables -P OUTPUT DROP iptables -P FORWARD DROP ;; stop) echo "stoppe firewall" iptables -F iptables -P INPUT ACCEPT iptables -P OUTPUT ACCEPT iptables -P FORWARD ACCEPT ;; esac
- Verwendete Syntax
- Wie in Syntax Allgemein angegeben muss die "default policy" auf alle 3 Anlaufstellen angewendet werden.
- Nach der Anlaufstelle geben wir an was mit den Paketen zu tun ist.
- Mit DROP lässt die gestartete Firewall alle Pakete fallen die nicht auf eine Regel passen.
- Mit ACCEPT lässt die gestoppte Firewall alle Pakete durch.
ESTABLISHED und RELATED Pakete
Ein Vorteil von iptables zu seinen Vorgängern ist die Funktion seinen Paketfilter nur auf die ersten Pakete einer Verbindung zu begrenzen und so Ressourcen zu sparen.
Dieses wird erreicht mit folgenden Zeilen
#!/bin/bash case $1 in start) echo "starte firewall" iptables -F iptables -P INPUT DROP iptables -P OUTPUT DROP iptables -P FORWARD DROP iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT ;; stop) echo "stoppe firewall" iptables -F iptables -P INPUT ACCEPT iptables -P OUTPUT ACCEPT iptables -P FORWARD ACCEPT ;; esac
- Verwendete Syntax
- Die neuen Funktionen die wir hier verwenden beinhalten:
- -m state: Das Modul von iptables das erkennt ob ein Paket eine Verbindung initiiert oder zu einer bereits errichteten Verbindung gehört.
- --state ESTABLISHED,RELATED: Der Status nach dem das Paket untersucht wird, wobei
- ESTABLISHED: Für alle Pakete steht die nicht das erste Paket einer Verbindung ist die in beide Richtungen sendet. (TCP)
- RELATED: Für alle Pakete steht die eine 2t Verbindung öffnen wollen. (FTP,ICMP)
- -j ACCEPT: Benutzt die angegebene Operation auf das Paket, hier ACCEPT.
loopback device
Nun haben wir schon ein paar Regeln aber noch keine die bisher zutreffen kann. Wenn wir diese Firewall aktivieren würden wäre unser eigener Router Nichtmal mehr in der Lage mit sich selbst zu kommunizieren. Da er dies über das sogennante "loopback device" lassen wir jetzt unsere ersten Pakete durch.
#!/bin/bash case $1 in start) echo "starte firewall" iptables -F iptables -P INPUT DROP iptables -P OUTPUT DROP iptables -P FORWARD DROP iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT iptables -A INPUT -i lo -j ACCEPT ;; stop) echo "stoppe firewall" iptables -F iptables -P INPUT ACCEPT iptables -P OUTPUT ACCEPT iptables -P FORWARD ACCEPT ;; esac
- Verwendete Syntax
- Hier geben wir nun zum ersten mal zur Anlaufstelle auch das jeweilige Interface das angelaufen wird mit an:
- Mit -o lo beschreiben wir als output also Ausgang die Schnittstelle lo was für das loopback device steht
- Genauso -i lo wobei lo hier als Eingang angegeben wird. In einem Satz:
- Alle Pakete die von unserem Router aus lo Ausgehen durchlassen
- Alle Pakete die an unserem Router an lo Ankommen durchlassen
Fernwartung
Angenommen unser Router mit der Firewall steht nicht im selben Netz wie unser üblicher Arbeitsrechner, ist es von Vorteil auch von außen auf ihn zugreifen zugreifen zu können. In unserem Beispiel ist das äußere Netz auch ein LAN.
#!/bin/bash case $1 in start) echo "starte firewall" iptables -F iptables -P INPUT DROP iptables -P OUTPUT DROP iptables -P FORWARD DROP iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -i eth0 -s 192.168.241.10 -p tcp --dport 22 -m state --state NEW -j ACCEPT ;; stop) echo "stoppe firewall" iptables -F iptables -P INPUT ACCEPT iptables -P OUTPUT ACCEPT iptables -P FORWARD ACCEPT ;; esac
- Verwendete Syntax
- -s: Passt auf die angegebene Quell IP-Adresse, hier 192.168.241.10
- -p: Passt auf ein Protokoll, hier tcp
- -dport: Passt auf Ziel Port, hier 22 (ssh)
- --state NEW: Passt auf Pakete die eine Verbindung Initiieren
DNS-Server und HTTP
Jetzt möchten wir mit unserem Router ins Internet gehen können. Dazu müssen wir 2 Dinge tun, zuerst müssen wir erlauben das er auf DNS-Server zugreifen kann.
#!/bin/bash case $1 in start) echo "starte firewall" iptables -F iptables -P INPUT DROP iptables -P OUTPUT DROP iptables -P FORWARD DROP iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -i eth0 -s 192.168.241.10 -p tcp --dport 22 -m state --state NEW -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp -d 192.168.240.21 --dport 53 -m state --state NEW -j ACCEPT iptables -A OUTPUT -o eth0 -p udp -d 192.168.240.21 --dport 53 -m state --state NEW -j ACCEPT ;; stop) echo "stoppe firewall" iptables -F iptables -P INPUT ACCEPT iptables -P OUTPUT ACCEPT iptables -P FORWARD ACCEPT ;; esac
- Verwendete Syntax
- -d: Das selbe Prinzip wie auch bei -s aber auf eine Ziel Adresse
Dann müssen wir auch noch eine Regel für HTTP aufstellen damit wir Internetseiten aufrufen dürfen
#!/bin/bash case $1 in start) echo "starte firewall" iptables -F iptables -P INPUT DROP iptables -P OUTPUT DROP iptables -P FORWARD DROP iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -i eth0 -s 192.168.241.10 -p tcp --dport 22 -m state --state NEW -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp -d 192.168.240.21 --dport 53 -m state --state NEW -j ACCEPT iptables -A OUTPUT -o eth0 -p udp -d 192.168.240.21 --dport 53 -m state --state NEW -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp --dport 80 -m state --state NEW -j ACCEPT ;; stop) echo "stoppe firewall" iptables -F iptables -P INPUT ACCEPT iptables -P OUTPUT ACCEPT iptables -P FORWARD ACCEPT ;; esac
ICMP
Jetzt wollen wir testen können ob unser Router erreichbar ist. Dazu müssen wir ICMP freischalten
#!/bin/bash case $1 in start) echo "starte firewall" iptables -F iptables -P INPUT DROP iptables -P OUTPUT DROP iptables -P FORWARD DROP iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -i eth0 -s 192.168.241.10 -p tcp --dport 22 -m state --state NEW -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp -d 192.168.240.21 --dport 53 -m state --state NEW -j ACCEPT iptables -A OUTPUT -o eth0 -p udp -d 192.168.240.21 --dport 53 -m state --state NEW -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp --dport 80 -m state --state NEW -j ACCEPT iptables -A INPUT -i eth0 -p icmp --icmp-type 8 -j ACCEPT ;; stop) echo "stoppe firewall" iptables -F iptables -P INPUT ACCEPT iptables -P OUTPUT ACCEPT iptables -P FORWARD ACCEPT ;; esac
- Verwendete Syntax
- --icmp-type 8 Beschränkt erlaubte ICMP Pakete auf typ 8 ( echo )
NAT Tabelle
NAT steht für Network Address Translation, also eine Übersetzung von Netzwerk Adressen, sei es in Namen oder auch einfach nur in andere IP-Adressen. Iptables kann diesen Job übernehmen und zwar auf verschiedene Art und Weise.
MASQUERADE
Masquerading ist wohl die simpelste Form von NAT, hiermit ersetzt der Router einfach jede Quell IP-Adresse jedes zu routenden Paketes mit seiner eigenen, sowie bei einem Antwort Paket die Ziel Adresse wieder mit der Original Quell Adresse.In iptables erreicht man diese Funktion mit folgender Zeile
#!/bin/bash case $1 in start) echo "starte firewall" iptables -F iptables -P INPUT DROP iptables -P OUTPUT DROP iptables -P FORWARD DROP iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -i eth0 -s 192.168.241.10 -p tcp --dport 22 -m state --state NEW -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp -d 192.168.240.21 --dport 53 -m state --state NEW -j ACCEPT iptables -A OUTPUT -o eth0 -p udp -d 192.168.240.21 --dport 53 -m state --state NEW -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp --dport 80 -m state --state NEW -j ACCEPT iptables -A INPUT -i eth0 -p icmp --icmp-type 8 -j ACCEPT iptables -t nat -A POSTROUTING -j MASQUERADE -o eth0 -s 172.23.242.0/24 ;; stop) echo "stoppe firewall" iptables -F iptables -P INPUT ACCEPT iptables -P OUTPUT ACCEPT iptables -P FORWARD ACCEPT ;; esac
- Verwendete Syntax
- -t nat: Hier sehen wir zum ersten mal wie man eine andere Tabelle außer Filter anspricht
- POSTROUTING: Damit der Router weiß das er den Adressen Tausch NACH dem Routing ausführen soll
- -j MASQUERADE: Eine weitere Aktion die auf ein Paket ausgeführt werden kann, hier unser NAT
- -s 172.23.242.0/24: Hier wird nicht nur eine IP-Adresse, sondern ein ganzer Netzbereich als Quelle angegeben
SNAT
SNAT ist Masquerading sehr ähnlich, der einzige Unterschied besteht darin das man sich bei SNAT die ersetzende IP-Adresse wählen kann. Da wir schon Masquerading eingebaut haben, hängen wir SNAT nicht auch noch mit in unsere Firewall.
Hier aber ein Beispiel:
iptables -t nat -A POSTROUTING -j SNAT -o eth0 -s 172.23.242.0/24 --to-source 192.168.242.100
- Verwendete Syntax
- -j SNAT: Die auszuführende Aktion, hier SNAT
- --to-source 192.168.242.100: Die Angabe zu welcher IP-Adresse ersetzt wird, hier die des Routers.
NETMAP
Eine weiter Form des NAT in iptables ist NETMAP. Statt wie bei MASQUERADE oder SNAT, ersetzt NETMAP die Quell Adresse nicht nur mit einer bestimmten Adresse, sondern bildet das gesamte Quell Netz auf ein anderes ab.
Beispiel:
iptables -t nat -A POSTROUTING -j NETMAP -o eth0 -s 172.23.242.0/24 --to 195.145.95.0/24
- Verwendete Syntax
- -j NETMAP: Aktion die auf Pakete ausgeführt wird, hier NETMAP
DNAT, port forwarding
Da das interne Netz nicht von außen angesprochen werden kann, wie es bei normalen Routern die ins Internet führen ja auch der Fall ist, bedient man sich hierfür einer Technik namens port forwarding, was bedeutet das ein Programm das über einen bestimmten Port mit dem Router kommuniziert an eine andere IP-Adresse und einen anderen Port weitergeleitet wird.
#!/bin/bash case $1 in start) echo "starte firewall" iptables -F iptables -P INPUT DROP iptables -P OUTPUT DROP iptables -P FORWARD DROP iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -i eth0 -s 192.168.241.10 -p tcp --dport 22 -m state --state NEW -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp -d 192.168.240.21 --dport 53 -m state --state NEW -j ACCEPT iptables -A OUTPUT -o eth0 -p udp -d 192.168.240.21 --dport 53 -m state --state NEW -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp --dport 80 -m state --state NEW -j ACCEPT iptables -A INPUT -i eth0 -p icmp --icmp-type 8 -j ACCEPT iptables -t nat -A POSTROUTING -j MASQUERADE -o eth0 -s 172.23.242.0/24 iptables -t nat -A PREROUTING -j DNAT -i eth0 --dport 3333 --to-dest 172.23.242.100:22 ;; stop) echo "stoppe firewall" iptables -F iptables -P INPUT ACCEPT iptables -P OUTPUT ACCEPT iptables -P FORWARD ACCEPT ;; esac
- Verwendete Syntax
- PREROUTING: Paket wird nach der Routingentscheidung geändert
- -j DNAT: Aktion die auf das Paket ausgeführt wird, hier DNAT
- --to-dest 172.23.242.100:22: IP-Adresse und Port zu denen weitergeleitet wird
- In einem Satz:
- Ändere bei allen Paketen die auf eth0 ankommen und den Port 3333 ansprechen die Ziel Adresse zu 172.23.242.100 und Port zu 22