Firewall mit ipchains

Grundlagen

Ein Firewall soll unerwünschte Zugriffe von außen unterbinden und nur gewollte Dienste zulassen. Dies wird durch sogenannte Regeln festgelegt. Die Rechner in unserem Netzwerk befinden sich alle im privaten Adressraum 192.168.0. Wenn einer dieser Rechner eine Verbindung zum Internet aufbaut, so muß seine Adresse maskiert (also in die Provideradresse geändert) werden.

Der Kernel 2.2.13 muß mit folgenden Optionen erstellt worden sein.

[*] Packet socket
[*] Firewall-Funktionalität
[*] Unterstützung für Unix Domain Sockets
[*] Unterstützung des TCP/IP-Protokolls
[*] IP: Firewall-Funktionalität
[*] IP: Gerät zur Analyse von Netz-Paketen am Firewall
[*] IP: use FWMARK value as routing key
[*] IP: transparente Proxies
[*] IP: Masquerading
[*] IP: ICMP Masquerading
[*] IP: Unterstützung von Aliasing
[*] IP: Schutz vor "SYN flooding"

Diese Optionen sollten auf jeden Fall eingeschaltet sein. Falls andere Optionen aktiviert waren, so sollte man diese nicht verändern, es sei denn, man weiß genau, was man tut.

Regeln für das interne Netzwerk

Wir erlauben im Intranet die folgenden Dienste:

Regeln für das interne Netzwerk
Dienst Bedeutung TCP-Port UDP-Port Ziel
icmp damit ping funktioniert und wir Fehlermeldungen erhalten krypton
ftp Datenaustausch via ftp Datenport: 20, Steuerport: 21 alle
ssh verschlüsselte Shell 22 alle
telnet unverschlüsselte Shell 23 alle
smtp Mails versenden 25 krypton
dns Domain Name Server 53 53 krypton auf Port 5353 leiten
http Internet 80 alle, auf krypton Port 8080 leiten
pop3s Mails empfangen 995 krypton
netbios Samba, Windowsfreigaben 137-139 137-139 alle
https verschlüsseltes Internet 443 alle, auf krypton Port 8443 leiten

Das sind die Regeln für den internen Netzverkehr. Ping ist erlaubt. Auch ftp, telnet und ssh dürfen als Ziel krypton haben. Es ist also erlaubt, sich aus dem internen Netz auf krypton anzumelden. Der Mailverkehr (smtp, pop3s) soll auch erlaubt sein. DNS-Anfragen sollen nur an krypton gerichtet werden, da hier ja ein DNS-Server läuft, der auch die Ergebnisse zwischenspeichert. Allerdings werden die Anfragen auf Port 5353 umgeleitet, weil der DNS-Server aus Sicherheitsgründen nicht als root läuft und somit keinen Port, der unter 1024 liegt, verwenden kann. Interne WWW-Anfragen werden auf Port 8080 umgelenkt, die anderen werden erlaubt. Der Samba-Server und die Windows-Klienten senden ihre Daten im NetBios-Format. Deshalb sind diese 3 Ports erlaubt.

Regeln für das externe Netzwerk

Der externe Netzverkehr muss sehr sorgfältig abgesichert werden. Angriffe aus dem Netz sind sonst Tür und Tor geöffnet.

ICMP-Pakete werden akzeptiert, wenn sie aus dem internen Netz kommen. ICMP-Pakete von außerhalb werden nur erlaubt, wenn sie Rückantworten oder spezielle Fehlermeldungen sind. Somit wird das Ausspionieren der Netzstruktur hinter dem Router erschwert.

DNS, SMPT und POP3S düfen nur von krypton selbst initiiert werden. Den anderen Rechnern im Netz sollte dies nicht erlaubt werden, da auf krypton ein Mail- und DNS-Server installiert ist.

Telnet, ssh, rlogin, exec, talk, ntalk und WWW-Anfragen vom Intra- ins Internet werden zugelassen. Die andere Richtung wird jedoch verboten. TCP-Pakete haben das SYN-Bit gesetzt ist, wenn sie eine Verbindung initiieren. Und diese Art von Pakete werden wir verbieten.

FTP braucht die unpriviligierten TCP-Ports (>1024). Deshalb werden diese freigegeben. Dies ist ein Sicherheitsrisiko, da z.B. BackOrifice und andere trojanische Pferde diese Ports für ihre Attacken benutzen. Man kann die bekannten Ports sperren, aber jede neue Version kann neue Ports benutzen, so dass absolute Sicherheit in diesem Fall nicht gewährleistet ist. Abhilfe schafft ein iptables-Modul, dass der neuen Netzfilter-Architektur von Linux beiliegt. Dieses Modul überwacht den FTP-Verkehr, und schaltet nur die benötigten Ports frei, wenn Bedarf besteht.

NetBIOS-Pakete lehnen wir grundsätzlich ab, denn es soll ja keiner auf unsere freigegenen Daten zugreifen dürfen.

Das Skript

Die Firewall ist das selbst erstellte Skript /etc/init.d/ipchain. In den Verzeichnissen /sbin/init.d/rc2.d und /sbin/init.d/rc3.d erstellen wir mit ln -s ../ipchain S96ipchain und ln -s ../ipchain K08ipchain Links auf unser Skript. Schauen wir uns das Skript einmal genau an.

#!/bin/bash

#location of the binary
IPCHAINS="/sbin/ipchains"

#internal network: 192.168.0.1 to 192.168.0.254
LAN="192.168.0.0/24"

#ip address of krypton
SERVER="192.168.0.1"

#the whole internet, don't change
ALL="0.0.0.0/0"
#loopback, don't change
SELF="127.0.0.1"

case "$1" in
start)
  echo "Starting firewall"
  #alle Regeln loeschen
  $IPCHAINS -F

  #input, output sperren, forwarding aktivieren
  $IPCHAINS -P input   REJECT
  $IPCHAINS -P forward MASQ
  $IPCHAINS -P output  REJECT

  ### lo, alles erlauben
  /sbin/ifconfig lo > /dev/null
  if [ $? -eq 0 ]
  then
    echo "   Setting up rules for device lo"
    #dns: redirect requests to port 5353
    $IPCHAINS -A input  -i lo -p tcp -d $SELF    53 -j REDIRECT 5353
    $IPCHAINS -A output -i lo -p tcp -s $SELF    53 -j ACCEPT ! -y
    $IPCHAINS -A input  -i lo -p udp -d $SELF    53 -j REDIRECT 5353
    $IPCHAINS -A output -i lo -p udp -s $SELF    53 -j ACCEPT ! -y

    #http: redirect requests to port 8080
    $IPCHAINS -A input  -i lo -p tcp -d $SELF    80 -j REDIRECT 8080
    $IPCHAINS -A output -i lo -p tcp -s $SELF    80 -j ACCEPT ! -y

    #https: redirect requests to port 8443
    $IPCHAINS -A input  -i lo -p tcp -d $SELF   443 -j REDIRECT 8443
    $IPCHAINS -A output -i lo -p tcp -s $SELF   443 -j ACCEPT ! -y

    #accept all packets from and to loopback device
    $IPCHAINS -A input  -i lo -j ACCEPT
    $IPCHAINS -A output -i lo -j ACCEPT
  fi

  ### eth0
  /sbin/ifconfig eth0 > /dev/null
  if [ $? -eq 0 ]
  then
    echo "   Setting up rules for device eth0"

    #allow all outgoing traffic over eth0
    $IPCHAINS -A output -i eth0 -j ACCEPT

    #icmp
    $IPCHAINS -A input  -i eth0 -p icmp -j ACCEPT

    #ftp, telnet, ssh
    $IPCHAINS -A input  -i eth0 -p tcp -s $LAN -d $SERVER 20:23 -j ACCEPT

    #smtp
    $IPCHAINS -A input  -i eth0 -p tcp -s $LAN -d $SERVER 25 -j ACCEPT

    #DNS
    $IPCHAINS -A input  -i eth0 -p tcp -s $LAN -d $SERVER 53 -j REDIRECT 5353
    $IPCHAINS -A input  -i eth0 -p udp -s $LAN -d $SERVER 53 -j REDIRECT 5353

    #www (redirect local requests to port 8080)
    $IPCHAINS -A input  -i eth0 -p tcp -s $LAN   -d $SERVER 80 -j REDIRECT 8080
    $IPCHAINS -A input  -i eth0 -p tcp -s $LAN ! -d $LAN 80 -j ACCEPT

    #pop3
    $IPCHAINS -A input  -i eth0 -p tcp -s $LAN -d $SERVER 110 -j ACCEPT

    #erlaubt netbios (ns, dgm, ssn)
    $IPCHAINS -A input  -i eth0 -p tcp -s $LAN -d $SERVER   137:139 -j ACCEPT
    $IPCHAINS -A input  -i eth0 -p tcp -s $LAN -d 192.168.0.255 137:139 -j ACCEPT
    $IPCHAINS -A input  -i eth0 -p udp -s $LAN -d $SERVER   137:139 -j ACCEPT

    #https (redirect local requests to port 8443)
    $IPCHAINS -A input  -i eth0 -p tcp -s $LAN   -d $SERVER 443 -j REDIRECT 8443
    $IPCHAINS -A input  -i eth0 -p tcp -s $LAN ! -d $LAN 443    -j ACCEPT

    #talk, ntalk
    $IPCHAINS -A input  -i eth0 -p udp -d $SERVER -s $LAN 517:518 -j ACCEPT

    #exec
    $IPCHAINS -A input  -i eth0 -p tcp -s $LAN -d $SERVER 512 -j ACCEPT

    #obere Ports im Netz sind frei
    $IPCHAINS -A input  -i eth0 -p tcp -s $LAN 1024: -d $SERVER 1024: -j ACCEPT
    $IPCHAINS -A input  -i eth0 -p udp -s $LAN 1024: -d $SERVER 1024: -j ACCEPT
  fi

  ## ippp0
  /sbin/ifconfig ippp0 > /dev/null
  if [ $? -eq 0 ]
  then
    echo "   Setting up rules for device ippp0"
    /sbin/modprobe ip_masq_ftp

    #allow all outgoing traffic over eth0
    $IPCHAINS -A output -i ippp0 -j ACCEPT

    #icmp
    $IPCHAINS -A forward -p icmp -i ippp0   -s $LAN -j MASQ
    $IPCHAINS -A input   -p icmp -i ippp0 ! -d $LAN -j ACCEPT

    #FTP
    $IPCHAINS -A forward -p tcp -i ippp0 ! -d $LAN 21 -j MASQ
    $IPCHAINS -A input   -p tcp -i ippp0 ! -d $LAN 21 -j ACCEPT ! -y
    $IPCHAINS -A forward -s $LAN 1024: --dport 21 -p tcp -i ippp0 -j MASQ
    $IPCHAINS -A input   -d $ALL 1024: --sport 21 -p tcp -i ippp0 -j ACCEPT ! -y
    $IPCHAINS -A input   -d $ALL 1024: --sport 20 -p tcp -i ippp0 -j ACCEPT
    $IPCHAINS -A forward -s $LAN 1024: --dport 20 -p tcp -i ippp0 -j MASQ   ! -y

    #unpriviligierte TCP-Ports
    $IPCHAINS -A forward -p tcp -i ippp0 ! -d $LAN 1024: -j MASQ
    $IPCHAINS -A input   -p tcp -i ippp0 ! -d $LAN 1024: -j ACCEPT ! -y

    #unpriviligierte UDP-Ports
    $IPCHAINS -A forward -p udp -i ippp0 ! -d $LAN 1024: -j MASQ
    $IPCHAINS -A input   -p udp -i ippp0 ! -d $LAN 1024: -j ACCEPT
    fi

  #abgelehnte Pakete protokollieren
  $IPCHAINS -A input   -l
  $IPCHAINS -A forward -l
  $IPCHAINS -A output  -l
  ;;
stop)
  echo -n "Shutting down firewall"
  $IPCHAINS -F
  $IPCHAINS -P input   ACCEPT
  $IPCHAINS -P forward ACCEPT
  $IPCHAINS -P output  ACCEPT
  /sbin/modprobe -r ip_masq_ftp
  ;;
restart|reload)
  $0 stop && $0 start
  ;;
status)
  $IPCHAINS -L
  ;;
*)
  echo "Usage: $0 {start|stop|restart|reload|status}"
  exit 1
esac
exit 0

Zuerst werden alle Regeln gelöscht. Anschließend wird alles verboten, was wir nachher nicht explizit erlauben. Zur Vereinfachung wird jeglicher Datenverkehr nach außen zugelassen. Dem Loopback-Device erlauben wir alles. Dies sollte generell auch nicht eingeschränkt werden. DNS Anfragen dürfen nur an krytpon gerichtet werden, und werden dann auf Port 5353 gelenkt. HTTP-Anfragen an krypton auf Port 80 (www) werden auf Port 8080 umgeleitet. Analog die HTTPS-Anfragen auf Port 8443. Auf diesem Port lauscht unsere Apache, mit dem wir das Web-Interface betreiben. Anfragen von außerhalb auf diesen Port werden wir natürlich unterbinden.

Der Aufbau einer Regel folgt einem festgelegten Muster. Zuerst spezifiziert man, ob man eine Regel für den einkommenden (input), ausgehenden (output) oder weiterleitenden (forward) Verkehr angeben möchte. Danach gibt man mit dem Schalter -i das Netzwerkgerät an, für welches die Regel gelten soll.

Kompliziert wird es bei aktivem FTP, z.B. dem Kommandozeilen-Ftp. Hier besteht das Problem, dass die Steuerleitung (Port 21) und die Datenleitung (Port 20) maskiert werden, und die Demaskierung auch beide Datenströme an den richtigen Rechner zurückschicken muss. Dazu wird am Anfang das Modul ip_masq_ftp geladen. Dieses Modul analysiert den Netzverkehr und weist die Datenpakete richtig zu.

Das Protokollieren abgelehnter Pakete vereinfacht die Fehlersuche, falls irgendein Dienst nicht funktioniert. Die Meldungen findet man in den Logdateien.