Autor: | B.Sc. Inf. Dominik Schulz <lkml@ds.gauner.org> |
---|---|
Version: | 0.1.545 |
Date: | 2008-10-19 |
Copyright: | This document is released under the terms of the GNU Free Documentation License. |
Status: | Draft |
Abstract: | Dieses Dokument beschreibt die Einrichtung einer IPv4 Firewall für einen einzelnen Host unter Verwendung von iptables. |
Inhalt
Dieses Dokument beschreibt die Einrichtung einer einfachen IPv4 Firewall für einen Rootserver mit mehreren IP-Adressen, VPN sowie eine Virtualisierungslösung für einige Dienste.
Bei der Arbeit mit IPTables kann es sehr schnell passieren, dass Sie sich selbst aussperren. Wenn Sie daher auf einem Rootserver arbeiten sollten Sie geeignete Vorsichtsmaßnahmen treffen. Sofern Sie über eine serielle Konsole oder eine Remote-KVM Lösung verfügen, sollten Sie darüber eine Verbindung zum Server offen halten während Sie IPTables Regeln testen. Falls Ihr Server nicht über eine solche Lösung verfügt und Sie nur ein Rescue-System haben, sollten Sie vor dem aktivieren der Regeln zumindest alle Dienste beenden und die Festplatten read-only mounten, damit ihr Server ggf. einen harten Restart ohne Schäden für das Dateisystem übersteht.
Der Name IPTables kommt von dem Dienstprogramm iptables aus dem Netfilter-Projekt, das diese Firewall im Linux-Kernel (seit 2.4) verwaltet. Die folgende Übersichtsgrafik zeigt die Verarbeitung von Pakete im Netfilter.
Die Funktion und Bedienung von Iptables basiert auf sogenannten Ketten (engl. Chains) die aus Regeln bestehen. Anhand von Mustern wird bestimmt ob eine Regel auf ein Paket angewandt wird. Diese Ketten werden vom Beginn an bis zum ersten Treffen sequentiell abgearbeitet. Daher ist es durchaus wichtig an welcher Stelle der Kette eine Regel steht.
Die folgenden fünf Ketten sind fest vorgegeben. Weitere Ketten lassen sich von Benutzer definieren.
Jede Regel besteht aus einem Muster (Pattern) bzw. einer Filterspezifikation sowie einem Ziel. Durch das Ziel wird bestimmt was mit dem Paket geschieht. Die wichtigsten Ziele sind:
Daneben gibt es noch weitere, spezielle, Ziele.
Die für IPTables notwendigen Kernel-Module sind in den meisten Distributionskerneln schon aktiv. Wenn man einen Kernel selbst baut sollte man die folgenden Optionen aktivieren.
Networking --> Networking options --> [*] Network packet filtering framework (Netfilter)
Im folgenden werde ich Ihnen ein Script vorstellen mit dem Sie für eine grundlegende Absicherung Ihres Servers oder Ihrer Workstation sorgen können. Natürlich kann dieses Skript beliebig erweitert und verbessert werden. Es basiert auf der Annahme, dass alle ausgehenden Verbindungen legitim sind und nur die einkommenden Verbindungen gefiltert werden sollten. Dies trifft z.B. auf einen Rootserver zu der nur bestimmte Dienste (Ports) anbieten soll. Diese Konfiguration ist für eine "echte" Firewall die vor einem Subnetzt sitzt nicht geeignet, da hier auch der ausgehende Verkehr gefiltert werden sollte.
Zunächste werden evtl. schon definierte Regel entfernt. -F löscht alle Regeln und -X die entsprechende Regelkette (Chain).
#!/bin/sh iptables -F iptables -X
Danach werden die Policies festgelegt. In diesem Fall werden hereinkommende und weitergeleitete Pakete verworfen (DROP) wenn keine andere Regel existiert.
# Set default policy iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT ACCEPT
Für die Tabelle nat (Network-Addresse-Translation) werden ebenfalls alle Regeln entfernt und Policies gesetzt.
# Remove old nat rules iptables -t nat -F iptables -t nat -X # Set default policy for nat iptables -t nat -P PREROUTING ACCEPT iptables -t nat -P POSTROUTING ACCEPT iptables -t nat -P OUTPUT ACCEPT
Das Gleiche wird noch für die Tabelle mangle wiederholt.
iptables -t mangle -F iptables -t mangle -X iptables -t mangle -P PREROUTING ACCEPT iptables -t mangle -P INPUT ACCEPT iptables -t mangle -P FORWARD ACCEPT iptables -t mangle -P OUTPUT ACCEPT iptables -t mangle -P POSTROUTING ACCEPT
Die folgenden Regeln beziehen sich zunächst auf die INPUT-Chain für hereinkommende Pakete. Alle Pakete die bereits zu einer bestehenden TCP-Verbindung gehören werden angenommen.
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
Jeglicher Traffic auf der lokalen Loopback-Schnittstelle wird ebenfalls erlaubt:
iptables -A INPUT -i lo -j ACCEPT
ICMP-Nachrichten sollte man erlauben, damit der Host auf Ping Anfragen antwortet. Da diese Host sowieso Dienste nach Außen anbietet soll, macht es keinen Sinn Pings zu unterdrücken.
iptables -A INPUT -p icmp -m icmp --icmp-type echo-reply -j ACCEPT iptables -A INPUT -p icmp -m icmp --icmp-type echo-request -j ACCEPT iptables -A INPUT -p icmp -m icmp --icmp-type destination-unreachable -j ACCEPT
Die folgenden Regeln legen fest auf welcher Adresse welche Ports erreichbar sind. Für jeden Dienst der nach außen erreichbar sein soll, müssen die entsprechenden Ports hier geöffnet werden.
Der erste Block bezieht sich auf die erste IP-Adresse dieses Hosts. Hier werden die Dienste SSH auf Port 22/tcp sowie VPN auf Port 1194/udp angeboten.
# Per IP Rules for open ports # IP: 10.0.0.1 - alias1.host.tld (Login-Host) # Open Ports: # 22/tcp - ssh (OpenSSHd) # 1194/udp - vpn (OpenVPN) iptables -A INPUT -i eth0 -p tcp -d 10.0.0.1 --dport 22 -j ACCEPT iptables -A INPUT -i eth0 -p udp -d 10.0.0.1 --dport 1194 -j ACCEPT
Dieser Block bezieht sich auf die zweite IP-Adresse. Hier ist ein Beispiel für einen Mailserver aufgeführt. Die Dienste sind der Liste zu entnehmen. Mit dem Modul multiport lassen sich mehrere (bis zu 15) Ports mit einem Befehl angeben, so dass nicht für jeden Port eine eigene Zeile notwendig wird.
# IP: 10.0.0.2 - alias2.host.tld (Mailserver) # Open Ports: # 25 - smtp (Exim4) # 110 - POP3 (Dovecot) # 143 - IMAP4 (Dovecot) # 587 - SMA (Exim4) # 993 - IMAPS (Dovecot) # 995 - POP3S (Dovecot) iptables -A INPUT -i eth0 -p tcp -d 10.0.0.2 -m multiport --dports 25,110,143,587,993,995 -j ACCEPT
Der dritte Block zeig ein Beispiel für einen Web- und FTP-Server. Hier werden jeweils ein Port für ftp, httd und https freigegeben.
# IP: 10.0.0.3 - alias3.host.tld (Web- and FTP-Server) # Open Ports: # 21 - ftp (vsftpd) # 80 - http (Apache2) # 443 - https (Apache2) iptables -A INPUT -i eth0 -p tcp -d 10.0.0.3 -m multiport --dports 21,80,443 -j ACCEPT
Der vorletzte Block ist ein einfaches Beispiel für einen Jabber-Server. Alle Angaben sind analog zu den vorherigen Beispielen.
# IP: 10.0.0.4 - alias4.host.tld (Jabber Server) # Open Ports: # 5222 - jabber (eJabberd) # 5223 - jabber (eJabberd) # 5269 - jabber (eJabberd) iptables -A INPUT -i eth0 -p tcp -d 10.0.0.4 -m multiport --dports 5222,5223,5269 -j ACCEPT
Dieser Block ist ein Beispiel für eine Adresse die keine offenen Ports anbietet. Natürlich kann man sich diesen Block auch komplett sparen, da ja keine Regeln definiert werden. Dieses Beispiel soll nur zeigen, dass in diesem Fall die default Policy greift und keine Ports offen sind.
# IP: 10.0.0.5 - alias5.host.tld (no open ports) # Open Ports: # none
Nach dem Definitionen für die einzelnen IP-Adressen folgt nun noch ein Beispiel für eine Möglichkeit virtuelle Maschinen in VMWare von Außen erreichbar zu machen. In diesem Fall wird das Netz 192.168.2.0/24 für die virtuellen Maschinen genutzt.
iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -o eth0 -j MASQUERADE iptables -A INPUT -i vmnet1 -s 192.168.2.0/24 -j ACCEPT iptables -A FORWARD -i eth0 -o vmnet1 -j ACCEPT iptables -A FORWARD -o eth0 -i vmnet1 -j ACCEPT
Diese Regeln beziehen sich ebenfalls auf die virtuellen Maschinen und sind ein Beispiel wie man klassisches NAT, wie es auch in den meisten Soho-Routern enthalten ist, mit IPTables umsetzt.
iptables -t nat -I PREROUTING -p tcp -d 10.0.0.5 -i eth0 --dport 122 -j DNAT --to 192.168.2.11:22 iptables -t nat -I PREROUTING -p udp -d 10.0.0.5 -i eth0 --dport 1155 -j DNAT --to 192.168.2.10:1155 iptables -t nat -I PREROUTING -p tcp -d 10.0.0.5 -i eth0 --dport 1155 -j DNAT --to 192.168.2.10:1155 iptables -t nat -I PREROUTING -p tcp -i tun0 --dport 3389 -j DNAT --to 192.168.2.10:3389
Wie bereits oben gesehen bietet der Server in diesem Beispiel auch einen OpenVPN-Server an. Dafür müssen natürlich auch hier die entsprechenden Tunnel-Schnittstellen freigeschaltet werden. Mit diesen Regeln werden alle Pakete von allen tun und tap Tunneln akzeptiert. Natürlich könnte man statt tun+ auch tun0 schreiben, um nur den ersten Tunnel zu erlauben.
iptables -A INPUT -i tun+ -j ACCEPT iptables -A FORWARD -i tun+ -j ACCEPT iptables -A INPUT -i tap+ -j ACCEPT iptables -A FORWARD -i tap+ -j ACCEPT
Damit die Kommunikation der VPN-Clients nicht nur mit dem OpenVPN-Server und den anderen Clients möglich ist, braucht es auch hier noch NAT Regeln:
# Track OpenVPN State iptables -A OUTPUT -m state --state NEW -o eth0 -j ACCEPT iptables -A FORWARD -m state --state NEW -o eth0 -j ACCEPT iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT # Masquerade local subnet iptables -t nat -A POSTROUTING -s 10.8.0.0/16 -o eth0 -j MASQUERADE
Alle Pakete die bis jetzt noch nicht behandelt wurden werden ordentlich zurückgewiesen. Eine andere Möglichkeit wäre hier ein stilles Drop, wie es die default Policy für alle Pakete vorsieht die in diesem Regelsatz möglicherweise nicht beachtet wurden. Allerdings sollte man nicht denken, dass man diesen Host damit verstecken könnte. Denn da der vorgelaerte Router kein ICMP Destination-unreachable sendet, kann ein Angreifen trotzdem erkennen, dass sich hier ein Host versteckt. Daher ist es besser gleich RFC-Konform die Verbindung zurück zu weisen.
iptables -A INPUT -p tcp -j REJECT --reject-with tcp-reset iptables -A INPUT -j REJECT --reject-with icmp-port-unreachable
Ganz am Schluss wird noch das connection tracking Modul für FTP geladen.
modprobe ip_conntrack_ftp
Auf Debian-basierten Systemen sollte das Skript unter /etc/network/if-pre-up.d/iptables abgelegt werden. Dies stellt sicher, dass die Firewall aktiviert wird bevor eine Schnittstelle aktiv wird (u.a. auch beim Systemstart).
Wer mit meinem Tutorial gar nicht glücklich wird, dem helfen vielleicht die folgenden Links weiter.