Wie entscheidet NAT, welche Verbindungen eingehen und welche ausgehen?


7

Ich erstelle eine P2P-Anwendung, die auf Knoten hinter einem NAT zugreifen muss. Dieses NAT erlaubt keine eingehenden Verbindungen, daher können die Knoten außerhalb des Netzwerks die Knoten hinter dem NAT nicht erreichen.

Meine Lösung für dieses Problem besteht darin, dass der Knoten hinter dem NAT den Knoten außerhalb erreicht und der Knoten außerhalb, wenn die Zeit abgelaufen ist, über diese zuvor hergestellte TCP-Verbindung eine Verbindung zu dem Knoten innerhalb des NAT herstellt. Da diese Verbindung vom Knoten innerhalb des NAT hergestellt würde, würde dies vom NAT nicht blockiert.

Hier ist meine Frage. Ich weiß nicht, welche der unterstrichenen Interpretationen richtig sind oder ob beide falsch sind.

Interpretation # 1

Es gibt ein Konzept für eine TCP-Verbindung, effektiv eine Röhre, und wenn ein Knoten innerhalb des NAT eine Anfrage an irgendetwas in der Außenwelt stellt, wird diese Röhre geöffnet, die Antwort wird in sie eingefügt und die Röhre wird für immer geschlossen.

Ergebnis: Das NAT erlaubt keine weiteren TCP-Verbindungen zum Client vom Knoten außerhalb, nachdem diese Röhre geschlossen wurde.

Interpretation # 2

Es gibt keine TCP-Verbindung, sondern eine TCP-Übertragung. Da eine TCP-Verbindung als a definiert local ip:portist und a remote ip:port, nachdem ein Knoten hinter dem NAT einen Knoten außerhalb aufgerufen hat, kann der Knoten außerhalb über denselben Port zurückrufen, von dem aus der Client die Anforderung gestellt hat, und dies würde als dasselbe TCP "zählen" Verbindung, kein unaufgeforderter Anruf des NAT.

Ergebnis: Das NAT errät effektiv anhand des historischen Datensatzes, ob diese Verbindung eine Antwort auf die Anforderungen des Knotens im NAT war. Da der Knoten hinter dem NAT den ersten Aufruf getätigt hat, kann der Knoten außerhalb über denselben Client-Port zurückrufen, und es würde funktionieren.

Mein mentales Modell war näher an Nummer 1, aber als ich die Verbindungen mit Wireshark untersuchte, erschienen sie als separate TCP-Verbindungen oder zumindest als separate Einheiten.

Ist es näher an # 1 oder # 2 oder bin ich hoffnungslos verwirrt?


Vielleicht möchten Sie STUN und verwandte Arbeiten
nachschlagen

5
Ich empfehle dringend, dass Sie zuerst eine IPv6-Version Ihrer Anwendung implementieren, damit Sie sich nicht mit der Komplexität von NAT in der ersten Version auseinandersetzen müssen. Sobald Sie eine funktionierende Version für IPv6 haben, überlegen Sie, wie diese für IPv4 funktioniert.
Kasperd

Antworten:


9

TCP ist ein verbindungsorientiertes Protokoll und kann nur über Verbindungen kommunizieren.

Bevor Sie mit der Programmierung mit TCP beginnen, sollten Sie zunächst die Funktionsweise von TCP verstehen. Beginnen Sie mit RFC 793 (Transmission Control Protocol) , der Definition von TCP.

Der RFC erklärt Sockets und Verbindungen:

Multiplexing:

Damit viele Prozesse innerhalb eines einzelnen Hosts gleichzeitig TCP-Kommunikationsfunktionen verwenden können, stellt der TCP eine Reihe von Adressen oder Ports in jedem Host bereit. Verkettet mit den Netzwerk- und Hostadressen der Internetkommunikationsschicht bildet dies einen Socket. Ein Paar Sockets identifiziert jede Verbindung eindeutig. Das heißt, ein Socket kann gleichzeitig in mehreren Verbindungen verwendet werden.

Die Bindung von Ports an Prozesse wird von jedem Host unabhängig durchgeführt. Es erweist sich jedoch als nützlich, häufig verwendete Prozesse (z. B. einen "Logger" oder einen Timesharing-Dienst) an feste Sockets anzuhängen, die der Öffentlichkeit bekannt gemacht werden. Auf diese Dienste kann dann über die bekannten Adressen zugegriffen werden. Das Einrichten und Lernen der Portadressen anderer Prozesse kann dynamischere Mechanismen beinhalten.

Verbindungen:

Die oben beschriebenen Zuverlässigkeits- und Flusssteuerungsmechanismen erfordern, dass TCPs bestimmte Statusinformationen für jeden Datenstrom initialisieren und verwalten. Die Kombination dieser Informationen, einschließlich Sockets, Sequenznummern und Fenstergrößen, wird als Verbindung bezeichnet. Jede Verbindung wird durch ein Paar Sockets eindeutig gekennzeichnet, die ihre beiden Seiten identifizieren.

Wenn zwei Prozesse kommunizieren möchten, müssen ihre TCPs zuerst eine Verbindung herstellen (die Statusinformationen auf jeder Seite initialisieren). Wenn ihre Kommunikation abgeschlossen ist, wird die Verbindung beendet oder geschlossen, um die Ressourcen für andere Zwecke freizugeben.

Da Verbindungen zwischen unzuverlässigen Hosts und über das unzuverlässige Internetkommunikationssystem hergestellt werden müssen, wird ein Handshake-Mechanismus mit taktbasierten Sequenznummern verwendet, um eine fehlerhafte Initialisierung von Verbindungen zu vermeiden.

Der externe TCP-Peer stellt eine Verbindung zur externen Adresse des NAT-Geräts her, obwohl dieses Gerät basierend auf der vom internen Gerät initiierten Verbindung an den anderen TCP-Peer im Inneren weiterleitet.

Sie können auch RFC 5382, NAT-Verhaltensanforderungen für TCP, studieren .


7

Eine TCP-Verbindung gilt als "in Kraft", solange die Softwareprozesse an beiden Enden den Socket offen halten.

Wenn die Prozesse an einem oder beiden Enden den Socket schließen (entweder ordnungsgemäß oder die Verbindung wird aus irgendeinem Grund abgebrochen), wird dies auf der Leitung in ein TCP-Paket mit gesetztem FIN- oder RST-Flag übersetzt.

Die NAT-Implementierung auf dem NAT-Router sucht nach den FIN- und RST-Flags. Wenn sie ein Paket mit diesen Flags sieht, schließt sie das Loch. Nach diesem Punkt muss der Client eine neue Verbindung herstellen, um "ein neues Loch zu öffnen".

Zusammenfassend lässt sich sagen, dass die NAT-Zuordnung am Leben bleibt, solange Ihr Client und Ihr Server ihre Sockets offen halten.


4

Wenn ich hier von "normal" schreibe, denke ich an einen durchschnittlichen WLAN-NAT-Router für Endverbraucher mit einer vernünftigen Konfiguration oder an ein einfaches Linux-Netzwerk mit Standardeinstellungen. Dies kann wie üblich so komplex oder kompliziert wie nötig gestaltet werden. Da die Frage sehr einfach ist, scheint dies für mich am sinnvollsten zu sein, anstatt sich für kompliziertere NAT-Lösungen auf Unternehmensebene zu entscheiden.

Sie haben bereits eine Antwort akzeptiert, aber lassen Sie mich versuchen, die von Ihnen gestellte Frage direkt zu beantworten:

Wie entscheidet NAT, welche Verbindungen eingehen und welche ausgehen?

Die Grundlage für die Entscheidung (für jede Entscheidung in einem Router) ist ein Regelwerk in irgendeiner Form oder Weise. In diesem Fall hat der Administrator für jede der beteiligten Schnittstellen (dh die interne LAN-Schnittstelle im Vergleich zur externen WAN / Uplink-Schnittstelle) Regeln implementiert. Diese Regeln sind sehr unterschiedlich, dh die Regeln für eine LAN-Schnittstelle unterscheiden sich erheblich von denen einer WAN-Schnittstelle.

Zu wissen, woher ein Paket kommt und wohin es geht, ist das A und O dessen, was ein Router tut.

Lassen Sie mich mit einem beginnen

Beispiel

Die NAT-Seite von Wikipedia enthält viel Text zu diesem Thema, aber in einem einfachen Fall (ein einfaches Firmen-LAN im Vergleich zu einem einzelnen DSL-Uplink) passiert Folgendes:

  1. Der Client-PC versucht, eine HTTP-Verbindung zu einem internetbasierten Server herzustellen, z. B. 198.51.100.20. Der PC selbst hat eine nicht geroutete Adresse wie 192.0.2.2. Der billige DSL-Router verfügt über zwei Schnittstellen, eine interne (192.0.2.1) und eine externe (203.0.113.10), die sich sehr wahrscheinlich häufig ändern und vom DLS-Anbieter über ein lokales Verbindungsprotokoll bereitgestellt werden. Der PC sendet also ein SYN-Paket über sein Standard-Gateway, 192.0.2.1, an 198.51.100.20:80.
  2. Der Router nimmt das Paket an seiner Schnittstelle 192.0.2.1 auf, wie es auch der Fall wäre, wenn überhaupt kein NAT beteiligt wäre. Es wurde für NAT auf dieser Schnittstelle konfiguriert, daher werden die folgenden Schritte ausgeführt:
    • Erfinde eine neue Portnummer, die bisher nicht verwendet wurde. Zum Beispiel 12345.
    • Ändern Sie die "Absender" -Adresse im IP-Header in 203.0.113.10.
    • Merken Sie sich die ursprüngliche Absenderportnummer im TCP-Header (vom PC bereitgestellt). Nennen wir sie 4321.
    • Ändern Sie den TCP-Header so, dass er die 12345-Absenderportnummer enthält.
    • Fügen Sie einen Eintrag (12345; 192.0.2.2; 4321) in die NAT-Übersetzungstabelle ein.
    • Senden Sie das Paket auf seinem fröhlichen Weg an seinen eigenen Uplink / Gateway.
  3. 198.51.100.20 empfängt schließlich das Paket, stellt fest, dass es sich um eine SYN handelt ("neue Verbindung herstellen"), und sendet eine SYN-ACK-Nachricht an den Absender zurück. Aus seiner Sicht ist dies die IP-Adresse 203.0.113.10 mit dem TCP-Zielport 12345.
  4. Der Router empfängt dieses Paket über seine WAN-Schnittstelle. Die WAN-Schnittstelle wurde so konfiguriert, dass NATted-Adressen wie folgt aufgelöst werden. Der Router dann ...
    • ... überprüft seine NAT-Übersetzungstabelle, findet den Eintrag ...
    • ... ändert das Paket auf ein Ziel von 192.0.2.2 ...
    • ... behebt den TCP-Zielport wieder auf 4321 ...
    • ... und sendet es auf seinem fröhlichen Weg (auf der LAN-Schnittstelle).
  5. Der PC empfängt das Paket und sieht nichts über die NAT-Prozedur. Das Paket sieht genauso aus, als hätte 198.51.100.20 es gesendet, als ob der NAT-Router überhaupt nicht da wäre.

Zu keinem Zeitpunkt erscheint das Thema einer "Verbindung". Der NAT-Router (in seiner einfachsten Form) muss sich nicht um den Inhalt der Nachrichten kümmern. Es kümmert sich um die IP-Adressen und die Ports des Absenders und Empfängers, aber sonst nichts. (Zugegeben: Hier werden wahrscheinlich alle Arten von Sicherheits- und Leistungsproblemen übersprungen. Dabei geht es jedoch um das Grundprinzip wie das in dieser Frage vorliegende.)

Woher weiß der Router das?

Der Router muss überhaupt nichts über "Verbindungen" wissen. Tatsächlich existieren ähnliche Verfahren wie für TCP für das verbindungslose UDP-Protokoll (UDP Hole Punching) beschrieben oder könnten tatsächlich für jedes Protokoll implementiert werden, das so etwas wie Portnummern in der Transportschicht hat.

Der Grund, warum der Router das Protokoll auf Transportebene (TCP, UDP, ...) in Bezug auf NAT kennen muss, liegt hauptsächlich darin, dass die Ports selbst nicht Teil von IP sind. und Ports machen den "Hack", der (diese Art von) NAT ist, leicht möglich.

Also zu Ihrer Frage:

Wie entscheidet NAT, welche Verbindungen eingehen und welche ausgehen?

Ausgehende Verbindungen sind per Definition diejenigen, die mit einem SYN-Paket (oder einem anfänglichen UDP-Punch im Fall von UDP) beginnen, das an der LAN-Schnittstelle angezeigt wird. Sie im Fall von NAT "Verbindung" zu nennen, ist ein bisschen viel; Sie enden einfach als temporärer Eintrag in einer NAT-Übersetzungstabelle (zuzüglich aller Sicherheits- / Leistungszusätze, die der einzelne NAT-Router möglicherweise ebenfalls verwendet).

Eingehende Verbindungen sind in dem Szenario, das ich bisher in der Antwort verwendet habe, nicht vorhanden. Es gibt natürlich Varianten von NAT, die dies tun; Sie können beispielsweise einen Port auf der WAN-Schnittstelle des Routers statisch mit einer bestimmten IP: PORT auf der LAN-Schnittstelle identifizieren, wodurch ein Server in Ihrem NATted LAN ausgeführt werden kann. Dies wird auch häufig von billigen DSL / WLAN-Routern unterstützt. Und mit "echten" Routern können Sie diese natürlich in jeder gewünschten Form und Weise konfigurieren.

Weitere eingehende / ausgehende IP-Pakete unterscheiden sich nicht von den im Beispiel angegebenen. Sobald der erste SYN-Handshake durchgeführt wurde und der Router den Eintrag in seiner Übersetzungstabelle hat, durchläuft er (mit derselben Übersetzung wie im Beispiel erläutert) alle weiteren Pakete in beide Richtungen.

Wenn der Server im Rahmen einer so hergestellten TCP-Verbindung Daten an den Client senden möchte (was durchaus möglich ist - TCP ist bidirektional), handelt es sich für den NAT-Router nur um weitere IP-Pakete. Der Inhalt dieser Pakete ist nicht so wichtig (dh ob sie bestimmte Nutzdaten enthalten oder nur "Verwaltungs" -Pakete von TCP oder was auch immer sind).

Zu keinem Zeitpunkt "schließt" der Router irgendwie die Röhre, wie Sie es sagen. Offensichtlich hat der Router eine Vorstellung davon, wann er den Eintrag aus der Übersetzungstabelle löschen kann (wahrscheinlich, wenn er einen FIN-Handshake bemerkt, der die Verbindung beendet, oder durch eine Zeitüberschreitung oder einen Fehlerzustand), aber von Anfang bis Ende ist dies der Fall eine ununterbrochene Angelegenheit.


1
Bitte verwenden Sie IP-Adressen von RFC5737, die speziell für Dokumentationszwecke definiert wurden, anstatt gültige Adressen, insbesondere von Google, zu "entführen".
Patrick Mevzek

1
Verbindungen sind bidirektional, also sowohl eingehend als auch ausgehend. Es ist die Initiierung der Verbindung, die eingehend oder ausgehend wäre.
Ron Maupin

@ RonMaupin, ja, das erkläre ich in den letzten Absätzen, insbesondere im vorletzten. Entspricht das dem, was Sie gemeint haben, oder habe ich es dunkel geschrieben?
AnoE

@PatrickMevzek, lerne jeden Tag etwas Neues. Fertig + danke!
AnoE

Vielen Dank. Ich stimme zu, meine Frage würde vielleicht spezifischer als Initiierung der Verbindung formuliert , nicht als Frage bezüglich der allgemeinen Bidirektionalität. Ich habe bereits eine Portzuordnung implementiert, und die Router, die normal funktionieren, funktionieren. Ich habe diese Frage gestellt, um herauszufinden, was für Router getan werden kann, die nicht zusammenarbeiten, z. B. in Coffeeshops, an öffentlichen Orten usw. Dies ist eine großartige Antwort, die über die Gesamtsituation hinausgeht und sehr geschätzt wird.
Dean M.
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.