Hier haben wir jetzt einen Server mit 2 Netzwerkschnittstellen. Die eine (ppp0) zeigt ins Internet, die andere ins lokale Netzwerk (eth0). Das lokale Netzwerk kann durch 192.168.1.0/255.255.255.0 oder 192.168.1.0/24 beschrieben werden.
iptables kennt drei Haupt-Schlangen durch die der Datenstrom geregelt wird. INPUT ist die Eingangs-Schlange, OUTPUT ist die Ausgangs-Schlange und FORWARD ist die Schlange, die sich um den Verkehr kümmert, der über den Server ins Internet und zurück geht.
Bevor wir Anfangen können, müssen wir die Kernel-Module laden, die iptables benötigt:
modprobe ip_tables
modprobe ip_conntrack
modprobe ip_conntrack_ftp
modprobe ip_conntrack_irc
Jetzt erlauben wir, dass Pakete "über den Server fließen dürfen" und erledigen noch ein paar Sicherheits- und Logging-Einstellungen.
echo 1 > /proc/sys/net/ipv4/ip_forward # ip-forwarding
echo 1 > /proc/sys/net/ipv4/ip_dynaddr # dhcp
echo 1 > /proc/sys/net/ipv4/tcp_syncookies # Enable TCP SYN Cookie Protection
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts # Enable broadcast echo Protection
echo 1 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses # Enable bad error message Protection
# Enable IP spoofing protection turn on Source Address Verification
for f in /proc/sys/net/ipv4/conf/*/rp_filter; do
echo 1 > $f
done
# Disable ICMP Redirect Acceptance
for f in /proc/sys/net/ipv4/conf/*/accept_redirects; do
echo 0 > $f
done
for f in /proc/sys/net/ipv4/conf/*/send_redirects; do
echo 0 > $f
done
# Disable Source Routed Packets
for f in /proc/sys/net/ipv4/conf/*/accept_source_route; do
echo 0 > $f
done
# Log Spoofed Packets, Source Routed Packets, Redirect Packets
if [ $logging = "enbaled" ]; then log=1; else log=0; fi
for f in /proc/sys/net/ipv4/conf/*/log_martians; do
echo $log > $f
done
Das alles kann so natürlich nicht auf die Kommandozeile, sondern muss in ein Skript.
Jetzt können wir schon anfangen. Als erstes spülen wir die Schlangen aus, damit keine alten Regeln zurückbleiben:
iptables -F INPUT
iptables -F OUTPUT
iptables -F FORWARD
Das F steht hier für Flush und bedeutet, dass die entsprechende Schlange ausgespült wird. Nun setzen wir die Standard-Vorgehensweise (default policy) der Schlangen auf DROP, da es passieren kann, dass das Script während des Ausführens hängen bleibt, und wir den Server völlig offen zurücklassen.
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
Jetzt spülen wir noch benutzerdefinierte Schlangen aus und löschen diese:
iptables -F
iptables -X
Dann können wir auch schon mit den Filter-Regeln anfangen. Die Syntax ist folgende:
iptables -A <SCHLANGE> [optionen] [-p <protocol>] [--dport <destination port>] [--sport <source port>] [-i <eingangs-interface>] [-o <ausgangs-interface>] [-s <source adresse>] [-d destination adresse] -j <ZIEL>
Was uns interessiert sind SCHLANGE und ZIEL. Als Schlange kommen INPUT, OUTPUT und FORWARD in Frage. ZIEL ist entweder ACCEPT, REJECT oder DROP. Wir nehmen DROP, da bei REJECT der anderen Seite eine Meldung geschickt wird, dass dieser Port geschlossen ist. DROP erspart uns daher Zeit und Bandbreite und macht diesen Port unsichtbar für mögliche Angreifer.
Das wichtigste ist, dass wir dem Server sein Loopback-Interface freischalten. Ohne Loopback werdet ihr nicht mehr glücklich werden, da vieles einfach nicht mehr funktionieren wird.
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
Jetzt legen wir fest, dass alle bestehenden Verbindungen weiterhin erlaubt sind:
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
Die INPUT und FORWARD Schlangen können jetzt beinahe beliebig gefüllt werden. Zugriff von innen vollständig erlauben:
iptables -A INPUT -i eth0 -s 192.168.1.0/24 -j ACCEPT
iptables -A FORWARD -i eth0 -o ppp0 -s 192.168.1.0/24 -j ACCEPT
Zugriff von außen nur über FTP, SSH und HTTP:
iptables -A INPUT -m state --state NEW,ESTABLISHED,RELATED -p tcp --dport 21 -j ACCEPT
iptables -A INPUT -m state --state NEW,ESTABLISHED,RELATED -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -m state --state NEW,ESTABLISHED,RELATED -p tcp --dport 80 -j ACCEPT
Auch passives FTP und SSH ist so möglich, da wir ja oben bestehende Verbindungen von überall her erlaubt haben. D.h. wenn sich der Port ändert, macht das nichts, da iptables das als Teil der selben Sitzung erkennen kann.
Das gleiche gilt für FORWARD von außen nach innen. Auch dies brauchen wir nicht extra zu erlauben, da niemand von außen eine neue Verbindung nach innen aufbauen soll. Gut, jetzt haben wir alles erlaubt, was wir brauchen, d.h. alles was jetzt noch bleibt ist böse - also weg damit!
iptables -A INPUT -j DROP
iptables -A FORWARD -j DROP
Unserem treuen Server verbieten wir natürlich nichts:
iptables -A OUTPUT -j ACCEPT
Damit wären wir auch schon fertig und hätten einen Paketfilter, der den Server und die Leute im Netzwerk schützt. Die Sache hat nur einen Haken: Die Leute im Netzwerk können nicht ohne den Server nach draußen. Aller Verkehr
muss jetzt über den Server laufen. Für manche mag das ok sein, wenn man zum Beispiel einen Proxyserver und Fetchmail eingerichtet hat. Aber alles weiter wäre den Benutzern im lokalen Netzwerk verweigert. Daher kommt ein neues Schlagwort ins Spiel - Network Address Translation, kurz NAT.