[OpenBSD]

[Zurück: Network Address Translation] [Inhalt] [Weiter: Abkürzungen zum Erzeugen von Regelsätzen]

PF: Umleitung (Port-Weiterleitung)


Inhaltsverzeichnis


Einführung

Wenn du NAT in deinem Büro einsetzt, steht dir das gesamte Internet für alle Maschinen zur Verfügung. Was aber, wenn du eine Maschine hinter einem NAT-Gateway hast, das von außen zugreifbar sein muss? Das ist der Punkt, an dem die Weiterleitung ins Spiel kommt. Weiterleitung erlaubt es eingehendem Verkehr, zu einer Maschine gesendet zu werden, die hinter dem NAT-Gateway ist.

Lass uns ein Beispiel betrachten:

rdr on tl0 proto tcp from any to any port 80 -> 192.168.1.20

Diese Zeile leitet TCP-Port-80- (Webserver) Verkehr zu einer Maschine im Netzwerk mit der IP 192.168.1.20 um. Obwohl sich 192.168.1.20 hinter deinem Gateway und in deinem Netzwerk befindet, kann die Außenwelt darauf zugreifen.

Der from any to any-Teil der oben angegebenen rdr-Zeile kann recht nützlich sein. Wenn du weißt, welche Adresse oder Subnetze berechtigt sind, Zugriff auf den Webserver auf dem Port 80 zu haben, kannst du sie hier einschränken:

rdr on tl0 proto tcp from 27.146.49.0/24 to any port 80 -> \
   192.168.1.20

Dies wird nur die angegebenen Subnetze umleiten. Bedenke, dass dies beinhaltet, dass du verschiedene Hosts, die Anfragen senden, zu verschiedenen Maschinen hinter deinem Gateway umleiten kannst. Du könntest zum Beispiel Benutzer an einer entfernten Stelle haben und ihnen Zugriff auf ihre eigenen Desktop-Computer unter Verwendung des gleichen Ports und der gleichen IP-Adresse auf dem Gateway ermöglichen, so lange du die IP-Adresse kennst, von der aus sie sich verbinden werden:

rdr on tl0 proto tcp from 27.146.49.14 to any port 80 -> \
   192.168.1.20
rdr on tl0 proto tcp from 16.114.4.89 to any port 80 -> \
   192.168.1.22
rdr on tl0 proto tcp from 24.2.74.178 to any port 80 -> \
   192.168.1.23

Ein Portbereich kann ebenfalls mit ein- und derselben Regel umgeleitet werden:

rdr on tl0 proto tcp from any to any port 5000:5500 -> \
   192.168.1.20
rdr on tl0 proto tcp from any to any port 5000:5500 -> \
   192.168.1.20 port 6000
rdr on tl0 proto tcp from any to any port 5000:5500 -> \
   192.168.1.20 port 7000:*

Diese Beispiele zeigen, dass die Ports 5000 bis einschließlich 5500 zu 192.168.1.20 umgeleitet werden. In Regel #1 wird der Port 5000 auf 5000 umgeleitet, 5001 auf 5001 etc. In Regel #2 wird der gesamte Portbereich auf den Port 6000 geleitet. Und in Regel #3 wird der Port 5000 auf 7000 umgeleitet, 5001 auf 7001 etc.

Umleitung und Paket-Filterung

HINWEIS: Übersetzte Pakete müssen weiterhin durch die Filter-Engine gelassen werden und werden geblockt oder durchgelassen, jenachdem, wie du die Filterregeln definiert hast.

Die einzige Ausnahme zu dieser Regel ist, wenn das pass-Schlüsselwort innerhalb der rdr-Regel eingesetzt wird. In diesem Fall werden die umgeleiteten Pakete direkt ,statefully' durch die Filter-Engine gelassen: die Filterregeln werden für diese Pakete nicht überprüft. Dies ist eine praktische Abkürzung, um das Hinzufügen von pass-Filterregeln für jede Umleitungsregel zu verhindern. Stell sie dir wie eine normale rdr-Regel vor (mit keinem pass-Schlüsselwort), in Verbindung gebracht mit einer pass-Filterregel mit dem keep state-Schlüsselwort. Wenn du jedoch spezifischere Filter-Optionen wie zum Beispiel synproxy, modulate state etc. aktivieren möchtest, musst du weiterhin eine dafür gewidmete pass-Regel verwenden, da diese Optionen nicht in Umleitungsregeln eingesetzt werden können.

Sei dir ebenfalls bewusst, dass, da die Übersetzung vor dem Filtern stattfindet, die Filter-Engine die übersetzten Pakete sehen wird, so wie sie nach der Änderung der Ziel-IP-Adresse und/oder des Ziel-Ports aussehen, um eine Übereinstimmung mit der angegeben umgeleiteten Adresse (und dem Port) in der rdr-Regel zu finden. Betrachte dieses Szenario:

Umleitungsregel:

rdr on tl0 proto tcp from 192.0.2.1 to 24.65.1.13 port 80 \
   -> 192.168.1.5 port 8000

Pakete, bevor die rdr-Regel verarbeitet wurde:

Pakete, nachdem die rdr-Regel verarbeitet wurde:

Die Filter-Engine wird die IP-Pakete so sehen, wie sie nach der Übersetzung aussehen.

Auswirkungen auf die Sicherheit

Die Umleitung hat Auswirkungen auf die Sicherheit. Ein Loch in die Firewall schlagen, um Verkehr in das interne, beschützte Netzwerk zu lassen, eröffnet den internen Maschinen potenziell die Möglichkeit, kompromittiert zu werden. Wenn der Verkehr zum Beispiel zum Webserver-Daemon weitergeleitet wird, und eine Sicherheitslücke im Webserver-Daemon oder in einem CGI-Skript gefunden wird, die auf dem Webserver laufen, kann die Maschine von einem Eindringling aus dem Internet kompromittiert werden. Von da an wird der Eindringling eine Hintertür zum internen Netzwerk haben, eine, die es ihm ermöglicht, direkt hinter die Firewall zu gelangen.

Diese Gefahren können minimiert werden, indem das extern zugreifbare System strikt in ein separates Netzwerk eingegrenzt wird. Dieses Netzwerk wird of auch als demilitarisierte Zone (DMZ) oder als ,Private Service Network' (PSN) bezeichnet. Wenn auf diesem Weg ein Webserver kompromittiert wird, kann der Effekt auf das DMZ/PSN-Netzwerk begrenzt werden, unter sorgfältigem Filtern des Verkehrs, der zum und vom DMZ/PSN gelassen wird.

Umleitung und Reflektion

Oftmals werden Umleitungsregeln verwendet, um eingehende Verbindungen vom Internet zu einem lokalen Server mit einer privaten Adresse in dem internen Netzwerk oder LAN weiterzuleiten, wie es hier getan wird:
server = 192.168.1.40

rdr on $ext_if proto tcp from any to $ext_if port 80 -> $server \
   port 80

Aber wenn die Umleitungsregel von einem Client im LAN getestet wird, funktioniert es nicht. Der Grund ist, dass Umleitungsregeln nur für Pakete gelten, die durch das angegebene Interface (in diesem Beispiel $ext_if, das externe Interface) geschickt werden. Sich auf die externe Adresse der Firewall von einem Host im LAN aus zu verbinden, heißt nicht, dass die Pakete auch tatsächlich durch das externe Interface gehen werden. Der TCP-IP-,stack' der Firewall vergleicht die Ziel-Adresse der eingehenden Pakete mit seinen eigenen Adressen und Aliasen und entdeckt Verbindungen, die an ihn selbst gerichtet sind, sobald sie das interne Interface passieren. Solche Pakete werden nicht physikalisch durch das externe Interface geleitet und der ,stack' simuliert auch kein derartiges Durchsenden. Daher sieht PF niemals diese Pakete auf dem externen Interface und die Umleitungsregel, die das externe Interface angibt, wird nicht zutreffen.

Eine zweite Umleitungsregel für das interne Interface anzulegen, wird auch nicht den gewünschten Effekt haben. Wenn der lokale Client sich auf die externe Adresse der Firewall verbindet, erreicht das erste Paket des TCP-Handschlags die Firewall durch das interne Interface. Die Umleitungsregel trifft zu und die Ziel-Adresse wird mit der Adresse des internen Servers ausgewechselt. Das Paket wird zurück durch das interne Interface weitergeleitet und erreicht den internen Server. Aber die Quell-Adresse wurde nicht übersetzt und enthält weiterhin die Adresse vom lokalen Client, sodass der Server seine Antworten direkt zum Client sendet. Die Firewall wird niemals die Antwort sehen und hat keine Möglichkeit, die Übersetzung erfolgreich umzukehren. Der Client erhält eine Antwort von einer Quelle, die er nicht erwartet hat, und lässt sie somit fallen. Der TCP-Handschlag schlägt fehl und keine Verbindung kann aufgebaut werden.

Es ist aber oftmals durchaus für Clients im LAN erwünscht, auf den gleichen internen Server wie externe Clients zuzugreifen, und das auch transparent. Es gibt einige Lösungen für diese Problem:

Split-Horizon DNS

Es ist möglich, DNS-Server so zu konfigurieren, dass Anfragen von lokalen Hosts anders beantwortet werden als externe Anfragen, sodass Clients die interne Server-Adresse während der Namensauflösung erhalten. Sie werden dann direkt auf den lokalen Server zugreifen und die Firewall wird überhaupt nicht miteinbezogen. Dies reduziert den lokalen Verkehr, da Pakete nicht durch die Firewall gesendet werden müssen.

Den Server in ein separates lokales Netzwerk verschieben

Das Hinzufügen eines zusätzlichen Netzwerk-Interfaces zur Firewall und das Verschieben des lokalen Servers vom Client-Netzwerk in ein dafür gewidmetes Netzwerk (DMZ) erlaubt das Umleiten der Verbindungen von lokalen Clients auf die gleiche Art und Weise wie das Umleiten von externen Verbindungen. Das Verwenden von separaten Netzwerken hat einige Vorteile, einschließlich der Erhöhung der Sicherheit, indem die Server von den übrigen lokalen Hosts getrennt werden. Sollte der Server (welcher in unserem Fall vom Internet aus erreichbar ist) jemals kompromittiert werden, kann er nicht direkt auf andere Hosts zugreifen, da alle Verbindungen durch die Firewall gelassen werden müssen.

TCP-Proxying

Ein genereller TCP-Proxy kann auf der Firewall eingerichtet werden, entweder so, dass er auf dem Port lauscht, der weitergeleitet werden soll, oder so, dass Verbindungen vom internen Interface zum Port weitergeleitet werden, auf dem er lauscht. Wenn ein lokaler Client sich zur Firewall verbindet, akzeptiert der Proxy die Verbindung, erstellt eine zweite Verbindung zum internen Server und leitet Daten zwischen diesen beiden Verbindungen weiter.

Einfache Proxies können unter der Verwendung von inetd(8) und nc(1) errichtet werden. Der folgende /etc/inetd.conf-Eintrag erstellt ein lauschendes Socket, das auf die Loopback-Adresse (127.0.0.1) und den Port 5000 gebunden ist. Verbindungen werden zum Port 80 auf dem Server 192.168.1.10 weitergeleitet.

127.0.0.1:5000 stream tcp nowait nobody /usr/bin/nc nc -w \
   20 192.168.1.10 80

Die folgende Umleitungsregel leitet den Port 80 vom internen Interface zum Proxy:

rdr on $int_if proto tcp from $int_net to $ext_if port 80 -> \
   127.0.0.1 port 5000

RDR- und NAT-Kombination

Mit einer zusätzlichen NAT-Regel auf dem internen Interface kann die fehlende Adress-Übersetzung erzielt werden, die oben beschrieben wurde.

rdr on $int_if proto tcp from $int_net to $ext_if port 80 -> \
   $server
no nat on $int_if proto tcp from $int_if to $int_net
nat on $int_if proto tcp from $int_net to $server port 80 -> \
   $int_if

Dies wird veranlassen, dass das erste Paket vom Client wieder übersetzt wird, wenn es wieder durch das interne Interface zurückgeleitet wird und damit die Quell-Adresse vom Client mit der internen Adresse der Firewall ausgetauscht wird. Der interne Server wird der Firewall antworten, welche die beiden NAT- und RDR-Übersetzungen rückgängig machen kann, wenn sie zum lokalen Client weiterleitet. Diese Konstrukt ist recht komplex, da es zwei separate ,states' für jede reflektierende Verbindung erzeugt. Es muss darauf geachtet werden, die NAT-Regel davon abzuhalten, auch für anderen Verkehr zuzutreffen, zum Beispiel für Verbindungen von externen Hosts (durch andere Umleitungen) oder der Firewall selbst. Bedenke, dass die oben angegebene rdr-Regel den TCP/IP-,stack' veranlasst, ankommende Pakete auf dem internen Interface mit einer Ziel-Adresse innerhalb des internen Netzwerks zu sehen.

Im Allgemeinen sollten die zuvor angegebenen Lösungen stattdessen verwendet werden.

[Zurück: Network Address Translation] [Inhalt] [Weiter: Abkürzungen zum Erzeugen von Regelsätzen]


[zurück] www@openbsd.org
$OpenBSD: rdr.html,v 1.15 2007/11/12 20:29:59 saad Exp $