Network Address Translation (NAT) ist ein Weg, um ein gesamtes
Netzwerk (oder Netzwerke) einer einzigen IP-Adresse zuzuweisen.
NAT ist notwendig, wenn du mehr Rechner besitzt, denen du
Internetzugriff ermöglichen möchtest, als dir dein Internetanbieter
IP-Adressen bereitgestellt hat. Im
RFC 1631
»The IP Network Address Translator (NAT)« wird NAT beschrieben.
NAT erlaubt dir den Vorteil der reservierten Adressblöcke zu
nutzen, wie sie in
RFC 1918
»Address Allocation for Private Internets« beschrieben werden.
Normalerweise wird dein internes Netzwerk so eingerichtet sein, dass
einer dieser Netzwerkblöcke verwendet wird. Diese sind:
10.0.0.0/8 (10.0.0.0 - 10.255.255.255)
172.16.0.0/12 (172.16.0.0 - 172.31.255.255)
192.168.0.0/16 (192.168.0.0 - 192.168.255.255)
Ein OpenBSD-System, das NAT durchführt, muss mindestens zwei
Netzwerkadapter besitzen: einen in Richtung Internet und die anderen
in Richtung internes Netzwerk. NAT wird die Anfragen vom internen
Netzwerk so übersetzen, dass sie so wirken, als wenn sie alle vom
OpenBSD-NAT-System kommen würden.
Wie NAT funktioniert
Wenn ein Client im internen Netzwerk eine Maschine im Internet
kontaktiert, sendet er IP-Pakete, die für diese Maschine bestimmt
sind. Diese Pakete beinhalten alle Adressinformationen, die benötigt
werden, um am Ziel anzukommen. NAT befasst sich mit diesen
Informationen:
Quell-IP-Adresse (zum Beispiel 192.168.1.35)
Quell-TCP- oder -UDP-Port (zum Beispiel 2132)
Wenn das Paket durch das NAT-Gateway gesendet wird, wird es so
modifiziert, dass es wirkt, als wenn es vom NAT-Gateway geschickt
worden wäre. Das NAT-Gateway wird sich die Änderungen in der
Statustabelle merken, sodass es a) die Änderungen für die
Antwortpakete wieder rückgängig machen kann und b) sicherstellen kann,
dass die Antwortpakete durch die Firewall gelassen und nicht geblockt
werden. Zum Beispiel können die folgenden Änderungen durchgeführt
werden:
Quell-IP: ersetzt mit der externen Adresse des Gateways
(zum Beispiel 24.5.0.5)
Quell-Port: ersetzt mit einem zufällig gewählten, unbenutzen Port
des Gateways (zum Beispiel 53136)
Weder die interne Maschine noch der Internethost wissen etwas von
diesen Übersetzungsschritten. Für die interne Maschine ist das
NAT-System einfach ein Internetgateway. Für den Internethost
scheinen die Pakete vom NAT-System direkt zu kommen; er weiß noch
nicht einmal, dass die interne Workstation überhaupt existiert.
Wenn der Internethost auf die Pakete der internen Maschine antwortet,
werden sie an die externe IP des NAT-Gateways (24.5.0.5) und den
Übersetzungsport (53136) gerichtet sein. Das NAT-Gateway durchsucht dann
die Statustabelle, ob die Antwortpakete zu einer bereits erstellten
Verbindung gehören. Ein einzigartiger Treffer (basierend auf der
IP/Port-Kombination) wird gefunden, der PF mitteilt, dass die
Pakete zu einer Verbindung gehören, die von der internen Maschine
192.168.1.35 eröffnet wurde. PF wird dann die entgegengesetzten
Änderungen, die an den gesendeten Paketen gemacht worden sind,
vornehmen und die Antwortpakete an die interne Maschine weiterleiten.
Die Übersetzung von ICMP-Paketen findet auf eine ähnliche Art und Weise
statt, aber ohne der Quellport-Modifizierung.
NAT und das Filtern von Paketen
HINWEIS: Übersetzte Pakete müssen weiterhin
die Filterengine durchlaufen und werden geblockt oder durchgelassen -
jenachdem, welche Filterregeln definiert wurden.
Die einzige Ausnahme zu dieser Regel ist, wenn das
pass-Schlüsselwort innerhalb der nat-Regel verwendet
wird. Dies hat zur Folge, dass NAT-Pakete direkt durch die Filterengine
gelassen werden.
Sei dir ebenfalls bewusst, dass - da die Übersetzung vor dem
Filtern stattfindet - die Filterengine die übersetzten Pakete
mit den übersetzten IP-Adressen und Ports sehen wird, wie es in
Wie NAT funktioniert beschrieben wurde.
IP-Weiterleitung
Da NAT fast ausschließlich auf Routern und Netzwerkgateways verwendet
wird, ist es wahrscheinlich notwendig, IP-Weiterleitung zu aktivieren,
sodass die Pakete zwischen den Netzwerkinterfaces der OpenBSD-Maschine
ausgetauscht werden können. IP-Weiterleitung wird über den
sysctl(3)-Mechanismus aktiviert:
# sysctl net.inet.ip.forwarding=1
# sysctl net.inet6.ip6.forwarding=1 (wenn IPv6 verwendet wird)
Um diese Änderungen dauerhaft zu machen, sollten die folgenden
Zeilen in die
/etc/sysctl.conf eingetragen werden:
Diese Zeilen sind zwar in der Standardinstallation bereits vorhanden,
aber auskommentiert (vor ihnen steht eine Raute #).
Entferne die # und speicher die Datei. IP-Weiterleitung
wird aktiviert, wenn die Maschine neustartet.
NAT konfigurieren
Das generelle Format der NAT-Regeln in pf.conf sieht so
ähnlich aus wie folgt:
nat [pass [log] on interface [af] from src_addr
[port src_port] to \ dst_addr [port dst_port] ->
ext_addr [pool_type] [static-port]
nat
Das Schlüsselwort, das eine NAT-Regel einleitet.
pass
Sorgt dafür, dass übersetzte Pakete komplett von den Filterregeln
unbeachtet bleiben.
log
Zeichne zutreffende Pakete mittels
pflogd(8) auf.
Normalerweise wird nur das erste
zutreffende Paket aufgezeichnet. Damit alle Pakete protokolliert
werden verwende log (all).
interface
Der Name des Netzwerkinterfaces, auf dem die Pakete übersetzt
werden sollen.
af
Die Adressfamilie: inet für IPv4 oder inet6
für IPv6. PF ist normalerweise in der Lage, das selbst anhand der
Quell/Ziel-Adresse(n) herauszufinden.
src_addr
Die (interne) Quelladresse der Pakete, die übersetzt werden
sollen.
Die Quelladresse kann wie folgt angegeben werden:
Ein »fully qualified domain name«, der per DNS aufgelöst werden
kann, wenn der Regelsatz geladen wird. Alle resultierenden IP-Adressen
werden in die Regel eingesetzt.
Der Name oder die Gruppe eines Netzwerkinterfaces. Jegliche
IP-Adressen, die dem Interface zugeordnet worden sind, werden in die
Regel zur Ladezeit eingesetzt.
Der Name eines Netzwerkinterfaces, gefolgt von
/netmask (z. B. /24). Jede IP-Adresse auf
dem Interface wird mit der Netzmaske kombiniert, um einen
CIDR-Netzwerkblock zu bilden, der in die Regel eingesetzt wird.
Der Name oder die Gruppe eines Netzwerkinterfaces, gefolgt von einem
dieser Modifizierer:
:network - fügt den CIDR-Netzwerkblock ein (z. B.
192.168.0.0/24)
:broadcast - fügt die Netzwerkbroadcastadresse ein
(z. B. 192.168.0.255)
:peer - fügt die IP-Adresse eines Peers von einem
Point-to-Point-Link ein
Zusätzlich kann der :0-Modifizierer einem
Interfacenamen/der Interfacegruppe oder einem der vorher genannten
Modifizierer angehängt werden, um PF mitzuteilen, dass keine
IP-Adressaliase mit eingefügt werden sollen. Diese Modifizierer können
ebenfalls verwendet werden, wenn das Interface sich in Klammern
befindet. Beispiel: fxp0:network:0
Die letzten beiden sind Binäroperatoren (sie nehmen zwei
Argumente) und fügen diese Argumente nicht mit in den Bereich
ein.
: (inklusiver Bereich)
Der Operator für den inklusiven Bereich ist ebenfalls ein
Binäroperator und fügt die Argumente mit in den Bereich ein.
Die port-Option wird normalerweise nicht in nat-Regeln
verwendet, da das Ziel normalerweise ist, NAT auf den Verkehr
auszuüben - unabhängig davon, welche Ports verwendet werden.
dst_addr
Die Zieladresse der Pakete, die übersetzt werden sollen. Die
Zieladresse wird genauso wie die Quelladresse angegeben.
dst_port
Der Zielport im Layer-4-Paketheader. Dieser Port wird genauso
wie der Quellport angegeben.
ext_addr
Die externe (Übersetzungs-)Adresse des NAT-Gateways, die die
übersetzten Pakete annehmen soll. Die externe Adresse kann wie folgt
angegeben werden:
Ein »fully qualified domain name«, der per DNS aufgelöst werden
kann, wenn der Regelsatz geladen wird. Alle resultierenden IP-Adressen
werden in die Regel eingesetzt.
Der Name des externen Netzwerkinterfaces. Jegliche IP-Adressen, die
dem Interface zugeordnet worden sind, werden in die Regel zur Ladezeit
eingesetzt.
Der Name des externen Netzwerkinterfaces in Klammern ( ).
Dies teil PF mit, dass die Regel neugeladen werden soll, wenn die
IP-Adresse(n) des genannten Interfaces sich über DHCP oder dial-up
ändern. Somit mus der Regelsatz nicht immer neugeladen werden, wenn sich
die Adresse ändert.
Der Name eines Netzwerkinterfaces, gefolgt von einem dieser
Modifizierer:
:network - fügt den CIDR-Netzwerkblock ein (z. B.
192.168.0.0/24)
:peer - fügt die IP-Adresse eines Peers von einem
Point-to-Point-Link ein
Zusätzlich kann der :0-Modifizierer einem Interfacenamen
oder einem der vorher genannten Modifizierer angehängt werden, um
PF mitzuteilen, dass keine IP-Adressaliase mit eingefügt werden
sollen. Diese Modifizierer können ebenfalls verwendet werden, wenn
das Interface sich in Klammern befindet.
Beispiel: fxp0:network:0
Ein Satz an Adressen unter Verwendung einer
Liste.
pool_type
Gibt den Typ des Adresspools an, der
für die Übersetzung verwendet werden soll.
static-port
Teilt PF mit, den Quellport in TCP- und UDP-Paketen nicht zu
verändern.
Dies würde zu der einfachsten Form einer Zeile führen, die dieser
ähnlich sein würde:
nat on tl0 from 192.168.1.0/24 to any -> 24.5.0.5
Diese Regel besagt, dass NAT auf dem tl0-Interface für
alle Pakete ausgeführt werden soll, die von 192.168.1.0./24 aus kommen,
und sie mit der Quell-IP-Adresse von 24.5.0.5 übersetzt werden sollen.
Während die vorher genannte Regel korrekt ist, ist es keine empfohlene
Form. Die Verwaltung könnte schwierig sein, da jegliche Änderung an
den internen oder externen Netzwerknummern eine Änderung der Zeile
zur Folge hätte. Vergleiche sie stattdessen mit dieser einfacher zu
verwaltenen Zeile (tl0 ist extern, dc0 intern):
nat on tl0 from dc0:network to any -> tl0
Der Vorteil sollte recht klar sein: du kannst die IP-Adressen von
einem der Interfaces ändern, ohne die Regeln ändern zu müssen.
Wenn ein Interfacename für die Übersetzungsadresse wie zuvor
angegeben wird, wird die IP-Adresse zur Ladezeit von pf.conf
ermittelt - nicht während der Verwendung! Wenn du DHCP verwendest, um
dein externes Interface zu konfigurieren, kann dies zu einem Problem
werden. Wenn deine zugewiesene IP-Adresse sich ändert, wird NAT
weiterhin die hinausgehenden Pakete mit der alten IP-Adresse übersetzen.
Dies wird dazu führen, dass ausgehende Verbindungen nicht mehr
funktionieren werden. Um dies zu umgehen, kannst du PF sagen, dass die
Übersetzungsadresse automatisch aktualisiert werden soll, indem
Klammern um den Interfacenamen herum gesetzt werden:
nat on tl0 from dc0:network to any -> (tl0)
Diese Methode funktioniert für Übersetzungen von IPv4- und
IPv6-Adressen.
Bidirektionales Mapping (1:1 mapping)
Ein bidirektionales Mapping kann durch die Verwendung der
binat-Regel aufgebaut werden. Eine binat-Regel
erzeugt ein Eins-zu-eins-Mapping zwischen einer internen und einer
externen IP-Adresse. Dies kann sinnvoll sein, wenn beispielsweise
ein Webserver aus dem internen Netzwerk mit seiner eigenen externen
Adresse bereitgestellt werden soll. Verbindungen aus dem Internet
zur externen Adresse werden dann zur internen Adresse übersetzt und
Verbindungen vom Webserver (zum Beispiel DNS-Anfragen) werden mit
der externen Adresse übersetzt. TCP- und UDP-Ports werden niemals
mit binat-Regeln modifiziert wie es mit nat-Regeln
der Fall ist.
binat on tl0 from $web_serv_int to any -> $web_serv_ext
Übersetzungsregel-Ausnahmen
Ausnahmen bei den Übersetzungsregeln können unter Verwendung des
no-Schlüsselwortes gemacht werden. Wenn zum Beispiel das
vorherige NAT-Beispiel so modifiziert wurde, dass es nun wie folgt
aussieht:
no nat on tl0 from 192.168.1.208 to any
nat on tl0 from 192.168.1.0/24 to any -> 24.2.74.79
Dann werden für das gesamte 192.168.1.0/24-Netzwerk alle Pakete
zur externen Adresse 24.2.74.79 übersetzt, nur nicht für 192.168.1.208.
Bedenke, dass die erste zutreffende Regel gewinnt; wenn es eine
no-Regel ist, dann wird das Paket nicht übersetzt. Das
no-Schlüsselwort kann ebenfalls mit binat-
und rdr-Regeln verwendet werden.
Den NAT-Status abfragen
Um die aktiven NAT-Übersetzungen zu betrachten, wird
pfctl(8) mit der Option -s state verwendet. Diese Option
wird alle momentanten NAT-Sitzungen auflisten:
# pfctl -s state
fxp0 TCP 192.168.1.35:2132 -> 24.5.0.5:53136 -> 65.42.33.245:22 TIME_WAIT:TIME_WAIT
fxp0 UDP 192.168.1.35:2491 -> 24.5.0.5:60527 -> 24.2.68.33:53 MULTIPLE:SINGLE
Erklärungen (nur die erste Zeile):
fxp0
Gibt das Interface an, an welches der Status gebunden ist. Das Wort
self wird erscheinen, wenn der Status
»floating«« ist.
TCP
Das Protokoll, das von der Verbindung genutzt wird.
192.168.1.35:2132
Die IP-Adresse (192.168.1.35) der Maschine im internen Netzwerk.
Der Quellport (2132) wird nach der Adresse angezeigt. Dies ist ebenfalls
die Adresse, die im IP-Header ersetzt wird.
24.5.0.5:53136
Die IP-Adresse (24.5.0.5) und Port (53136) vom Gateway, mit denen
die Pakete übersetzt werden.
65.42.33.245:22
Die IP-Adresse (65.42.33.245) und der Port (22), mit denen die
interne Maschine verbunden ist.
TIME_WAIT:TIME_WAIT
Dies gibt an, was PF glaubt, zu welchem Status die TCP-Verbindung
gehört.