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:port
ist 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?
Antworten:
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:
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 .
quelle
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.
quelle
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:
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:
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:
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.
quelle