UDP Hole Punching (Loch-Trick) - Verständnisfrage

  • Allgemein

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von haiyyu.

    UDP Hole Punching (Loch-Trick) - Verständnisfrage

    Hallo.

    Ich habe mich in letzter Zeit mit UDP Hole Punching beschäftigt, da es ein sehr interessantes Thema ist.
    So langsam verstehe ich, wie das Ganze funktioniert, aber ein paar Dinge bleiben noch unklar.
    Also, so sieht es mit meinem Verständnis bisher aus:

    Es gibt zwei Clienten, C1 und C2, und einen Server, S.
    Der Server weiß die IP-Adresse und den Port der jeweiligen Clienten.
    Nun möchte C1 zu C2 eine Verbindung aufbauen.
    Dazu schickt C1 dem Server S eine Anfrage nach der IP und dem Port.
    Daraufhin schickt S dem Client C1 die IP und den Port.
    C1 schickt nun ein Paket an C2 über die erhaltenen Verbindungsdaten.
    C1s NAT öffnet nun temporär seinen Port, damit die Antwort empfangen werden kann.
    C2s NAT verwirft dieses Paket, da sein Port nicht offen ist, da kein Paket erwartet wird.
    C1 weiß davon nichts und ist immer noch im Glauben, eine Antwort zu bekommen.
    Nun informiert der Server C2, dass C1 etwas von C2 will und C2 schickt etwas zurück.
    Das von C2 versendete Datenpaket kommt als erwartete Antwort durch.

    So weit habe ich das Ganze verstanden (falls irgendwas an meiner Auffassung nicht stimmt, bitte ich, mich darauf hinzuweisen).
    Das Problem: So, wie ich das sehe, müsste die obige Prozedur für jedes Paket wiederholt werden.
    Allerdings heißt es oft, dass der Server nachher nicht mehr von Belang ist...?
    Ich wäre sehr erfreut, wenn mich jemand ein wenig erleuchten könnte, wie das genau funktioniert.
    Habe schon alle möglichen Erklärungen und Demonstrationen, die ich bei Google finden konnte, durch, und irgendwie werde ich nicht hunderprozentig schlau.

    Danke schon mal im Voraus.
    Also bis jetzt ist das was du geschrieben hast alles richtig.

    Je nachdem welchen router du hast, oder ebend der Client musst du laut meines verständnisses nicht das ganze für jedes Paket wiederholen. Das Problem sind die besch***** NAT's jeder router arbeitet anders. Es gibt 3 verschiedene arten von NAT's die alle unterschiedlich leicht auszutricksen sind.

    Das große Problem welches du bekommen wirst, ist das Paket an den richtigen Port zurück zu senden. Denn wie ich eingangs schon erwähnte, läuft das alles über den NAT denn rein theoretisch können ja 2 oder mehrere Rechner an dem NAT hängen und auf dem Port lauschen. Deswegen heißt das auch "Network Adress Translator" . Da mehrere Rechner bei IPv4 über die selbe öffentliche IP verfügen öffnet der NAT für jede Verbindung einen öffentlichen Port. Damit er die Verbindungen selbst bei 20 Rechnern die auf dem selben Port horchen jedem einzelnen Rechner zuordnen kann.

    Deine Herausforderung wird also sein, die Datenpakete immer an den richtigen ÖFFENTLICHEN Port zu senden. Da der NAT deine Datenpakete sonst verwirft.

    Das wird sich alles ändern sobald ALLES über IPv6 läuft weil jeder router ein eigenes Subnet von seinem Provider zugewiesen bekommt. Somit hat jeder Rechner an einem NAT eine eigene öffentliche IP, und es steht dir nur noch die Firewall im Weg.

    Bei weiteren Fragen stehe ich gerne zur Verfügung.
    Hey.

    Schon mal danke für deine Antwort.
    Die hat mir schon ein wenig Klarheit verschafft.

    Also wenn sagen wir PC X über Port 1234 etwas versendet, sendet das NAT möglicherweise das Paket bspw. über Port 8765 (Ausgangsport).
    Dann speichert es diesen Vorgang in einer Tabelle.
    Der PC Y sieht das Paket und schickt die Antwort über Port 8765 zurück.
    Das NAT Von PC X sieht nun, dass etwas über diesen Port erhalten wurde, sieht in seiner Tabelle nach, sieht den Eintrag und ändert den Port wieder auf 1234 und ordnet das Paket PC X zu.
    Habe ich das so richtig verstanden?

    Und zum Senden:
    UDP ist nicht verbindungsorientiert, das heißt, das Paket wird einfach nur an einen Endpunkt gesendet.
    Wenn PC X nun ein Paket PC Y über Port 1234 versende, muss dieser den Port manuell geöffnet haben, da das Paket ansonsten am NAT verworfen wird.
    Allerdings erwartet PC X nun die Antwort, welche PC Y ihm schicken kann. Nun erwartet PC Y eine Antwort (d.h. Port kurzzeitig geöffnet) usw.
    Ich denke, ich hab jetzt auch das verstanden.

    Bei Fehlern in meiner Auffassung oder weiteren Hinweisen, wäre ich erfreut, wenn sich jemand melden würde. Danke. :)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „haiyyu“ ()

    So ... Gestern war ich am Handy, deswegen ist meine Antwort mehr oder weniger Speerlich ausgefallen.

    Also im Grunde hast du mit dem was du da gerade geschrieben hast völlig recht. Nur wirst du ebend das Problem haben, ebend diesen Port herauszufinden

    Und das stellt sich nichtmal allzu einfach dar. Es gibt NAT´s , die verändern den öffentlichen Port nicht, das heißt wenn du das erste mal über Port 8000 was rausgeballert hast, nutzt der NAT z.B den öffentlichen port 5666 um auf die Antwort zu warten. Sendest du nochmal ein Paket über 8000 nutzt der NAT den selben öffentlichen Port wie bei der Übertragung davor.

    Der Zweite NAT ist da schon etwas schwieriger, und stellt etwas Rechengeschick vorraus. Wenn du ein Paket über Port 8000 sendest, öffnet der NAT z.B den öffentlichen Port 5666. Beim Zweiten Paket, nimmt er aber den nächsten freien Port, dass bedeutet, wenn der Öffentliche Port 5667 noch nicht belegt ist, wird er dort auf die Antwort warten. Wenn der Port 5667 allerdings belegt ist, dann nimmt er den nächsten freien Port.

    Der Dritte im Bunde ist der am härtesten auszutricksende NAT. Dort passiert nämlich alles nach Zufall. Sprich, du sendest ein Paket über Port 8000. Der NAT nimmt dafür dann beispielsweise den öffentlichen Port 5666. Bei dem nächsten Paket aber nimmt er einen zufälligen Port. Dieser wäre dann beispielsweise 62023. Und für das nächste Paket nimmt er dann 12540. Dieser NAT stellt also das größte Problem für dich da.
    Hallo.

    Habe mich in letzter Zeit weiter damit beschäftigt und dabei auf die Bind-Methode eines Sockets gestoßen.
    Bisher hatte es mich nicht groß interessiert, was sie macht. Jetzt weiß ich, dass sie dafür sorgt, dass der Port mehr oder weniger gebunden wird.
    Ich habe mir eine simple Server-Client-Applikation geschrieben.
    Hier Ausschnitte des Codes (ich hoffe mal, niemanden stört es, dass er in C# ist):

    C-Quellcode

    1. // server
    2. Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
    3. EndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 1234); // wobei 1234 der Port ist, von dem die Daten empfangen werden
    4. EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
    5. sock.ReceiveFrom(buffer, ref remoteEndPoint);
    6. Console.WriteLine((remoteEndPoint as IPEndPoint).Port);

    C-Quellcode

    1. // client
    2. Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
    3. EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1234); // Server und Client laufen am selben Rechner
    4. sock.SendTo(buffer, remoteEndPoint);
    Wenn der Server nun etwas vom Clienten empfängt, ist der Port des Clients zufällig.
    Wenn ich allerdings den Clientsocket mit dem gleichen Code wie beim Serversocket binde, dann hat der Clientport auch einen bestimmten, immer gleichen, Port.
    Würde das nicht die Probleme mit dem NAT umgehen?
    Oder funktioniert die ganze Sache nur lokal?

    haiyyu schrieb:

    Das Problem: So, wie ich das sehe, müsste die obige Prozedur für jedes Paket wiederholt werden.
    Das ist eben der Trick an der Sache.
    Sobald die Clients sich "gefunden" haben klingt der Server aus.
    Die entsprechenden Ports bleiben offen und können genutzt werden - wie lang die Pause zum Schließen ist, kann ich aber nicht sagen.

    Mfg.
    SAR
    Ja, das habe ich mittlerweile verstanden. :)
    Danke für die Erklärung.

    Weiß zufällig auch jemand etwas zu meinem anderen Post?

    Slayers schrieb:

    Meiner Meinung nach, funktioniert die ganze sache nur Lokal
    Das wäre ja langweilig.
    Lokal brauchst den den Lochtrick nicht, weil du nicht durch irgendwelche Router musst.

    Der Lochtrick ist genau dafür da, remote zu funktionieren.
    Sonst könntest du auch Skype nur im lokalen Netz betreiben.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --