Exemplarischer Aufbau einer DMZ-Firewall
Keywords: Buch

> Nächste Seite: Wichtige Portnummern Aufwärts: Crashkurs Firewallaufbau unter Linux Vorherige Seite: Die Firewall als Router Inhalt
> Unterabschnitte
> - Die symbolischen Konstanten
>   - Die Konstanten für die Bastion
>   - Die Konstanten für die Choke
> - Weitere Grundeinstellungen
> - ICMP-Nachrichten filtern
>   - Source-Quench Nachrichten
>     - Die Befehle für die Bastion
>     - Die Befehle für die Choke
>   - Parameter-Problem Nachrichten
>     - Die Befehle für die Bastion
>     - Die Befehle für die Choke
>   - Destination-Unreachable Nachrichten
>     - Die Befehle für die Bastion
>     - Die Befehle für die Choke
>   - Time-Exceeded Nachrichten
>     - Die Befehle für die Bastion
>     - Die Befehle für die Choke
>   - Ping Konfiguration
>     - ping Konfiguration der Bastion
>     - ping Konfiguration der Choke
> - Dienste auf unprivilegierten Ports
> - Domain Name Service
>   - Nutzung eines öffentlichen Nameservers
>   - Betreiben eigener Nameserver
>     - Konfiguration der Bastion als öffentlicher Nameserver
>     - Konfiguration der Choke als privater Nameserver
> - Der ident-Service (auth)
>   - Konfiguration der Bastion
>   - Konfiguration der Choke
> - E-Mail
>   - Abgehende Mails über die Bastion verschicken
>   - Mailempfang über POP-Server auf der Bastion
> - Alle weiteren Dienste
> - LAN Zugriff auf die Choke
> - Und schließlich das Masquerading

> # Exemplarischer Aufbau einer DMZ-Firewall

> Um die Komplexität des Aufbaus einer Firewall mit DMZ am Stück darzustellen, werden wir in diesem Kapitel eine komplette solche Firewall aufbauen. Zunächst einmal aber noch etwas Begriffsklärung für das Projekt:
> Bastion
>   Der Rechner, der das Internet mit der DMZ verbindet.
> Choke
>   Der Rechner, der das zu schützende Netz mit der DMZ verbindet.
> DMZ
>   Die demilitarisierte Zone, das Netz zwischen dem Internet und dem zu schützenden Netz.
> LAN
>   Das zu schützende Netz.
> Wir gehen also davon aus, daß Bastion und Choke beide als Gateway (dual homed host) zur DMZ dienen. Die DMZ enthält öffentliche und halböffentliche Server. Jedes Netzwerkinterface der beiden Firewall-Rechner (Bastion und Choke) besitzt eigene, individuelle Regeln. Wir benötigen also mindestens vier Regelsätze, je einen für das externe und interne Interface beider Maschinen. Die Regeln für das externe Interface der Bastion sind fast identisch mit denen aus dem Beispiel aus dem Abschnitt 6.4 (Seite ).

> Die wirklichen Neuigkeiten dieses Kapitels beziehen sich hauptsächlich auf die Schnittstellen zur DMZ, also die interne Schnittstelle der Bastion und die externe Schnittstelle der Choke. Diese Regeln verhalten sich spiegelbildlich zueinander. Für die öffentlichen Server innerhalb der DMZ muß es noch ein paar separate Regeln geben, wir gehen aber in diesem Beispiel davon aus, daß es sich hierbei um spezialisierte Rechner handelt, die jeweils nur einen Dienst anbieten und daher sehr einfache Regeln benötigen.

> Um den Rahmen und die Übersicht über dieses Kapitel nicht zu gefährden, werden innerhalb des Kapitels Vereinfachungen zugelassen. Weil die externen Regeln der Bastion praktisch identisch sind mit denen aus Abschnitt 6.4, werden hier nur die Unterschiede dargestellt. Im Anhang ab Seite sind die beiden Scripts für Bastion und Choke jedoch beide noch einmal vollständig abgedruckt.

> Bild 8..1: Der Aufbau des Beispiels

> Das externe Interface der Bastion liegt auf der Schnittstelle `eth0` und hat die echte IP-Adresse 123.45.67.89 zugewiesen. Das interne Interface liegt auf `eth1` und hat die reservierte Adresse 192.168.1.1

> Die DMZ hat die 192.168.1.0 als Netzwerkadresse.

> Die Choke hat ihr externes Netz am Interface `eth0` und dort die Adresse 192.168.1.2, ihr internes Netz liegt auf `eth1` und bekommt die Adresse 192.168.5.1

> Das LAN hat die Netzadresse 192.168.5.0 als Netzwerkadresse.

> # Die symbolischen Konstanten

> Ein Firewallscript lässt sich grundsätzlich leichter lesen und hauptsächlich flexibler an Veränderungen anpassen, wenn wir nicht bei jeder Regel erneut die IP-Adressen angeben, sondern am Anfang symbolische Konstanten definieren, die wir im weiteren Verlauf dann benutzen. Das ist immer das erste, was beim Aufbau neuer Scripts zu beachten ist und daher halten wir uns an diese Vorgaben:

> ## Die Konstanten für die Bastion

>       # Konstantendefinition
>       EXTERNAL_INTERFACE=eth0        # Das Interface ins Internet
>       IPADDR=123.45.67.89            # Adresse des Internetzugangs
>       MY_ISP=123.45.67.90/16         # Der Bereich meines Providers

>       BASTION_DMZ_INTERFACE=eth1     # internes Interface
>       BASTION_DMZ_IPADDR=192.168.1.1 # Adresse dazu

>       LOOPBACK_INTERFACE=lo          # Local Loopback
>       LOOPBACK=127.0.0.0/8           # Loopback-Adressbereich

>       CHOKE_DMZ_IPADDR=192.168.1.2   # ext. Interface der Choke
>       DMZ_ADDRESSES=192.168.1.0/24   # IP-Bereich der DMZ
>       DMZ_BROADCAST=192.168.1.255    # Broadcastadresse DMZ
>       ANYWHERE=any/0                 # Jede IP-Adresse

>       CLASS_A=10.0.0.0/8             # Reservierter Bereich Klasse A
>       CLASS_B=172.16.0.0/12          # Reservierter Bereich Klasse B
>       CLASS_C=192.168.0.0/16         # Reservierter Bereich Klasse C
>       CLASS_D=224.0.0.0/4            # Komplette Klasse D
>       CLASS_E=240.0.0.0/5            # Komplette Klasse E
>       BROADCAST_SRC=0.0.0.0          # Broadcast Absender
>       BROADCAST_DEST=255.255.255.255 # Broadcast Empfänger
>       PRIVPORTS=0:1023               # Privilegierte Portnummern
>       UNPRIVPORTS=1024:65535         # Unprivilegierte Portnummern

> ## Die Konstanten für die Choke

>       #Konstantendefinition
>       CHOKE_DMZ_INTERFACE=eth0       # externes Interface der Choke
>       CHOKE_DMZ_IPADDR=192.168.1.2   # externe Adresse der Choke
>       CHOKE_LAN_INTERFACE=eth1       # internes Interface der Choke
>       CHOKE_LAN_IPADDR=192.168.5.1   # interne Adresse der Choke
>       LOOPBACK_INTERFACE=lo          # Local Loopback
>       LOOPBACK=127.0.0.0/8           # Loopback-Adressbereich

>       BASTION_DMZ_IPADDR=192.168.1.1 # interne Adresse der Bastion
>       DMZ_ADDRESSES=192.168.1.0/24   # IP-Bereich der DMZ
>       LAN_ADDRESSES=192.168.5.0/24   # IP-Bereich des LAN
>       DMZ_BROADCAST=192.168.1.255    # Broadcastadresse DMZ
>       ANYWHERE=any/0                 # Jede IP-Adresse

>       CLASS_A=10.0.0.0/8             # Reservierter Bereich Klasse A
>       CLASS_B=172.16.0.0/12          # Reservierter Bereich Klasse B
>       CLASS_C=192.168.0.0/16         # Reservierter Bereich Klasse C
>       CLASS_D=224.0.0.0/4            # Komplette Klasse D
>       CLASS_E=240.0.0.0/5            # Komplette Klasse E
>       BROADCAST_SRC=0.0.0.0          # Broadcast Absender
>       BROADCAST_DEST=255.255.255.255 # Broadcast Empfänger
>       PRIVPORTS=0:1023               # Privilegierte Portnummern
>       UNPRIVPORTS=1024:65535         # Unprivilegierte Portnummern

> # Weitere Grundeinstellungen

> Wie üblich löschen wir zunächst einmal in beiden Scripts (für Choke und Bastion) die bisher bestehenden Regeln. Das ist nur eine Sicherheitsmaßnahme, um zu vermeiden, daß eventuell existierende Regeln, die vor dem Aufruf des Scripts erstellt wurden, nicht weiter gelten. In beiden Scripts steht also jetzt

>       # Alle bestehenden Regeln löschen
>       ipchains -F

> Die Chains sind jetzt gelöscht, nicht jedoch eine eventuell bestehende Policy. Also definieren wir sofort eine neue, die alles grundsätzlich verbietet, was nicht explizit erlaubt ist. Hier machen wir aber einen Unterschied zwischen Bastion und Choke. Die Bastion arbeitet grundsätzlich mit DENY, gibt also keinerlei Rückmeldungen zurück, außer ins interne Netz, also die DMZ. Das ist wichtig, weil solche Rückmeldungen einem potenziellen Angreifer schon bestimmte Dinge mitteilen kann. Die Choke jedoch arbeitet in einem Umfeld, das wesentlich mehr Vertrauen von uns verdient. Hier arbeiten wir mit REJECT, um Fehlermeldungen zu erzeugen und Timeout-Wartezeiten dadurch zu vermeiden. Das Script der Bastion erhält also folgenden Eintrag:

>       # Voreingestellte Policies setzen
>       ipchains -P input    DENY
>       ipchains -P output   REJECT
>       ipchains -P forward  REJECT

> während die Choke überall mit REJECT arbeitet:

>       # Voreingestellte Policies setzen
>       ipchains -P input    REJECT
>       ipchains -P output   REJECT
>       ipchains -P forward  REJECT

> An diesem Punkt sind alle Regeln gelöscht und alle Policies auf DENY oder REJECT gesetzt. Es ist keinerlei Netzverkehr mehr möglich. Wie im letzten Beispiel sollten wir jetzt zunächst wieder das Loopback-Device ermöglichen, dort sind Angriffe nicht möglich, es droht keinerlei Gefahr, wir lassen einfach alles auf diesem Device zu. Das gilt wieder für beide Maschinen, Bastion und Choke:

>       # Loopback ohne Einschränkungen
>       ipchains -A input  -i $LOOPBACK_INTERFACE -j ACCEPT
>       ipchains -A output -i $LOOPBACK_INTERFACE -j ACCEPT

> Es kann auch nicht schaden, wenn wir an dieser Stelle wieder bei beiden Maschinen die Kernel-eigenen Schutzroutinen aktivieren, wie wir das auch schon im Abschnitt 6.4.2 gemacht hatten. Dort ist es schon erklärt, daher hier nur noch die entsprechenden Anweisungen:

>       # SYN_COOKIES aktivieren
>       echo 1 > /proc/sys/net/ipv4/tcp_syncookies

>       # SOURCE ADDRESS VERIFICATION aktivieren
>       for i in /proc/sys/net/ipv4/conf/*/rp_filter
>       do
>         echo 1 > $i
>       done

> Jetzt filtern wir wieder die Adressen aus, die offensichtlich ungültig sind. Zunächst mal wieder jeweils die eigenen Adressen. Die Bastion Firewall bekommt also die Anweisungen

>       # Pakete ablehnen, die vorgeben von der eigenen Adresse zu stammen
>       ipchains -A input -i $EXTERNAL_INTERFACE \
>                -s $IPADDR -j DENY -l
>       ipchains -A input -i $BASTION_DMZ_INTERFACE \
>                -s $BASTION_DMZ_IPADDR -j DENY -l

> während die Choke folgende Zeilen braucht:

>       # Pakete ablehnen, die vorgeben von der eigenen Adresse zu stammen
>       ipchains -A input -i $CHOKE_LAN_INTERFACE\
>                -s $CHOKE_LAN_IPADDR -j REJECT -l
>       ipchains -A input -i CHOKE_DMZ_INTERFACE \
>                -s $CHOKE_DMZ_IPADDR -j REJECT -l

> Bei der Bastion belassen wir die Filterung der restlichen Adressen wie in unserem Beispiel aus Abschnitt 6.4. Die Choke hingegen muß nur Adressen aus dem Pool der reservierten A- und B-Klassen aussondern, weil sie ja selbst auf beiden Netzwerkkarten eine C-Klasse reservierte Adresse benutzt. Nebenbei filtern wir wie gehabt auch Loopback- und fehlerhafte Broadcasts aus. Die Angabe der von der IANA reservierten Adressen sparen wir uns für die Choke, die Bation hat sie ja schon.

>       # Pakete mit privaten A-Klasse Adressen als Sender oder
>       # Empfänger verwerfen
>       ipchains -A input -i $CHOKE_DMZ_INTERFACE -s $CLASS_A -j REJECT -l
>       ipchains -A input -i $CHOKE_LAN_INTERFACE -s $CLASS_A -j REJECT -l
>       ipchains -A output -i $CHOKE_DMZ_INTERFACE -d $CLASS_A -j REJECT -l
>       ipchains -A output -i $CHOKE_LAN_INTERFACE -d $CLASS_A -j REJECT -l

>       # Pakete mit privaten B-Klasse Adressen als Sender oder
>       # Empfänger verwerfen
>       ipchains -A input -i $CHOKE_DMZ_INTERFACE -s $CLASS_B -j REJECT -l
>       ipchains -A input -i $CHOKE_LAN_INTERFACE -s $CLASS_B -j REJECT -l
>       ipchains -A output -i $CHOKE_DMZ_INTERFACE -d $CLASS_B -j REJECT -l
>       ipchains -A output -i $CHOKE_LAN_INTERFACE -d $CLASS_B -j REJECT -l

>       # Pakete mit D-Klasse Adressen als Sender verwerfen
>       ipchains -A input -i $CHOKE_DMZ_INTERFACE -s $CLASS_D -j REJECT -l
>       ipchains -A input -i $CHOKE_LAN_INTERFACE -s $CLASS_D -j REJECT -l
>       ipchains -A output -i $CHOKE_DMZ_INTERFACE -s $CLASS_D -j REJECT -l
>       ipchains -A output -i $CHOKE_LAN_INTERFACE -s $CLASS_D -j REJECT -l

>       # Pakete mit E-Klasse Adressen verwerfen
>       ipchains -A input -i $CHOKE_DMZ_INTERFACE -s $CLASS_E -j REJECT -l
>       ipchains -A input -i $CHOKE_LAN_INTERFACE -s $CLASS_E -j REJECT -l

>       # Pakete mit Loopback Adressen als Sender verwerfen
>       ipchains -A input -i $CHOKE_DMZ_INTERFACE -s $LOOPBACK -j REJECT -l
>       ipchains -A input -i $CHOKE_LAN_INTERFACE -s $LOOPBACK -j REJECT -l

>       # Pakete mit fehlerhaften Broadcast Adressen verwerfen
>       ipchains -A input -i $CHOKE_DMZ_INTERFACE \
>                -s $BROADCAST_DEST -j REJECT -l
>       ipchains -A input -i $CHOKE_LAN_INTERFACE \
>                -s $BROADCAST_DEST -j REJECT -l
>       ipchains -A input -i $CHOKE_DMZ_INTERFACE \
>                -d $BROADCAST_SRC -j REJECT -l
>       ipchains -A input -i $CHOKE_LAN_INTERFACE \
>                -d $BROADCAST_SRC -j REJECT -l

> Damit hätten wir die Grundeinstellung bei beiden Scripts erledigt. Jetzt geht es an die eigentliche Arbeit, verspricht aber auch interessanter zu werden.

> # ICMP-Nachrichten filtern

> Die Bastion hat schon Regeln für ICMP-Nachrichten, die sich bisher aber nur auf die externe Schnittstelle, also auf die Schnittstelle ins Internet beziehen. Diese Regeln lassen wir wie gehabt, fügen aber noch ein paar Regeln für die Kommunukation mit der DMZ hinzu. Hier wird das erste Mal die Symetrie zwischen dem internen Interface der Bastion und dem externen der Choke sichtbar.

> ## Source-Quench Nachrichten

> Die ICMP-Nachrichten vom Typ 4 (`source-quench`) werden erstellt, wenn ein Kommunikationspartner mit der Geschwindigkeit eines anderen nicht mehr mithalten kann, weil z.B. seine internen Buffer voll sind. Bastion und Choke akzeptieren alle `source-quench` Nachrichten, die bei der Kommunikation mit der DMZ entstehen.

> ### Die Befehle für die Bastion

>       # source-quench zur DMZ
>       ipchains -A output -i $BASTION_DMZ_INTERFACE -p icmp\
>                -s $BASTION_DMZ_IPADDR 4 -d $DMZ_ADDRESSES -j ACCEPT
>       ipchains -A input -i $BASTION_DMZ_INTERFACE -p icmp\
>                -s $DMZ_ADDRESSES 4 -d $BASTION_DMZ_IPADDR -j ACCEPT

> ### Die Befehle für die Choke

>       # source-quench zur DMZ
>       ipchains -A input -i $CHOKE_DMZ_INTERFACE -p icmp\
>                -s $DMZ_ADDRESSES 4 -d $CHOKE_DMZ_IPADDR -j ACCEPT
>       ipchains -A output -i $CHOKE_DMZ_INTERFACE -p icmp\
>                -s $CHOKE_DMZ_IPADDR 4 -d $DMZ_ADDRESSES -j ACCEPT

> Sichtbar wird hier, daß die Regeln für Bastion und Choke sehr ähnlich sind, aber eben nur die für die interne Bastion Schnittstelle und die der externen Choke Schnittstelle. Das ist logisch, denn diese beiden Schnittstellen transportieren ja die Informationspakete vom LAN ins Internet.

> ## Parameter-Problem Nachrichten

> Diese Nachrichtenpakete (Typ 12) werden gesendet, wenn ein Paket empfangen wurde, das ungültige Daten im Header aufweist. Auch diese Nachrichten lassen wir für die Kommunikation mit der DMZ grundsätzlich durch.

> ### Die Befehle für die Bastion

>       # parameter-problem zur DMZ
>       ipchains -A output -i $BASTION_DMZ_INTERFACE -p icmp\
>                -s $ANYWHERE 12 -d $DMZ_ADDRESSES -j ACCEPT
>       ipchains -A input -i $BASTION_DMZ_INTERFACE -p icmp\
>                -s $DMZ_ADDRESSES 12 -d $ANYWHERE -j ACCEPT

> ### Die Befehle für die Choke

>       # parameter-problem zur DMZ
>       ipchains -A input -i $CHOKE_DMZ_INTERFACE -p icmp\
>                -s $ANYWHERE 12 -d $CHOKE_DMZ_IPADDR -j ACCEPT
>       ipchains -A output -i $CHOKE_DMZ_INTERFACE -p icmp\
>                -s $CHOKE_DMZ_IPADDR 12 -d $ANYWHERE -j ACCEPT

> ## Destination-Unreachable Nachrichten

> Dieser Nachrichtenpakettyp (Typ 3) ist eine allgemeine Fehlermeldung. Auch diese Nachrichten lassen wir für die Kommunikation mit der DMZ grundsätzlich durch.

> ### Die Befehle für die Bastion

>       # destination-unreachable zur DMZ
>       ipchains -A output -i $BASTION_DMZ_INTERFACE -p icmp\
>                -s $ANYWHERE 3 -d $DMZ_ADDRESSES -j ACCEPT
>       ipchains -A input -i $BASTION_DMZ_INTERFACE -p icmp\
>                -s $DMZ_ADDRESSES 3 -d $ANYWHERE -j ACCEPT

> ### Die Befehle für die Choke

>       # destination-unreachable zur DMZ
>       ipchains -A input -i $CHOKE_DMZ_INTERFACE -p icmp\
>                -s $ANYWHERE 3 -d $CHOKE_DMZ_IPADDR -j ACCEPT
>       ipchains -A output -i $CHOKE_DMZ_INTERFACE -p icmp\
>                -s $CHOKE_DMZ_IPADDR 3 -d $ANYWHERE -j ACCEPT

> ## Time-Exceeded Nachrichten

> Diese Nachrichtenpakete (Typ 11) zeigen an, daß ein Paket zu oft geroutet wurde, daß seine Lebensdauer auf 0 gesunken ist. Es wird aber auch als Antwort für Traceroute benutzt. Auch diese Nachrichten lassen wir für die Kommunikation mit der DMZ grundsätzlich durch.

> ### Die Befehle für die Bastion

>       # time-exceeded zur DMZ
>       ipchains -A output -i $BASTION_DMZ_INTERFACE -p icmp\
>                -s $BASTION_DMZ_IPADDR 11 -d $DMZ_ADDRESSES -j ACCEPT
>       ipchains -A input -i $BASTION_DMZ_INTERFACE -p icmp\
>                -s $DMZ_ADDRESSES 11 -d $BASTION_DMZ_IPADDR -j ACCEPT

> ### Die Befehle für die Choke

> Die Choke darf nur mit der Bastion Nachrichten vom Typ `time-exceed` austauschen.

>       # time-exceeded zur DMZ
>       ipchains -A input -i $CHOKE_DMZ_INTERFACE -p icmp\
>                -s $BASTION_DMZ_IPADDR 11 -d $CHOKE_DMZ_IPADDR -j ACCEPT
>       ipchains -A output -i $CHOKE_DMZ_INTERFACE -p icmp\
>                -s $CHOKE_DMZ_IPADDR 11 -d $BASTION_DMZ_IPADDR -j ACCEPT

> ## Ping Konfiguration

> Der Befehl `ping` verwendet zwei unterschiedliche Nachrichtentypen, jeweils für Anfragen (`echo-request` - Typ 8) und Antworten (`echo-reply` - Typ 0).

> ### ping Konfiguration der Bastion

> Alle Rechner der DMZ dürfen ins Internet pingen:

>       # Ausgehendes Ping aus der DMZ
>       ipchains -A input -i $BASTION_DMZ_INTERFACE -p icmp\
>                -s $DMZ_ADDRESSES 8 -d $ANYWHERE -j ACCEPT
>       ipchains -A output -i $BASTION_DMZ_INTERFACE -p icmp\
>                -s $ANYWHERE 0 -d $DMZ_ADDRESSES -j ACCEPT

> Andersherum darf aber nur die Bastion selbst Rechner in der DMZ anpingen:

>       # Ankommendes Ping in die DMZ
>       ipchains -A output -i $BASTION_DMZ_INTERFACE -p icmp\
>                -s $BASTION_DMZ_IPADDR 8 -d $DMZ_ADDRESSES -j ACCEPT
>       ipchains -A input -i $BASTION_DMZ_INTERFACE -p icmp\
>                -s $DMZ_ADDRESSES 0 -d $BASTION_DMZ_IPADDR -j ACCEPT

> ### ping Konfiguration der Choke

> Die Choke darf jeden Rechner im Internet anpingen:

>       # Ausgehendes Ping ins Internet
>       ipchains -A output -i $CHOKE_DMZ_INTERFACE -p icmp\
>                -s $CHOKE_DMZ_IPADDR 8 -d $ANYWHERE -j ACCEPT
>       ipchains -A input -i $CHOKE_DMZ_INTERFACE -p icmp\
>                -s $ANYWHERE 0 -d $CHOKE_DMZ_IPADDR -j ACCEPT

> Ankommende Pings sind jedoch nur aus der DMZ gestattet.

>       # Ankommende Pings aus der DMZ
>       ipchains -A input -i $CHOKE_DMZ_INTERFACE -p icmp\
>                -s $DMZ_ADDRESSES 8 -d $CHOKE_DMZ_IPADDR -j ACCEPT
>       ipchains -A output -i $CHOKE_DMZ_INTERFACE -p icmp\
>                -s $CHOKE_DMZ_IPADDR 0 -d $DMZ_ADDRESSES -j ACCEPT

> # Dienste auf unprivilegierten Ports

> Die Dienste auf den unprivilegierten Ports lassen wir auf der Bastion so, wie wir sie im Abschnitt 6.4 formuliert hatte. Die Choke muß diese Dienste überhaupt nicht beachten, denn es waren ja nur Verbote aus dem globalen Netz. Von außen droht uns also keine Gefahr mehr.

> Wir brauchen diese Dienste nicht vom LAN in die DMZ weitergeben und da grundsätzlich alles verboten ist, was nicht explizit erlaubt, benötigen wir keine Regeln mehr. Innerhalb des LAN stehen sie uns natürlich weiter zur Verfügung. Dort werden Pakete ja nicht gefiltert, sondern nur weitergegeben.

> # Domain Name Service

> Das DNS-System (TCP- und UDP-Port 53) ist heute für eine Zugriff auf das Internet von zwingender Bedeutung. Ohne Nameserver müssten die IP-Addressen der einzelnen Server im Internet bekannt sein, das ist mehr oder weniger unmöglich. Alle Rechner des LAN müssen also Zugriff auf einen Nameserver haben. Dabei gibt es aber verschiedene Möglichkeiten, die hier kurz beschrieben werden sollen.

> ## Nutzung eines öffentlichen Nameservers

> Die einfachste Form ist die, daß ein öffentlicher Nameserver im Internet, etwa der Ihres Providers benutzt wird. In diesem Fall muß der Choke nur mitgeteilt werden, daß DNS-Anfragen durchgelassen werden, so wie wir das auch schon im Beispiel in Abschnitt 6.4 getan haben. Die Bastion behält die Zeilen aus dem genannten Beispiel ebenfalls. Damit ist ein Durchgang geschaffen, der alle notwendigen DNS-Dienste ermöglicht. Die Choke erhält also die Zeilen:

>       # DNS IP Adresse:
>       NAMESERVER=xx.xx.xx.xx

>       # UDP-Nameserverzugriff
>       ipchains -A output -i $CHOKE_DMZ_INTERFACE -p udp\
>                -s $CHOKE_DMZ_IPADDR $UNPRIVPORTS \
>                -d $NAMESERVER 53 -j ACCEPT

>       ipchains -A input -i $CHOKE_DMZ_INTERFACE -p udp\
>                -s $NAMESERVER 53 \
>                -d $CHOKE_DMZ_IPADDR $UNPRIVPORTS -j ACCEPT

>       # TCP-Nameserverzugriff
>       ipchains -A output -i $CHOKE_DMZ_INTERFACE -p tcp\
>                -s $CHOKE_DMZ_IPADDR $UNPRIVPORTS \
>                -d $NAMESERVER 53 -j ACCEPT

>       ipchains -A input -i $CHOKE_DMZ_INTERFACE -p tcp ! -y\
>                -s $NAMESERVER 53 \
>                -d $CHOKE_DMZ_IPADDR $UNPRIVPORTS -j ACCEPT

> Wir werden ja später das Masquerading aktivieren, daher reicht es, wenn die Adresse immer nur die der Choke ist. Alle Adressen des LAN werden ja in diese Adresse maskiert.

> ## Betreiben eigener Nameserver

> Ein wesentlich komplexeres Verfahren besteht darin, eigene Nameserver zu betreiben. In unserem Beispiel würde sich dabei - wenn hohe Sicherheit erwünscht ist - folgendes Szenario anbieten:

> Auf der Bastion läuft ein öffentlicher Nameserver. Er ist konfiguriert als autoritativer Server für die Site, verfügt aber nur über unvollständige Daten. Er hat keine Informationen über die Rechner des LAN, nur über die der DMZ. Die Programme der Bastion selbst greifen nicht auf diesen Server zu.

> Auf der Choke läuft auch ein Nameserver. Dieser Nameserver enthält tatsächlich die realen Daten des LAN und der DMZ. Alle Clients aus dem LAN greifen ausschließlich auf diesen Nameserver zu. Auch die Clients der Bastion (die Programme der Bastion, die einen DNS-Dienst benötigen) greifen auf den Server der Choke zu. Wenn der Choke-Server eine Anfrage nicht beantworten kann, leitet er sie weiter an den Server der Bastion, der sie wiederum an einen externen Server im Internet weitergibt.

> Für diese Konfiguration sind natürlich auch erheblich komplexere Regeln notwendig.

> ### Konfiguration der Bastion als öffentlicher Nameserver

>       # Der DNS-Server der Bastion akzeptiert Anfragen der Choke (UDP 53)
>       ipchains -A input -i $BASTION_DMZ_INTERFACE -p udp\
>                -s $CHOKE_DMZ_IPADDR 53\
>                -d $BASTION_DMZ_IPADDR 53 -j ACCEPT
>       ipchains -A output -i $BASTION_DMZ_INTERFACE -p udp\
>                -s $BASTION_DMZ_IPADDR 53\
>                -d $CHOKE_DMZ_IPADDR 53 -j ACCEPT

>       # DNS Anfragen der Bastion an den Server der Choke (UDP/TCP 53)
>       ipchains -A output -i $BASTION_DMZ_INTERFACE -p udp\
>                -s $BASTION_DMZ_IPADDR $UNPRIVPORTS \
>                -d $CHOKE_DMZ_IPADDR 53 -j ACCEPT
>       ipchains -A input -i $BASTION_DMZ_INTERFACE -p udp\
>                -s $CHOKE_DMZ_IPADDR 53 \
>                -d $BASTION_DMZ_IPADDR $UNPRIVPORTS -j ACCEPT
>       ipchains -A output -i $BASTION_DMZ_INTERFACE -p tcp\
>                -s $BASTION_DMZ_IPADDR $UNPRIVPORTS \
>                -d $CHOKE_DMZ_IPADDR 53 -j ACCEPT
>       ipchains -A input -i $BASTION_DMZ_INTERFACE -p tcp ! -y\
>                -s $CHOKE_DMZ_IPADDR 53 \
>                -d $BASTION_DMZ_IPADDR $UNPRIVPORTS -j ACCEPT

>       # DNS IP Adresse (Nameserver im Internet):
>       NAMESERVER=xx.xx.xx.xx

>       #DNS Forwarding (Server zu Server)
>       ipchains -A output -i $EXTERNAL_INTERFACE -p udp\
>                -s $IPADDR 53 \
>                -d $NAMESERVER 53 -j ACCEPT

>       ipchains -A input -i $EXTERNAL_INTERFACE -p udp\
>                -s $NAMESERVER 53 \
>                -d $IPADDR 53 -j ACCEPT

>       # UDP-Nameserverzugriff
>       ipchains -A output -i $EXTERNAL_INTERFACE -p udp\
>                -s $IPADDR $UNPRIVPORTS \
>                -d $ANYWHERE 53 -j ACCEPT
>       ipchains -A input -i $EXTERNAL_INTERFACE -p udp\
>                -s $ANYWHERE 53 \
>                -d $IPADDR $UNPRIVPORTS -j ACCEPT

>       # TCP-Nameserverzugriff
>       ipchains -A output -i $EXTERNAL_INTERFACE -p tcp\
>                -s $IPADDR $UNPRIVPORTS \
>                -d $ANYWHERE 53 -j ACCEPT
>       ipchains -A input -i $EXTERNAL_INTERFACE -p tcp ! -y\
>                -s $ANYWHERE 53 \
>                -d $IPADDR $UNPRIVPORTS -j ACCEPT

>       # DNS Zugriff fremder Clients
>       ipchains -A input -i $EXTERNAL_INTERFACE -p udp\
>                -s $ANYWHERE $UNPRIVPORTS\
>                -d $IPADDR 53 -j ACCEPT
>       ipchains -A output -i $EXTERNAL_INTERFACE -p udp\
>                -s $IPADDR 53\
>                -d $ANYWHERE $UNPRIVPORTS -j ACCEPT
>       ipchains -A input -i $EXTERNAL_INTERFACE -p tcp\
>                -s $ANYWHERE $UNPRIVPORTS\
>                -d $IPADDR 53 -j ACCEPT
>       ipchains -A output -i $EXTERNAL_INTERFACE -p tcp ! -y\
>                -s $IPADDR 53\
>                -d $ANYWHERE $UNPRIVPORTS -j ACCEPT

> ### Konfiguration der Choke als privater Nameserver

> Der private Nameserver liegt auf der Choke. Clients aus dem LAN und der Bastion greifen auf diesen Server zu. Wenn er eine Anfrage nicht beantworten kann, dann leitet er sie an den Server der Bastion weiter.

> Die Regeln für die Choke verhalten sich gewissermaßen spiegelbildlich zu denen der Bastion.

>       # Der DNS-Server der Choke gibt Anfragen an die Bastion (UDP 53)
>       ipchains -A output -i $CHOKE_DMZ_INTERFACE -p udp\
>                -s $CHOKE_DMZ_IPADDR 53\
>                -d $BASTION_DMZ_IPADDR 53 -j ACCEPT
>       ipchains -A input -i $CHOKE_DMZ_INTERFACE -p udp\
>                -s $BASTION_DMZ_IPADDR 53\
>                -d $CHOKE_DMZ_IPADDR 53 -j ACCEPT

>       # Der Nameserver der Choke lässt Anfragen aller Clients aus der
>       # DMZ zu (TCP/UDP 53)
>       ipchains -A input -i $CHOKE_DMZ_INTERFACE -p udp \
>                -s $DMZ_ADDRESSES $UNPRIVPORTS \
>                -d $CHOKE_DMZ_IPADDR 53 -j ACCEPT
>       ipchains -A input -i $CHOKE_DMZ_INTERFACE -p udp \
>                -s CHOKE_DMZ_IPADDR 53 \
>                -d $DMZ_ADDRESSES $UNPRIVPORTS -j ACCEPT
>       ipchains -A input -i $CHOKE_DMZ_INTERFACE -p tcp \
>                -s $DMZ_ADDRESSES $UNPRIVPORTS \
>                -d $CHOKE_DMZ_IPADDR 53 -j ACCEPT
>       ipchains -A input -i $CHOKE_DMZ_INTERFACE -p tcp ! -y \
>                -s CHOKE_DMZ_IPADDR 53 \
>                -d $DMZ_ADDRESSES $UNPRIVPORTS -j ACCEPT

> # Der ident-Service (auth)

> Dieser Service (TCP 113) wird von manchen Internet-Diensten benutzt, um Namen oder ID eines bestimmten Users zu erfragen. Das ist etwa bei fremden Mailservern der Fall, die Mails weitergeben. Es ist nicht zwingend nötig, selbst einen solchen Server laufen zu haben, obwohl nichts dagegen spricht. Auf jeden Fall sollten wir eine Firewall-Regel erstellen, um unnötige Timeouts zu vermeiden.

> Für unser Beispiel werden wir davon ausgehen, daß sowohl auf der Bastion, als auch auf der Choke sowohl Clients, als auch Server mit dem `auth`-Protokoll arbeiten.

> ## Konfiguration der Bastion

>         # abgehende auth-Anfragen ins Internet
>       ipchains -A output -i $EXTERNAL_INTERFACE -p tcp\
>                -s $IPADDR $UNPRIVPORTS\
>                -d $ANYWHERE 113 -j ACCEPT

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

>       # ankommende auth-Anfragen aus dem Internet
>       ipchains -A input -i $EXTERNAL_INTERFACE -p tcp\
>                -s $ANYWHERE $UNPRIVPORTS\
>                -d $IPADDR 113 -j ACCEPT

>       ipchains -A output -i $EXTERNAL_INTERFACE -p tcp ! -y\
>                -s $IPADDR 113 \
>                -d $ANYWHERE $UNPRIVPORTS -j ACCEPT

>       # Bastion als auth-Client nach innen
>       ipchains -A output -i $BASTION_DMZ_INTERFACE -p tcp \
>                -s $BASTION_DMZ_IPADDR $UNPRIVPORTS \
>                -d $DMZ_ADDRESSES 113 -j ACCEPT
>       ipchains -A input -i $BASTION_DMZ_INTERFACE -p tcp ! -y\
>                -s $DMZ_ADDRESSES 113 \
>                -d $BASTION_DMZ_IPADDR $UNPRIVPORTS -j ACCEPT

>       # Bastion als Server nach innen
>       ipchains -A input -i $BASTION_DMZ_INTERFACE -p tcp \
>                -s $DMZ_ADDRESSES $UNPRIVPORTS \
>                -d $BASTION_DMZ_IPADDR 113 -j ACCEPT
>       ipchains -A output -i $BASTION_DMZ_INTERFACE -p tcp ! -y\
>                -s $BASTION_DMZ_IPADDR 113 \
>                -d $DMZ_ADDRESSES $UNPRIVPORTS -j ACCEPT

> ## Konfiguration der Choke

>       # Choke als auth Server
>       ipchains -A input -i $CHOKE_DMZ_INTERFACE -p tcp \
>                -s $DMZ_ADDRESSES $UNPRIVPORTS \
>                -d $CHOKE_DMZ_IPADDR 113 -j ACCEPT
>       ipchains -A output -i $CHOKE_DMZ_INTERFACE -p tcp ! -y\
>                -s $CHOKE_DMZ_IPADDR 113 \
>                -d $DMZ_ADDRESSES $UNPRIVPORTS -j ACCEPT

>       # Choke als auth-Client
>       ipchains -A output -i $CHOKE_DMZ_INTERFACE -p tcp\
>                -s $CHOKE_DMZ_IPADDR $UNPRIVPORTS \
>                -d $ANYWHERE 113 -j ACCEPT
>       ipchains -A input -i $CHOKE_DMZ_INTERFACE -p tcp ! -y \
>                -s $ANYWHERE 113 \
>                -d $CHOKE_DMZ_IPADDR $UNPRIVPORTS -j ACCEPT

> # E-Mail

> Es gibt natürlich - auch nur für unser Modell - eine Vielzahl von denkbaren Kombinationen für E-Mail Empfang und Versand. Wir werden hier exemplarisch eine Kombination durchspielen, die wahrscheinlich in der Praxis die häufigste ist. Die Bastion, die ja eine echte IP-Adresse hat, sendet und empfängt Mail mit SMTP (TCP 25). Die Rechner des LAN holen sich die Mails bei der Bastion mittels POP3 (TCP 110) ab.

> Wir müssen also der Bastion erlauben SMTP-Pakete zu empfangen und zu senden, und weiterhin POP-Anfragen zu empfangen und zu beantworten. Die Choke muß auch SMTP durchlassen, schließlich senden die Rechner des LAN ihre Mails ja mit SMTP. Sie muß ebenfalls POP-Pakete durchlassen, in beide Richtungen.

> ## Abgehende Mails über die Bastion verschicken

> Hier haben wir zunächst einmal zwei Möglichkeiten. Entweder wir schicken alle ausgehende Mail an den Mailserver unseres Providers oder wir schicken sie gleich an die entsprechenden Empfängerrechner. Die einfachere Möglichkeit ist die des Providerservers, weil der sich dann um die korrekte Weiterleitung kümmern muß. Die dazu nötigen Regeln der Bastion sind:

>       # Mail über SMTP an Provider Gateway
>       # Zuerst der Name des Gateways
>       SMTP_GATEWAY=smtp.server.provider.beispiel

>       ipchains -A output -i $EXTERNAL_INTERFACE -p tcp\
>                -s $IPADDR $UNPRIVPORTS \
>                -d $SMTP_GATEWAY 25 -j ACCEPT
>       ipchains -A output -i $EXTERNAL_INTERFACE -p tcp ! -y\
>                -s $SMTP_GATEWAY 25 \
>                -d $IPADDR $UNPRIVPORTS -j ACCEPT

> Wenn aber stattdessen erwünscht ist, daß die Bastion selbst Mailserver ist, also die Mail direkt zu verschicken, dann muß einfach statt der Angabe des SMTP-Gateways ein `$ANYWHERE` verwendet werden:

>       # Mail über SMTP an Provider Gateway
>       ipchains -A output -i $EXTERNAL_INTERFACE -p tcp\
>                -s $IPADDR $UNPRIVPORTS \
>                -d $ANYWHERE 25 -j ACCEPT
>       ipchains -A output -i $EXTERNAL_INTERFACE -p tcp ! -y\
>                -s $ANYWHERE 25 \
>                -d $IPADDR $UNPRIVPORTS -j ACCEPT

> Damit die Bastion aber auch ankommende Aufträge aus der DMZ akzeptieren kann, bedarf es noch eines weiteren Regelsatzes für das Bastion-Script:

>       # Bastion nimmt SMTP Anfragen aus der DMZ entgegen
>       ipchains -A input -i $BASTION_DMZ_INTERFACE -p tcp \
>                -s $DMZ_ADDRESSES $UNPRIVPORTS \
>                -d $BASTION_DMZ_IPADDR 25 -j ACCEPT
>       ipchains -A output -i $BASTION_DMZ_INTERFACE -p tcp ! -y \
>                -s $BASTION_DMZ_IPADDR 25 \
>                -d $DMZ_ADDRESSES $UNPRIVPORTS -j ACCEPT

> Jetzt müssen wir aber noch der Choke erlauben, SMTP-Pakete an die Bastion durchzulassen. In das Choke Script muß folglich eingetragen werden:

>       # Choke erlaubt SMTP-Pakete an die Bastion
>       ipchains -A output -i $CHOKE_DMZ_INTERFACE -p tcp\
>                -s CHOKE_DMZ_IPADDR $UNPRIVPORTS \
>                -d $BASTION_DMZ_IPADDR 25 -j ACCEPT
>       ipchains -A input -i $CHOKE_DMZ_INTERFACE -p tcp ! -y\
>                -s $BASTION_DMZ_IPADDR 25 \
>                -d CHOKE_DMZ_IPADDR $UNPRIVPORTS -j ACCEPT

> Damit sollte der Versand von E-Mail auch für die Rechner im LAN möglich sein.

> ## Mailempfang über POP-Server auf der Bastion

> Die Rechner des LAN holen ihre Mails direkt bei der Bastion ab. Das geschieht mit dem POP3 Protokoll (TCP 110). Die Bastion muß nur Pakete aus der DMZ durchlassen, aus dem Internet ist dieser Service nicht verfügbar. Das Bastion-Script bekommt also noch die Regeln:

>       # POP-Server der Bastion nimmt Pakete aus der DMZ entgegen
>       ipchains -A input -i $BASTION_DMZ_INTERFACE -p tcp \
>                -s $CHOKE_DMZ_IPADDR $UNPRIVPORTS \
>                -d $BASTION_DMZ_IPADDR 110 -j ACCEPT
>       ipchains -A output -i $BASTION_DMZ_INTERFACE -p tcp ! -y \
>                -s $BASTION_DMZ_IPADDR 110 \
>                -d $CHOKE_DMZ_IPADDR $UNPRIVPORTS -j ACCEPT

> Natürlich muß jetzt auch wieder die Choke noch soweit konfiguriert werden, daß sie Pakete durchlässt, die an die Bastion gerichtet sind. Das Choke-Script wird um die folgenden Regeln erweitert:

>       # POP3 Pakete an die Bastion werden weitergegeben:
>       ipchains -A output -i $CHOKE_DMZ_INTERFACE -p tcp \
>                -s $CHOKE_DMZ_IPADDR $UNPRIVPORTS \
>                -d $BASTION_DMZ_IPADDR 110 -j ACCEPT
>       ipchains -A input -i $CHOKE_DMZ_INTERFACE -p tcp ! -y \
>                -s $BASTION_DMZ_IPADDR 110 \
>                -d $CHOKE_DMZ_IPADDR $UNPRIVPORTS -j ACCEPT

> # Alle weiteren Dienste

> Damit wir hier jetzt nicht jeden denkbaren Internet-Dienst in epischer Breite darstellen müssen, hier noch ein paar allgemeingültige Tips zum Aufbau der einzelnen Regeln.

> Der grundsätzliche Aufbau der Regeln ist immer gleich, die Bastion erlaubt bestimmte Pakete, die Choke erlaubt die selben Pakete. Aber während die Bastion die Pakete auf ihre interne Schnittstelle erlaubt, tut die Choke es auf die externe. Man könnte fast von einer Art Achsensymetrie sprechen, die Achse wäre in dem Fall die DMZ.

> Um die richtigen Regeln für einen bestimmten Dienst zu erstellen, ist es notwendig, ein Protokoll hinlänglich zu verstehen. Dazu können die im Anhang aufgeführten Protokollbeschreibungen dienen. Diese Beschreibungen sind selbstverständlich nicht vollständig, das würde den Rahmen der Darstellung sprengen. Genauere Details können in den jeweiligen HOWTOS, den RFCs und anderen Informationsquellen entnommen werden. Trotzdem sollte nach der Durcharbeitung der letzten Abschnitte genügend Verständnis für eigene Weiterentwicklungen vorhanden sein.

> # LAN Zugriff auf die Choke

> Bei allen Regeln, die wir in den letzten Abschnitten aufgestellt haben, haben wir eine Kleinigkeit einfach weggelassen. Wir haben zwar der Choke jeweils Regeln gegeben, die bestimmten Paketen erlauben, an die Bastion weitergeleitet zu werden, wir haben aber der Choke niemals eine Regel gegeben, die überhaupt Pakete aus dem LAN entgegennehmen würde.

> In der Regel stellt es kein Sicherheitsproblem dar, wenn die Choke alle Pakete aus dem zu schützenden Netz (LAN) akzeptiert, damit sparen wir uns eine Menge zusätzlicher Regeln, wenn wir das pauschal für die Choke formulieren:

>       # Vollständige Öffnung der Kommunikation zwischen LAN und Choke
>       ipchains -A input -i $CHOKE_LAN_INTERFACE \
>                -s $LAN_ADDRESSES -j ACCEPT
>       ipchains -A output  -i $CHOKE_LAN_INTERFACE \
>                -d $LAN_ADDRESSES -j ACCEPT

> # Und schließlich das Masquerading

> Bis zu diesem Punkt der Darstellung haben weder die Bastion, noch die Choke tatsächlich Pakete maskiert, aus diesem Grund hätte auch ein Datenverkehr mit dem Internet bis jetzt noch nicht funktionieren können. In unserer DMZ und im LAN arbeiten wir ja mit reservierten Adressen. (Auch wenn es in der Praxus wenig Sinn macht, die DMZ wäre ja so von außen nicht ansprechbar)

> Der erste Schritt ist jetzt also der, daß wir die Bastion zum Masquerading-Server erklären, der alle Pakete, die von der Choke kommen, auf seine echte Internet-Adresse maskiert. Das gesammte Netz wird so zum Internet komplett versteckt.

>       # Bastion maskiert alle Pakete der Choke
>       ipchains -A forward -i $EXTERNAL_INTERFACE \
>                -s $CHOKE_DMZ_IPADDRESS -j MASQ

> Damit jetzt aber auch alle Pakete aus dem LAN unter der Adresse der Choke an die Bastion gehen, müssen wir auch die Choke als Masquerading Server konfigurieren, die jetzt alle Pakete aus dem LAN mit ihrer DMZ-Adresse maskiert. Das bietet auch eine doppelte Sicherheit, denn innerhalb der DMZ ist damit das LAN unsichtbar, es existiert nur noch die Choke:

>       # Choke maskiert alle Pakete des LAN
>       ipchains -A forward -i $CHOKE_DMZ_INTERFACE \
>                -s $LAN_ADDRESSES -j MASQ

> Nächste Seite: Wichtige Portnummern Aufwärts: Crashkurs Firewallaufbau unter Linux Vorherige Seite: Die Firewall als Router Inhalt