iptables – Debian Firewall Regeln für einen Webserver

In diesem Artikel werde ich erklären wie man die Firewall iptables auf einem Debian Linux einrichten um nur Zugriffe auf die erwarteten Dienste (HTTP, HTTPS und SSH) zu erlauben.

Seiteninhalte

Firewall Grundlagen

Iptables bestimmt wie die meisten Firewalls ob ein Packet durch darf oder nicht indem es das eingerichtete Regelwerk von oben noch unten durchgeht. Sobald die erste Regel gefunden wird, die auf das Packet passt, wird diese Angewendet. Wenn unser Regelwerk also wie folgt aussehen würde, dann würden nur SSH Verbindungen zustande kommen und keine HTTP Verbindungen:

  1. Erlaube alle SSH Verbindungen
  2. Verbiete alle Verbindungen
  3. Erlaube HTTP Verbindungen

Es ist also wichtig auf die Reihenfolge der Regeln zu achten und am Schluss sollte immer eine Regel stehen “Verbiete alle Verbindungen” (Deny All).

 IPv4 vs IPv6

Die meisten Webserver sind heute sowohl über eine IPv4 wie auch eine neue IPv6 Adresse erreichbar. Die neue Protokollversion wird jedoch oft sträflich vernachlässigt obwohl diese auf den Systemen aktiv ist. Dies ist bei Firewalls im besonderen ein Problem. Wenn wir bei dem Beispiel oben bleiben und in der Standardkonfiguration von IPtables nun via IPv6 eine HTTP Verbindung öffnen würden, so würden wir bis zu dem Webserver kommen. Da IPv6 die Zukunft ist empfehle ich daher explizit nicht einfach alle solchen Verbindungen zu verbieten sondern die Regeln auch für dieses Protokoll einzurichten. Bei iptables ist dies besonders einfach, da die meisten Befehle in beiden Versionen funktionieren und das einzige was man ändern muss ist der Programmname (von iptables zu ip6tables). In meinem Beispielen führe ich daher jeweils beide Befehlssätze (IPv4 & IPv6) auf.

System Vorbereiten

Viel ist nicht nötig um mit der Konfiguration anfangen zu können. Wir müssen im wesentlichen nur ein Packet installieren (welches häufig schon vorhanden ist):

apt-get install iptables iptables-persistent

Filterregeln erstellen

Es gibt bei iptables im wesentlichen zwei Möglichkeiten Regeln zu erstellen. Man kann diese entweder in eine Datei schreiben und diese vom System automatisch laden lassen oder man schreibt die Regeln in den (flüchtigen) Speicher von iptables und lässt iptables am Ende das File schreiben. Ich bevorzuge und verwende hier letzteren Weg, da man hier bei einem Fehler das System nur neustarten muss um einen Weitere Versuch zu erhalten.

Derzeitiges Regelwerk anschauen

Um sich das aktuell vorhandene Regelwerk anzuschauen genügt ein einfacher Befehl. Im Auslieferungszustand sollte das Ergebnis wie folgt aussehen:

IPv4

# 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

IPv6

# ip6tables -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

Regel für SSH Zugang und den Loopback Verkehr einrichten

Die erste Regel sollte immer für den Loopback Verkehr und dann für den Remotezugang verwendet werden. So wird verhindert, dass man sich zu einem späteren Zeitpunkt durch eine falsche Regel aussperrt bzw das System zu viel Zeit verbraucht um z. B. Verbindungen zum lokalen Datenbankserver aufzubauen.

IPv4

# iptables -I INPUT -p tcp --dport 22 -j ACCEPT
# iptables -I INPUT -i lo -j ACCEPT

IPv6

# ip6tables -I INPUT -p tcp --dport 22 -j ACCEPT
# ip6tables -I INPUT -i lo -j ACCEPT

Alle nicht explizit erlaubten Verbindungen ignorieren

Nachdem die SSH Regel gesetzt wurde können wir iptables scharf schalten und in der base policy einstellen, dass nur explizit erlaubte Verbindungen an unseren Server heran kommen dürfen.

IPv4

# iptables -P INPUT DROP

IPv6

# ip6tables -P INPUT DROP

Regeln für den Webserver anhängen

Für unseren Webserver erlauben wir nun noch HTTP und HTTPS Verbindungen auf den Ports 80 und 443:

IPv4

# iptables -A INPUT -p tcp --dport 80 -j ACCEPT
# iptables -A INPUT -p tcp --dport 443 -j ACCEPT

IPv6

# ip6tables -A INPUT -p tcp --dport 80 -j ACCEPT
# ip6tables -A INPUT -p tcp --dport 443 -j ACCEPT
# iptables -L -n
Chain INPUT (policy DROP)
target     prot opt source               destination
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:22
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:80
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:443
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED

Im Gegensatz zu dem Befehl den wir zum Anlegen der SSH Regel verwendet haben, haben wir hier den Parameter –I durch den Parameter –A ersetzt. Dies bewirkt, dass die Regel an das Regelwerk angehängt (append) wird.

Etablierte Verbindungen zulassen

Mit dem bestehenden Regelwerk würde der Webserver und der SSH Server wie erwartet funktionieren. Allerdings würdet Ihr vermutlich recht schnell über Fehlermeldungen z. B. von apt fallen, da hier verschiedene Verbindungen nicht durch gehen würden. Es ist daher ratsam noch folgende Regel hinzuzufügen:

IPv4

# iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

IPv6

# ip6tables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# ip6tables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

Filterregeln permanent speichern

Alle Regeln die wir bis jetzt eingerichtet haben wären nach einer Reboot wieder weg. Um diese zu speichern ist ein kurzer Befehl notwendig:

# iptables-save > /etc/iptables/rules.v4
# ip6tables-save > /etc/iptables/rules.v6

Nach einem Reboot werden die Regeln nun automatisch wieder gelesen und geladen. Zur Sicherheit sollte man das System neustarten und prüfen ob dies auch der Fall ist.

Alles in einem Script für Schreibfaule

Um das setzen der Regeln zu vereinfachen habe ich alle Befehle in eine bash Datei geworfen. Ihr müsste diese also nur auf euer System herunter laden, die Datei ausführbar machen (chmod +x [name]) und danach ausführen. Den Schritt um die Regeln zu persistieren habe ich nicht mit aufgenommen um Fehlern vorzubeugen.

Datei herunterladen