Hinweis: Dieses Script stammt aus 2009 und nutzt iptables auf einem Debian mit Kernel 2.4. Die Konzepte sind zeitlos, aber die Umsetzung ist veraltet. Heute nimmt man nftables statt iptables. Trotzdem: Wer versteht was hier passiert, versteht auch nftables.

Das Setup

Dedizierte Firewall-Maschine mit drei Netzwerkkarten. Ein Interface zum Internet (PPPoE), zwei für interne Netze mit unterschiedlichen Berechtigungen. Default-Policy auf allen Chains: DROP. Alles was nicht explizit erlaubt ist, wird verworfen.

Grundstruktur

#!/bin/bash

# Module laden
modprobe ip_tables
modprobe ip_conntrack
modprobe ip_conntrack_ftp
modprobe ip_nat_ftp

# Tabellen leeren
iptables -F
iptables -t nat -F
iptables -t mangle -F
iptables -X
iptables -t nat -X
iptables -t mangle -X

# Default: Alles verwerfen
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

Custom Chains für Logging

Eigene Chains für sauberes Logging. Jedes verworfene Paket wird mit Prefix geloggt bevor es gedroppt wird:

# MY_REJECT: Protokollieren und zurückweisen
iptables -N MY_REJECT
iptables -A MY_REJECT -p tcp -m limit --limit 7200/h -j LOG --log-prefix "REJECT TCP "
iptables -A MY_REJECT -p tcp -j REJECT --reject-with tcp-reset
iptables -A MY_REJECT -p udp -m limit --limit 7200/h -j LOG --log-prefix "REJECT UDP "
iptables -A MY_REJECT -p udp -j REJECT --reject-with icmp-port-unreachable

# MY_DROP: Portscans stillschweigend verwerfen
iptables -N MY_DROP
iptables -A MY_DROP -m limit --limit 7200/h -j LOG --log-prefix "PORTSCAN DROP "
iptables -A MY_DROP -j DROP

Stealth Scan Detection

Ungültige TCP-Flag-Kombinationen erkennen und verwerfen. Kein normaler Client setzt SYN+FIN gleichzeitig oder schickt ein Paket ohne Flags:

# Keine Flags gesetzt
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j MY_DROP
# SYN und FIN gleichzeitig
iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j MY_DROP
# SYN und RST gleichzeitig
iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j MY_DROP
# FIN ohne ACK
iptables -A INPUT -p tcp --tcp-flags ACK,FIN FIN -j MY_DROP

Connection Tracking und NAT

Stateful Firewall: Bestehende und zugehörige Verbindungen durchlassen, neue nur aus dem internen Netz erlauben. NAT per MASQUERADE für den Internetzugang:

# Loopback erlauben
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# Ausgehend: Alles erlauben
iptables -A OUTPUT -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

# Forwarding: Neue Verbindungen nur von innen
iptables -A FORWARD -i ! ppp0 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# NAT für interne Netze
iptables -t nat -A POSTROUTING -o ppp0 -s 192.168.0.0/24 -j MASQUERADE

Traffic Shaping mit tc

Mit tc (traffic control) und iptables -t mangle lässt sich die Bandbreite pro Client oder Netz begrenzen. iptables markiert die Pakete, tc ordnet sie in Queues ein:

# HTB Queueing Discipline auf dem internen Interface
tc qdisc add dev eth2 root handle 1:0 htb default 10
tc class add dev eth2 parent 1:0 classid 1:1 htb rate 150kbit ceil 250kbit
tc filter add dev eth2 parent 1: prio 0 protocol ip handle 1 fw flowid 1:1

# Pakete per iptables markieren
iptables -t mangle -A FORWARD -s 192.168.100.0/24 -j MARK --set-mark 1

Kernel-Hardening

Am Ende des Scripts werden Kernel-Parameter gesetzt die über die Firewall hinausgehen:

# SYN-Cookies gegen SYN-Flood
echo 1 > /proc/sys/net/ipv4/tcp_syncookies

# Source-Routing deaktivieren
for i in /proc/sys/net/ipv4/conf/*; do echo 0 > $i/accept_source_route; done

# Redirects ignorieren
for i in /proc/sys/net/ipv4/conf/*; do echo 0 > $i/accept_redirects; done

# Martian-Pakete loggen
for i in /proc/sys/net/ipv4/conf/*; do echo 1 > $i/log_martians; done

# ICMP-Ping ignorieren
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all

# TCP-FIN-Timeout gegen DoS
echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout

Die Konzepte aus diesem Script gelten unverändert: Default DROP, Stateful Tracking, Custom Chains für Logging, Stealth Scan Detection, Kernel-Hardening. Nur die Syntax hat sich geändert. Wer heute eine Linux-Firewall baut, nimmt nft statt iptables und erspart sich die Modprobe-Zeilen. Für IPv6 braucht man eine eigene Regelkette, damals mit ip6tables, heute in nftables integriert.

Fragen? Einfach melden.