13. Mai 2015

Raspberry PI als Firewall - Den Geheimnissen von iptables auf der Spur

In meinen Augen gehört die Firewall zu den Kategorien "easy to learn, hard to master".

Oder mit anderen Worten: Das Grundprinzip ist eigentlich sehr schnell verstanden. Aber die perfekte Firewall einzurichten, ist eine Wissenschaft für sich.

Jede Firewall basiert auf dem gleichen System: Wenn ein Paket nicht in das Muster passt, wird es aussortiert.

Dabei gibt es zwei verschiedene Modelle: Whitelist und Blacklist.

Wie funktioniert eine Firewall?

Stell dir mal vor, du möchtest in die Disko gehen um mit deinen Kumpels zu feiern. Vor der Tür wirst du von einem freundlichen Türsteher (nennen wir ihn mal Hakan) zunächst abgecheckt.

Analogie zur Netzwerktechnik:

  • Du bist das Paket
  • Hakan ist die Firewall
  • Die Disko ist das Netzwerk

Blacklist Firewall

Der Disko-Besitzer hat was gegen Turnschuhe und sagt Hakan, dass er alle Leute mit Turnschuhen nicht reinlassen soll.

Wenn du jetzt am Abend Turnschuhe anhast, wirst du direkt an der Tür abgewiesen und wirst nach Hause geschickt!

Dieses Verfahren ist eigentlich so das Standardverhalten bei den meisten Firewalls.

Whitelist Firewall

Der obere Disko-Besitzer plant eine Halloween Party und sagt Hakan, dass er nur verkleidete Leute reinlassen darf (auch mit Turnschuhen wenn es zur Verkleidung passt).

Diesmal bist du schlauer und ziehst dir ein schönes Hemd und ein paar Lackschuhe an.

Trotzdem wirst du nach Hause geschickt da du nicht verkleidet bist und damint damit nicht ins Muster passt.

Die Whitelist Firewall ist etwas schwieriger zu konfigurieren. Man muss von vornherein gut planen und gut Überlegen, welche Dienste erlaubt werden.

Hat man sich aber einmal die Mühe gemacht und alles korrekt eingerichtet ist diese Konfiguration in Punkto Sicherheit der Blacklist weit überlegen.

Warum ist eine Firewall wichtig?

Gäbe es in unserem Netzwerk kein Hakan, ähm keine Firewall, könnten Hinz und Kunz auf unser Netzwerk zugreifen und Daten hin und her schicken.

Auch Software (oder ganze Betriebssysteme), die dich ausspioniert (angeblich um die Software besser zu machen) haben durch solche Paketfilter keine Chance, da die Pakete von vornherein abgewiesen werden.

Anderseits ist es auch keine 100%-tige Sicherheit gegenüber Trojanern etc.

Sehr viele Firewalls haben ein aktiven Port 80 (HTTP). Deine auch. Viele Anwendungen nutzen das aus und versenden über Port 80 irgendwelche Pakete. Daher solltest du dich nicht nur auf deine Firewall verlassen, sondern auch andere Sicherheitsvorkehrungen treffen

iptables – die hauseigene Linux Firewall

Die Firewall werden wir mittels iptables einrichten.

Bevor es jedoch praktisch wird, möchte ich noch auf die Funktionsweise von iptables eingehen.

Die folgende Abbildung soll den Ablauf eines Pakets veranschaulichen.

iptables firewall Ketten

Der eigentliche Aufbau besteht aus Tabellen, Ketten und Regeln.

Regeln

Wie der Name schon sagt, sagt eine Regel aus, was mit einem Paket passieren soll.

Ich habe da noch eine schöne Grafik vorbereitet:

firewall iptables regeln

Also eigentlich nur eine Ansammlung von irgendwelchen Bedingungen.

Die Entscheidung, was mit einem Paket passieren soll, bezeichnet man auch als Policy.

Das sind die am meisten verwendeten Policies:

  • ACCEPT: alles gut, das Paket darf weiter
  • REJECT: Paket wird abgewiesen. Der Absender bekommt eine Rückmeldung
  • LOG: Schreibt ein Eintrag in das syslog (und geht zur nächsten Regel weiter).
  • DROP: Das Paket wird ignoriert. Der Absender wird nicht Benachrichtigt.
  • REDIRECT: Das Paket wird modifiziert und an eine andere IP oder anderen Port weitergeleitet
  • MASQUERADE: Bei einem maskierten Paket wird die IP abgeändert indem die Quell-Adresse auf die eigene IP-Adresse geändert wird.

Ketten

Ketten sind eine Ansammlung von Regeln. Es kann aber auch sein, dass keine Regel in einer Kette vorhanden ist.

Ein Paket durchläuft also alle Regeln einer Kette solange bis eine Bedingung zutrifft. Wenn es soweit ist, wird dann die Ausführung der Kette abgebrochen. Ansonsten wird die Standard Policy der Kette angewendet.

Diese Standardketten gibt es:

  • PREROUTING: Alle frischen Pakete
  • FORWARD: Alle Pakete, die zwischen den Netzwerkschnittstellen hin und her gereicht werden
  • INPUT: Alle eingehenden Pakete
  • OUTPUT: Alle herausgehende Pakete
  • POSTROUTING: Alle verarbeiteten Pakete

Tabellen

Last, but not least gibt es noch die Tabellen. iptables kennt dabei drei Tabellen:

  • mangle: Erlaubt das Verändern der Pakete. Beinhaltet alle Ketten
  • nat: steht führ Network Adress Translation und wird verwendet um interne und externe IP-Adressen zu übersetzen. Beinhaltet die PREROUTING, OUTPUT und POSTROUTING Ketten.
  • filter: Der Paketfilter beinhaltet die FORWARD, INPUT und OUTPUT Ketten wird dafür verwendet um Pakete abzuweisen oder durchzulassen.

Von der Theorie, in die Praxis

Wenn du bis hierhin alles durchgelesen hast: Herzlichen Glückwunsch, du kennst jetzt die Theorie von iptables! Wenn nicht, schreibe bitte den Grund in die Kommentare 😃

Best Practice – Firewall im Autostart ausführen

iptables ist ein Konsolenbefehl und lässt sich eigentlich ganz normal ausführen. Allerdings finde ich unpraktisch. Wenn du den Rechner neu startest, ist die ganze Konfiguration pfutsch.

Ich habe mir angewöhnt für die komplette Konfiguration ein Script zu erstellen und es beim Systemstart auszuführen.

$ nano /etc/init.d/firewall

Diese Datei wird zunächst mit dem folgenden Inhalt erstellt:

#!/bin/sh
case "$1" in
start)
;;
stop)
;;
esac
exit 0
view raw firewall_1 hosted with ❤ by GitHub

Damit die Datei ausgeführt werden kann, musst du ihr noch die passenden Rechte verpassen:

$ chmod +x /etc/init.d/firewall

Der nächste Befehl sorgt dafür, dass die das Script beim nächsten Start mit ausgeführt wird.

$ update-rc.d firewall defaults
Zwar kannst du es auch sofort ausführen, jedoch würde ich bis zum Ende der Konfiguration damit warten. Mir ist es passiert, dass ich aus versehen den SSH Port gesperrt habe und mich nicht mehr auf dem PI einloggen konnte. Ein Reset hat die Einstellungen dann verworfen.

Best Practice – Whitelist Firewall

Ich habe bereits weiter oben den den Unterschied zwischen einer Black- und Whitelist Firewall erklärt.

Ich verwende immer eine Whitelist Firewall, da ich gerne die Kontrolle über alle Pakete haben möchte.

Best Practice – Drop vs. Reject

Ich habe viele Firewalls gesehen, die alle Pakete verwerfen. Das ist zwar legitim, aber in meinen Augen nicht die beste Wahl.

Die Diskussion um das Thema ist wohl schon so alt wie es die Firewall gibt.

Meine Meinung dazu: Alles was aus dem LAN kommt, oder nach draußen möchte, sollte abgewiesen werden. Alles was ins Netzwerk möchte, sollte verworfen werden.

Warum? Ganz einfach!

Ich möchte schnell benachrichtigt werden, wenn ein Port blockiert wird und nicht unnötig lange warten. Wenn ich beispielsweise Port 80 sperre, vergehen bis zu 10 Sekunden bis der Browser eine Rückmeldung gibt. Bei 'Reject' kommt die Antwort sofort.

Ich möchte aber nicht unbedingt von außen direkt sichtbar sein. Ist zwar auch nicht so schlimm, aber wozu unnötige Sicherheitslücken ins Haus holen 😃

Requirements Engineering - firewall

Heißt nichts anderes als: Anforderungsanalyse.

Vor dem Aufbau der Firewall, muss ich zunächst ganz genau wissen, was ich erreichen möchte.

Ich gebe mich mit relativ wenig zufrieden und beschränke mich auf folgende Punkte:

  • Als Netzwerkadministrator möchte ich die Pakete kennen, die in mein Netzwerk reingehen.
  • Als Netzwerkadministrator möchte ich abgewiesene Pakete kennen um ggf. darauf reagieren zu können.
  • Als Benutzer möchte ich in Internet surfen können und meine tägliche Arbeit erledigen können (Email, Web, etc.)

Schritt für Schritt zum perfekten Script

Vorhandene Regeln löschen

Bevor du mit der Konfiguration loslegst, musst du sicherstellen, dass alle Ketten leer sind:

do_flush() {
iptables -F
iptables -F -t mangle
iptables -F -t nat
iptables -F INPUT
iptables -F FORWARD
iptables -F OUTPUT
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
iptables -X ROUTER
}
view raw firewall_flush hosted with ❤ by GitHub

MASQUERADE – IP Adressen maskieren

enable_masquerade() {
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
}
view raw firewall_mask hosted with ❤ by GitHub

INPUT – Paketfilter am Raspberry

Als nächstes werden alle benötigten Ports am Router geöffnet.

Der wohl wichtigste Port ist 22 (SSH). Ohne diesen Port, können wir uns nicht mehr auf den Raspberry aufschalten.

Da ich nicht jedem den Zugriff gewähren möchte, schalte ich es nur für eth1 frei. Also in meinem Fall für alle, die direkt an meinem Router hängen. Endgeräte, die per WLAN ins Netz kommen, werden abgewiesen.

pass_ports() {
iptables -A INPUT -i eth1 -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p icmp -j ACCEPT
iptables -A INPUT -p tcp -m multiport --dport 139,445 -j ACCEPT
iptables -A INPUT -p udp -m multiport --dport 137,138 -j ACCEPT
iptables -A INPUT -p tcp -m multiport --dport 80,443 -j ACCEPT
iptables -A INPUT -p tcp --dport 68 -j ACCEPT
iptables -A INPUT -j LOG --log-prefix "[FW] DENY-RPI-ACCESS "
iptables -A INPUT -j REJECT --reject-with icmp-host-prohibited
iptables -P INPUT DROP
}
view raw firewall_input hosted with ❤ by GitHub

OUTPUT – Bleibst du wohl hier?

Pakete, die aus dem internen Netzwerk kommen, werden auch ordnungsgemäß beantwortet.

Alles andere kommt bei uns nichts ins Haus. Warum auch? 😃

enable_intranet() {
iptables -A OUTPUT -o eth1 -j ACCEPT
iptables -A OUTPUT -o wlan0 -j ACCEPT
iptables -A OUTPUT -j LOG --log-prefix "[FW] WARNING-CALL-HOME "
iptables -A OUTPUT -j REJECT
iptables -P OUTPUT DROP
}
view raw firewall_output hosted with ❤ by GitHub

FORWARD – Intranet Paketfilter

Das ist eigentlich das Kernstück des ganzen Artikels.

Hier öffne ich also sukzessiv alle benötigten Ports frei. Aber auch nur die, die wirklich benötigt werden.

enable_routing() {
# HTTP(s)
iptables -A FORWARD -p tcp -m multiport --dport 80,443 -j ACCEPT
iptables -A FORWARD -p udp -m multiport --dport 80,443 -j ACCEPT
# POP3(s)
iptables -A FORWARD -p tcp -m multiport --dport 110,995 -j ACCEPT
iptables -A FORWARD -p udp -m multiport --dport 110,995 -j ACCEPT
# IMAP(s)
iptables -A FORWARD -p tcp -m multiport --dport 143,993 -j ACCEPT
iptables -A FORWARD -p udp -m multiport --dport 143,993 -j ACCEPT
# SMTP
iptables -A FORWARD -p tcp --dport 25 -j ACCEPT
iptables -A FORWARD -p udp --dport 25 -j ACCEPT
# DNS
iptables -A FORWARD -p tcp --dport 53 -j ACCEPT
iptables -A FORWARD -p udp --dport 53 -j ACCEPT
# NTP (Network Time Protocol)
iptables -A FORWARD -p udp --dport 123 -j ACCEPT
# Google Play (für Androids und so)
iptables -A FORWARD -p tcp --dport 9000 -j ACCEPT
iptables -A FORWARD -p tcp --dport 9300 -j ACCEPT
iptables -A FORWARD -p tcp --dport 9339 -j ACCEPT
iptables -A FORWARD -p tcp --dport 4234 -j ACCEPT
iptables -A FORWARD -p tcp --dport 9050 -j ACCEPT
# WhatsApp
iptables -A FORWARD -p tcp --dport 5222 -j ACCEPT
iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -j LOG --log-prefix "[FW-F] LAN-ACCESS "
iptables -A FORWARD -j REJECT --reject-with icmp-host-prohibited
}
view raw firewall_forward hosted with ❤ by GitHub

Dem aufmerksamen Leser wird auffallen, dass ich beispielsweise kein FTP erlaube.

Das mag zwar einige wundern, aber Port 21 wird tatsächlich für einige Trojaner etc. verwendet. Dieses Sicherheitsrisiko möchte ich nicht eingehen.

Falls ich ein neuen Port freischalten muss, schaue mich mir den Port ganz genau an ob dieser Port irgendwelche Gefahren bergen könnte und entscheide dann individuell.

Dazu verwende ich die Tools von adminsub.net oder speedguide.net.

Put it all together

Dieser Anglizismus mal wieder 😃

So, nachdem du die Funktionen zum Script hinzugefügt hast, kannst du die dann in deine Ausführungsroutine integrieren.

case "$1" in
start)
do_flush
pass_ports
enable_intranet
enable_masquerade
enable_routing
echo "firewall started";
;;
stop)
do_flush
echo "firewall stopped";
;;
esac
view raw firewall_2 hosted with ❤ by GitHub

Die Firewall kannst du jetzt also mit dem 'start' Parameter starten und mit 'stop' komplett abschalten.

/etc/init.d/firewall start

Troubleshooting

Es kann schnell passieren, dass ein Port gesperrt wurde, der eigentlich nicht gesperrt werden sollte.

Wenn es nicht gerade Port 22 ist, kann man das schnell beheben:

Mit diesem Befehl listest du alle aktuellen Regeln und Ketten auf:

iptables -L -v

Wenn du deine Firewall so konfiguriert hast, wie oben beschrieben, wird relativ viel geloggt.

Schau als erstes in das log rein und überprüfe welchen Port die Applikation haben könnte.

tail /var/log/syslog

Schaue anschließend ob es sich um ein potentiell gefährlichen Port handelt. Wäge immer den Nutzen und das Risiko ab bevor du ein Port freischaltest.

Weiterführende Links

Zu guter Letzt möchte ich noch ein paar Links aufführen, die mir während meiner Recherche geholfen haben 😃

http://www.selflinux.org/selflinux/html/iptables.html

http://ipset.netfilter.org/iptables.man.html

Und wenn du nicht alle Schnipsel per Hand zusammenfügen möchtest, habe ich die komplette Datei noch einmal auf github hochgeladen 😃

github | jupiter | firewall

Fazit

In meinen Augen ist das Thema Firewall am ganzen Projekt am kompliziertesten.

Es gibt viele Konfigurationsmöglichkeiten. Gerade deswegen kann man auch sehr viel falsch machen.

Manchmal vergisst man ein Port zu öffnen und dann funktioniert das halbe Netzwerk nicht mehr. Natürlich sucht man den Fehler zunächst bei genau diese Applikation und nicht bei der Firewall.

Nicht umsonst gibt es ganze Unternehmen, die sich einzig und allein mit dem Thema Firewall beschäftigen und dafür bezahlte Software auf die Beine stellen.

So geht es weiter

Im nächsten Artikel wird es wieder etwas leichter. Da schauen wir uns dann ein Proxy Server an 😃

Wenn dir das gefallen hat, wirst du diese Artikel lieben!

Die neuesten Artikel, die du gelesen haben musst!

teilen

Noch mehr privux?

Verpasse keine spannende Beiträge & Tutorials mehr!

Jetzt kostenlosen Newsletter abonieren!

Jetzt newsletter abonieren