Um ein komplettes Firewallscript zu schreiben fehlt uns hier der benötigte Rahmen, wir können aber die Regeln für die wichtigsten Dienste hier formulieren und alles weitere kann dann – sofern erwünscht – hinzugefügt werden.

Wir erstellen die Regeln am Besten in einem Shellscript, das wir dann jedesmal einfach aufrufen können, dann stellt sich gar nicht erst die Frage, wie einzelne Regeln gespeichert werden.

Das Script beginnt üblicherweise mit einem ganzen Satz von Variablendefinitionen, damit wir uns später leichter mit der Formulierung der Regeln tun:

  #!/bin/bash

  EXTERN_INTERFACE=eth0    # Unsere Netzschnittstelle
  LOOP_INTERFACE=lo        # Das Loopback Interface
  IPADDR=10.230.1.100      # Unsere IP-Adresse
  ANYWHERE=any/0           # Jede Adresse im Netz
  MYNET=10.230.1.0/24      # Unsere Netzadresse
  UNPRIVPORTS=1024:65535   # Die unprivilegierten Ports

Als nächstes löschen wir alle bestehenden Regeln. Falls wir das Script einmal mehrfach hintereinander starten kommt es so nicht zu Doppelregeln. Dadurch, dass wir keine Regelkette angeben, werden alle bestehenden Regelketten gelöscht.

  ipchains -F

Alle Ketten sind jetzt leer. Allerdings haben wir noch nicht die Grund-Policies gelöscht bzw. verändert. Sie bleiben auch nach dem Löschen vorhanden. Also stellen wir jetzt diese Policies ein, für jede Kette extra. Dazu stellt ipchains den Parameter -P (nicht verwechseln mit -p) zur Verfügung. Wir setzen alle drei Regelketten auf die Grundeinstellung DENY, also ist alles verboten, was nicht explizit erlaubt ist.

  ipchains -P input    DENY
  ipchains -P output   DENY
  ipchains -P forward  DENY

Ab hier ist jetzt also alles verboten. Es existieren keinerlei Regeln mehr, die Grundeinstellung ist DENY. Wir können uns ab diesem Moment nicht einmal mehr selbst anpingen.

Damit das Loopback-Interface wieder funktioniert erlauben wir in den nächsten beiden Regeln grundsätzlich alles auf diesem Interface.

  ipchains -A input  -i $LOOP_INTERFACE -j ACCEPT
  ipchains -A output -i $LOOP_INTERFACE -j ACCEPT

Jetzt erlauben wir alle ICMP-Pakete auf der Netzschnittstelle. Wir könnten zwar hier verschiedene Einschränkungen machen, aber das ist langwierig und kompliziert. Viele Programme benötigen ICMP-Nachrichten um z.B. eine Nichtverfügbarkeit oder ähnliche Fehlermeldungen zu übertragen.

  ipchains -A input -i $EXTERN_INTERFACE -p icmp -j ACCEPT
  ipchains -A output -i $EXTERN_INTERFACE -p icmp -j ACCEPT

Jetzt funktioniert wenigstens ein Ping schonmal wieder. Allerdings nur mit numerischen IP-Adressen. Denn wir haben noch keinerlei Zugriff auf Nameserver. DNS funktioniert in den meisten Fällen über UDP auf Port 53. Wir können jetzt die erste vollständige Regel anwenden, indem wir den Zugriff auf Nameserver freischalten. Da uns über Port 53 wenig Gefahr droht geben wir ihn für alle frei, nicht nur für einen bestimmten Nameserver. Falls das nicht gewünscht wöre, müsste der Eintrag $ANYWHERE durch die IP-Adresse des Nameservers ersetzt werden.

  ipchains -A output -i $EXTERN_INTERFACE -p udp\
           -s $IPADDR $UNPRIVPORTS \
           -d $ANYWHERE 53 -j ACCEPT

  ipchains -A input -i $EXTERN_INTERFACE -p udp\
           -s $ANYWHERE 53 \
           -d $IPADDR $UNPRIVPORTS -j ACCEPT

Jetzt können wir anfangen, die wichtigen Dienste einzeln zu erlauben. Zunächst einmal HTTP (TCP Port 80) und HTTP mit SSL (TCP Port 443) Wir erlauben nur Antworten eines Servers an uns.

  ipchains -A output -i $EXTERN_INTERFACE -p tcp\
           -s $IPADDR $UNPRIVPORTS \
           -d $ANYWHERE 80 -j ACCEPT

  ipchains -A input -i $EXTERN_INTERFACE -p tcp ! -y\
           -s $ANYWHERE 80 \
           -d $IPADDR $UNPRIVPORTS -j ACCEPT

  ipchains -A output -i $EXTERN_INTERFACE -p tcp\
           -s $IPADDR $UNPRIVPORTS \
           -d $ANYWHERE 443 -j ACCEPT

  ipchains -A input -i $EXTERN_INTERFACE -p tcp ! -y\
           -s $ANYWHERE 443 \
           -d $IPADDR $UNPRIVPORTS -j ACCEPT

Sind wir selbst auch Webserver, dann müssen wir auch Zugriffe fremder Clients auf unseren Server zulassen und unsere Antwortpakete an diese Clients. Das könnte mit der Einschränkung passieren, dass wir nur Clients aus dem lokalen Netz ($MYNET) akzeptieren.

  ipchains -A input -i $EXTERN_INTERFACE -p tcp\
           -s $MYNET $UNPRIVPORTS \
           -d $IPADDR 80 -j ACCEPT

  ipchains -A output -i $EXTERN_INTERFACE -p tcp ! -y\
           -s $IPADDR 80 \
           -d $MYNET $UNPRIVPORTS -j ACCEPT

Schwieriger wird es mit FTP. Hier existieren zwei Portnummern (20 und 21), eine für den FTP-Befehlskanal und eine für den Datenkanal. Zudem existieren zwei Modi, der sogenannte aktive Modus und der passive Modus, der von den meisten Browsern verwendet wird. Der Unterschied liegt darin, dass der passive Modus beim Datenkanalaufbau auf beiden Ports (Sender und Empfänger) unprivilegierte Portnummern verwendet. Wir brauchen also 6 Regeln um als Client an einen FTP Server zu kommen:

  • Anfrage des lokalen Clients beim fremden Server
  • Antwort des fremden Servers
  • Datenkanalaufbau durch den fremden Server (aktiv)
  • Antwort auf Datenkanalaufbau durch den lokalen Client (aktiv)
  • Datenkanalaufbau des Clients zum fremden Server (passiv)
  • Antwort des fremden Servers auf Datenkanalaufbau (passiv)

In der oben genannten Reihenfolge sieht das also folgendermaßen aus:

  ipchains -A output -i $EXTERN_INTERFACE -p tcp \
           -s $IPADDR $UNPRIVPORTS\
           -d $ANYWHERE 21 -j ACCEPT

  ipchains -A input -i $EXTERN_INTERFACE -p tcp ! -y \
           -s $ANYWHERE 21\
           -d $IPADDR $UNPRIVPORTS -j ACCEPT

  ipchains -A input -i $EXTERN_INTERFACE -p tcp\
           -s $ANYWHERE 20\
           -d $IPADDR $UNPRIVPORTS -j ACCEPT

  ipchains -A output -i $EXTERN_INTERFACE -p tcp ! -y\
           -s $IPADDR $UNPRIVPORTS\
           -d $ANYWHERE 20 -j ACCEPT

  ipchains -A output -i $EXTERN_INTERFACE -p tcp\
           -s $IPADDR $UNPRIVPORTS\
           -d $ANYWHERE $UNPRIVPORTS -j ACCEPT

  ipchains -A input -i $EXTERN_INTERFACE -p tcp ! -y\
           -s $ANYWHERE  $UNPRIVPORTS\
           -d $IPADDR $UNPRIVPORTS -j ACCEPT

Das Gleiche in umgekehrter Reihenfolge wäre dann für einen eigenen FTP-Server nötig.

Dabei belassen wir es einmal, die Grundzüge des Aufbaus der Firewallscripts sind damit eigentlich geklärt. Das ganze Script ist hier nochmal am Stück einsehbar.

Unsere Firewall schützt bisher natürlich nur uns selbst, Aber die Mechanismen sind natürlich auch bei einer Firewall mit zwei Netzwerkkarten im Grunde die selben.