Ein Server ohne Firewall – kann man mal machen, aber dann ist es halt ….
Zugegeben, der Grundstock dieses Scripts stammt nicht aus meiner Feder. Ich habe es vor Jahren mal irgendwo gefunden und dann immer wieder angepasst mittlerweile schlummert bei mir auf nahezu jedem Server das folgende Script in einem «script-Verzeichnis» als iptables.sh:
#!/bin/bash
### BEGIN INIT INFO
# Provides: iptables-firewall
# Required-Start: $local_fs $network
# Required-Stop: $local_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: iptables-firewall
# Description: iptables-firewall
### END INIT INFO
#Ports: Hier eintragen welche Ports geöffnet werden sollen
SERVICES_UDP="" #freigegebene UDP-Ports
SERVICES_TCP="22 80 443" #freigegebene TCP-Ports (Hier sshd und http/https)
#Alle vorhandenen Regeln löschen
iptables -F
iptables -t nat -F
iptables -t mangle -F
iptables -X
iptables -t nat -X
iptables -t mangle -X
#Grundregeln
iptables -P OUTPUT ACCEPT
iptables -P INPUT DROP
iptables -P FORWARD DROP
#Sicherheit
iptables -N other_packets #Tabelle "other_packets" erzeugen
iptables -A other_packets -p ALL -m state --state INVALID -j DROP #Kaputte Pakete verwerfen
iptables -A other_packets -p icmp -m limit --limit 1/s -j ACCEPT #ICMP auf max. 1 Paket/Sekunde limitieren
iptables -A other_packets -p ALL -j RETURN #Tabelle "other_packets" verlassen
iptables -N service_sec #Tabelle "services_sec" erzeugen
iptables -A service_sec -p tcp --syn -m limit --limit 2/s -j ACCEPT #SYN-Flood Attacken
iptables -A service_sec -p tcp ! --syn -m state --state NEW -j DROP #TCP-SYN-Pakete ohne Status NEW verwerfen
iptables -A service_sec -p tcp --tcp-flags ALL NONE -m limit --limit 1/h -j ACCEPT #Portscanner ausschalten
iptables -A service_sec -p tcp --tcp-flags ALL ALL -m limit --limit 1/h -j ACCEPT #Portscanner ausschalten
iptables -A service_sec -p ALL -j RETURN #Tabelle "services" verlassen
iptables -N reject_packets #Tabelle "reject_packets" erzeugen
iptables -A reject_packets -p tcp -j REJECT --reject-with tcp-reset #TCP Pakete(Protokoll) zurückweisen
iptables -A reject_packets -p udp -j REJECT --reject-with icmp-port-unreachable #UDP Pakete(Protokoll) zurückweisen
iptables -A reject_packets -p icmp -j REJECT --reject-with icmp-host-unreachable #ICMP Pakete(Protokoll) zurückweisen (bei mehr als 1Paket/Sekunde [s.o.])
iptables -A reject_packets -j REJECT --reject-with icmp-proto-unreachable #Alle anderen Pakete(Protokolle) zurückweisen
iptables -A reject_packets -p ALL -j RETURN #Tabelle "reject_packets" verlassen
#Dienste
iptables -N services #Tabelle für die Dienste erzeugen
for port in $SERVICES_TCP ; do #Für jeden TCP Port (oben definiert) folgendes tun:
iptables -A services -p tcp --dport $port -j service_sec #Bei Verbindungen auf TCP Port "$port in die Tabelle "services_sec" springen
iptables -A services -p tcp --dport $port -j ACCEPT #Bei Verbindungen auf TCP Port "$port Verbindung zulassen
done
for port in $SERVICES_UDP ; do #Für jeden UDP Port (oben definiert) folgendes tun:
iptables -A services -p udp --dport $port -j service_sec #Bei Verbindungen auf UDP Port "$port" in die Tabelle "services_sec" springen
iptables -A services -p udp --dport $port -j ACCEPT #Bei Verbindungen auf UDP Port "$port Verbindung zulassen
done
iptables -A services -p ALL -j RETURN #Tabelle "services" verlassen
#INPUT
iptables -A INPUT -p ALL -i lo -j ACCEPT #Alle Pakete vom Loopback Interface zulassen
iptables -A INPUT -p ALL -m state --state ESTABLISHED,RELATED -j ACCEPT #Bereits vorhandene Verbindungen zulassen
iptables -A INPUT -p ALL -j other_packets #In die Tabelle "other_packets" springen
iptables -A INPUT -p ALL -j services #In die Tabelle "services" gehen
iptables -A INPUT -p ALL -m limit --limit 10/s -j reject_packets #Nicht erlaubte Pakete zurückweisen, max 10Pakete/Sekunde (Tabelle "reject_Packets")
iptables -A INPUT -p ALL -j DROP #Alles andere verwerfen
#OUTPUT:
iptables -A OUTPUT -p ALL -j ACCEPT
Ich habe (schon damals) versucht, es mit Kommentaren einigermassen verständlich zu machen. Versucht
Damit das Script beim Starten direkt ausgeführt wird, muss es noch nach init.d verlinkt werden (oder direkt dort abgespeichert) und dann noch als Service hinzugefügt werden. An dieser Stelle aber erstmal ein dickes
Achtung!!
Ab dem Punkt, wo die Datei verlinkt ist und als Service eingetragen ist, wird sie bei jedem Start ausgeführt. Sprich: Wenn ihr wichtige Ports darin vergesst (wie z.B. SSH bei einem remote-Server), schiesst ihr euch selbst in’s Knie und sperrt euch aus. Daher vor dem Eintrag am Besten das Script direkt ausführen und testen. Wenn ihr danach nicht mehr auf den Server kommt: Reboot und neuer Versuch.
Wenn alles eingerichtet ist, dann noch folgende beiden Befehle auf der Konsole absetzen und schon kommt die Firewall nach jedem Neustart automatisch:
ln -s /pfad/zu/iptables.sh /etc/init.d/iptables
update-rc.d iptables defaults
Danach neustarten und mittels
iptables -L
Testen, ob das Script gezogen hat. Die Ausgabe sollte wie folgt aussehen:
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
other_packets all -- anywhere anywhere
services all -- anywhere anywhere
reject_packets all -- anywhere anywhere limit: avg 10/sec burst 5
DROP all -- anywhere anywhere
Chain FORWARD (policy DROP)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere
Chain other_packets (1 references)
target prot opt source destination
DROP all -- anywhere anywhere state INVALID
ACCEPT icmp -- anywhere anywhere limit: avg 1/sec burst 5
RETURN all -- anywhere anywhere
Chain reject_packets (1 references)
target prot opt source destination
REJECT tcp -- anywhere anywhere reject-with tcp-reset
REJECT udp -- anywhere anywhere reject-with icmp-port-unreachable
REJECT icmp -- anywhere anywhere reject-with icmp-host-unreachable
REJECT all -- anywhere anywhere reject-with icmp-proto-unreachable
RETURN all -- anywhere anywhere
Chain service_sec (3 references)
target prot opt source destination
ACCEPT tcp -- anywhere anywhere tcp flags:FIN,SYN,RST,ACK/SYN limit: avg 2/sec burst 5
DROP tcp -- anywhere anywhere tcp flags:!FIN,SYN,RST,ACK/SYN state NEW
ACCEPT tcp -- anywhere anywhere tcp flags:FIN,SYN,RST,PSH,ACK,URG/NONE limit: avg 1/hour burst 5
ACCEPT tcp -- anywhere anywhere tcp flags:FIN,SYN,RST,PSH,ACK,URG/FIN,SYN,RST,PSH,ACK,URG limit: avg 1/hour burst 5
RETURN all -- anywhere anywhere
Chain services (1 references)
target prot opt source destination
service_sec tcp -- anywhere anywhere tcp dpt:ssh
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
service_sec tcp -- anywhere anywhere tcp dpt:http
ACCEPT tcp -- anywhere anywhere tcp dpt:http
service_sec tcp -- anywhere anywhere tcp dpt:https
ACCEPT tcp -- anywhere anywhere tcp dpt:https
RETURN all -- anywhere anywhere
Noch ein kleiner Hinweis: iptables arbeitet alles nacheinander ab. Wenn also oben erstmal alles verboten wird und dann nach und nach dinge wieder erlaubt werden, ist das so in Ordnung.
Weitere nützliche Informationen zu IPtables findet ihr hier.