Login
Newsletter
Werbung

Mo, 25. August 2003, 00:00

Firewall selbst entwickeln

OutTCP

OutTCP()
{
 for i in $*
 do
 ${IPTABLES} -A OUTPUT -j ACCEPT -o ${INTERFACE} -p tcp \
 --sport 1024: --dport $i -m state --state NEW,ESTABLISHED,RELATED
 ${IPTABLES} -A INPUT -j ACCEPT -i ${INTERFACE} -p tcp \
 --sport $i -m state --state ESTABLISHED,RELATED
 ${IPTABLES} -A FORWARD -j ACCEPT -o ${INTERFACE} -p tcp \
 -s ${LOCAL} --sport 1024: --dport $i -m state --state NEW,ESTABLISHED,RELATED
 ${IPTABLES} -A FORWARD -j ACCEPT -i ${INTERFACE} -p tcp \
 --sport $i -d ${LOCAL} -m state --state ESTABLISHED,RELATED
 done
}

Diese Funktion entspricht InTCP, nur werden hiermit Verbinundgen nach außen freigegeben, also das, was man in 99% aller Fälle benötigt. Also sind die Richtungen gegenüber InTCP gerade vertauscht. Als zusätzliche Restriktion kommt noch hinzu, daß die Portnummer des Absenders über 1023 liegen muß. Dies ist OK bei allen TCP-basierten Protokollen, die ich verwende, doch es kann Ausnahmen geben. FTP ist solch eine Ausnahme, doch auch noch aus anderen Gründen.

InUDP

InUDP()
{
 for i in $*
 do
 ${IPTABLES} -A INPUT -j ACCEPT -i ${INTERFACE} -p udp \
 --dport $i -m state --state NEW,ESTABLISHED,RELATED
 ${IPTABLES} -A OUTPUT -j ACCEPT -o ${INTERFACE} -p udp \
 --sport $i --dport 1024: -m state --state ESTABLISHED,RELATED
 ${IPTABLES} -A FORWARD -j ACCEPT -i ${INTERFACE} -p udp \
 --dport $i -m state --state NEW,ESTABLISHED,RELATED
 ${IPTABLES} -A FORWARD -j ACCEPT -o ${INTERFACE} -p udp \
 --sport $i -m state --state ESTABLISHED,RELATED
 done
}

Diese Funktion entspricht InTCP, nur ist sie für das UDP-Protokoll. Der einzige Unterschied ist in der Tat der Protokollname, und das, obwohl UDP kein verbindungsorientiertes Protokoll ist.

OutUDP

OutUDP()
{
 for i in $*
 do
 ${IPTABLES} -A OUTPUT -j ACCEPT -o ${INTERFACE} -p udp \
 --sport 1024: --dport $i -m state --state NEW,ESTABLISHED,RELATED
 ${IPTABLES} -A INPUT -j ACCEPT -i ${INTERFACE} -p udp \
 --sport $i -m state --state ESTABLISHED,RELATED
 ${IPTABLES} -A FORWARD -j ACCEPT -o ${INTERFACE} -p udp \
 -s ${LOCAL} --sport 1024: --dport $i -m state --state NEW,ESTABLISHED,RELATED
 ${IPTABLES} -A FORWARD -j ACCEPT -i ${INTERFACE} -p udp \
 --sport $i -d ${LOCAL} -m state --state ESTABLISHED,RELATED
 done
}

Diese Funktion entspricht OutTCP, nur ist sie für das UDP-Protokoll. Der einzige Unterschied ist in der Tat der Protokollname, und das, obwohl UDP kein verbindungsorientiertes Protokoll ist.

OutEqualUDP

OutEqualUDP()
{
 for i in $*
 do
 ${IPTABLES} -A OUTPUT -j ACCEPT -o ${INTERFACE} -p udp \
 --sport $i --dport $i -m state --state NEW,ESTABLISHED,RELATED
 ${IPTABLES} -A INPUT -j ACCEPT -i ${INTERFACE} -p udp \
 --sport $i --dport $i -m state --state ESTABLISHED,RELATED
 done
}

Diese Funktion läßt ausgehende Verbindungen für UDP-basierte Protokolle zu, die nicht unserer ursprünglichen Annahme folgen, daß die Portnummer des Senders über 1023 liegt. Das einzige mir bekannte Beispiel ist NTP, das Network Time Protocol. Bei dessen Implementierung sind die Portnummern von Sender und Empfänger identisch. Hier habe ich auf die FORWARD-Regeln verzichtet, d.h. weitergeleitet wird nicht. Die entsprechenden Regeln bei Bedarf hinzuzufügen, sei dem Leser als Übung überlassen.

OutFTP

OutFTP()
{
 InOutTCP ftp-data
 ${IPTABLES} -A INPUT -j ACCEPT -i ${INTERFACE} -p tcp \
 --sport ftp-data -m state --state NEW,ESTABLISHED,RELATED
}

Für aktives FTP ist die Funktion OutFTP gedacht. Aktives FTP ist bekanntlich ein Spezialfall, der bei einem Firewall einige Kopfschmerzen bereitet, weshalb oft passives FTP oder ein FTP-Proxy verwendet wird. Passives FTP habe ich hier nicht vorgesehen. Das wird im übernächsten Abschnitt beschrieben.

Die Funktion erlaubt zunächst Verbindungen in beide Richtungen auf dem ftp-data Port, welcher als Port Nr. 20 definiert ist. Durch die nachfolgende Regeln werden Pakete auf einem beliebigen Port akzeptiert, wenn die Portnummer des Senders 20 ist. Ohne Stateful Filtering würde dies sozusagen ein riesiges Scheunentor öffnen.

Für passives FTP wandelt man die Funktion OutFTP ab, wie nachfolgend angegeben. Passives FTP macht keinen Gebrauch von Port 20, sondern macht die Verbindung zwischen zwei beliebigen Ports oberhalb von 1023. Ohne Stateful Filtering wäre das eine sicherheitstechnische Katastrophe, da man alle Ports freigeben müßte. Mit den hier angegebenen Regeln sollte es aber sicherer sein als aktives FTP. Wir lassen hier explizit keine neuen Verbindungen zu, sondern nur solche, die mit einer existierenden Verbindung in Zusammenhang stehen. Die existierende Verbindung ist hier natürlich die ursprüngliche Verbindung zum FTP-Server auf Port 21.

OutFTP()
{
 ${IPTABLES} -A OUTPUT -j ACCEPT -o ${INTERFACE} -p tcp \
 --sport 1024: --dport 1024: -m state --state ESTABLISHED,RELATED
 ${IPTABLES} -A INPUT -j ACCEPT -i ${INTERFACE} -p tcp \
 --sport 1024: --dport 1024: -m state --state ESTABLISHED,RELATED
}

Installation

Zur Installation kopiert man die beiden Skripte ipfilter und ipfilter-util ins Verzeichnis der Init-Skripte. Dieses ist distributions-abhängig, oft jedoch /etc/rc.d. ipfilter muß ausführbar sein. Beide Skripte sollten root gehören. Danach sollte man die Skripte erst einmal durch Aufruf von /etc/rc.d/ipfilter start und /etc/rc.d/ipfilter stop testen. Insbesondere sollte man testen, ob alle benötigten Applikationen noch funktionieren. Dann sollte man testen, ob unerwünschte Pakete tatsächlich ausgefiltert werden. Dies funktioniert offensichtlich nur von einem Rechner im Internet, doch gibt es Webseiten, die das als Dienst anbieten.

Netfilter ist sehr modular aufgebaut. Eine ganze Reihe von Kernel-Modulen müssen geladen werden, damit alles funktioniert. Glücklicherweise sorgt das Programm iptables dafür, daß alle Module automatisch geladen werden. Nur das Modul "ip_tables" muß eventuell von Hand (d.h. in den Start-Skripten vor Aufruf unseres Skripts) geladen werden.

Funktioniert alles zufriedenstellend, kann man dafür sorgen, daß das Skript automatisch beim Systemstart ausgeführt wird. Wie das genau geschieht, ist wiederum distributions-abhängig.

Einschränkungen

Das Skript unterstützt noch nicht mehr als ein lokales Netz. Entweder erweitert man in diesem Fall die Funktionen In, Out usw., was ja simpel genug ist, oder man faßt die IP-Adressen der Netze unter einer Adresse/Maske zusammen.

Mein Filter ist sehr restriktiv. Jedes neue Protokoll muß extra freigegeben werden. Dies hat den Vorteil der absoluten Kontrolle, kann aber auch unpraktisch sein. Im Prinzip könnte man alle Protokolle in der Richtung von LAN ins Internet freigeben. Solange die Gegenrichtung gesperrt bleibt, kann dennoch kein Eindringling ins LAN. Wer die Notwendigkeit dafür sieht, kann das machen. Doch mein Ziel war maximale Sicherheit, nicht maximaler Komfort.

iptables(8) - Manual Page für iptables Version 1.2

Kommentare (Insgesamt: 0 )
Pro-Linux
Pro-Linux @Facebook
Neue Nachrichten
Werbung