UDP Hole Punching - Was genau tut der Server?

danoman

Mitglied
Hallo zusammen,

hab vor eine client-client connection via java aufzubauen ohne Port-Forwarding seitens der Clients einrichten zu müssen wenn sie hinter nem Router oder NAT sitzen. Mir ist klar, dass man dazu zwei Clients (logischerweise) und nen dritten "server" brauch der die beiden in Verbindung setzt. Die erste grundlegende Frage ist: handelt es sich jetzt wirklich um eine Client-Client Verbindung oder läuft alles, was die beiden Clients an Daten austauschen über den Server? Iwie sagt jeder was anderes. Hab mir auch schon einige Java Examples angeguckt aus denen aber nicht das Verhältnis zum "server" hervor ging (siehe: http://www.java-forum.org/netzwerkprogrammierung/99684-udp-hole-punching.html - Habs probiert. Die Verbindung kommt zustande, jedoch auch nur wenn man den jeweiligen Port forwarded).
Was ich jetzt beim ganzen hole punching-Verfahren nicht verstehe ist: Wenn sich die Clients mit nem Server verbinden, muss der Server ja auch wiederrum mit den Clients über den spezifizierten Port kommunizieren. Aber spätestens beim NAT oder Router des Clients wär doch wieder ende... also ist man doch wieder beim Ausgangspunkt und dem Problem mit dem Forwarding angekommen.

Ich vermute der Server muss iwas spezielles machen. Wär schön wenn mir einer diese Sache beim Hole Punching erklären könnte.

Danke & Gruß
Daniel
 

Kr0e

Gesperrter Benutzer
Also:

Ja, es ist eine Client2Client Sache!

Es geht so:

Beide Clienten melden sich beim Clientserver an. Dieser merkt sich die Ip in Verbindung mit einem Namen z.B.

Will nun ein Client eine Verbindung aufbauen geht das so:

Client erfragt beim server die IP von Client X. Dann schickt dieser Client eine Nachricht an Client X. Natuerlich kommt keine Antwort, da deine Nachricht nicht zum Client durchkommt, sondern vom NAT verworfen wird. Dann schickt Client X eine Nachricht an dich. Diese kommt auch durch, da du ja gerade eine Anfrage an Client X gesendet hast, werden temporeare Ports in deinem Router geoeffnet. Die schliessen sich nach einem Timeout wieder, aber das timeout reicht aus, damit der Client X die Pakete schicken kann. Ab dem Punkt ist eure Verbindung hergestellt und der Server ist dann nicht mehr von Belang... Ist ne ziemlich einfache Sache und mit Java schnell realisierbar. Schwer wirds erst bei TCP Hole Punching. Dafuer brauchste dann aber low level Zugang mit C/C++, sonst geht nix.

UPDATE:

Meine Methode ist etwas umstaendlich, da der andere Client erst ueber meinen Verbindungversuch benachrichtigt werden muesste. Hatte das nicht mehr so 100% im Kopf... Hier eine etwas raffiniertere Variante von Wiki:

Let A and B be the two hosts, each in its own private network; N1 and N2 are the two NAT devices; S is a public server with a well-known globally reachable IP address.
A and B each begin a UDP conversation with S; the NAT devices N1 and N2 create UDP translation states and assign temporary external port numbers
S relays these port numbers back to A and B
A and B contact each others' NAT devices directly on the translated ports; the NAT devices use the previously created translation states and send the packets to A and B
 
Zuletzt bearbeitet:

danoman

Mitglied
Vielen Dank für die Antwort. Den Wiki-Post kenn ich soweit. Nichts desto trotz habe ich keine Ahnung, wie eine genaue Umsetzung zu Stande kommen könnte. Ich versteh zwar das Grundprinzip allerdings reicht es nicht, um damit produktiv was auf die Beine zu stellen, falls du verstehst was ich meine ^^.
Ich besitzt quasi ein gewisses Halbwissen was grade mal zum klugscheißen ausreicht xD.

Hab ich das soweit richtig verstanden?: Nachdem C1 dem CS (Clientserver) ein Paket geschickt hat, öffnet der Router von C1 einen Port damit der CS nen Response zurück an C1 senden kann (wie es z.B. üblicherweise passiert, wenn ich mit meinem Browser ne Website auf irgendnem Port ansurfe - Ich muss Port 80 ja auch nicht forwarden). Deswegen ist es ja auch wichtig, dass der CS ne öffentliche IP hat - sprich - nicht hinter nem NAT sitzt. Und bevor der Router von C1 wieder nach nem Timeout die Ports dicht macht, muss C2 dem C1 ein Paket (über den eigenlichen response-Weg der C1-CS connection) zurückschicken.

Ist das richtig so?
 

Kr0e

Gesperrter Benutzer
Ansich ja, ich zweifele grad nur noch an einer Sache: Eigentlich muss das Paket dass C2 an C1 schickt noch angepasst werden, denn der Router merkt sich, an wen das UDP Paket ging, sprich nur eine Antwort von CS wuerde durch dier Firewall gehen. Deswegen hab ich auch anfangs diese etwas komplexere Methode mir ueberlegt. Kann auch sein dass ich mich grad irre und der Firewall(Router) das vollkommen egal ist..
 

danoman

Mitglied
hm oke. Also wenns so ist, isset ja testable. Ich weiß, dass TCP zwangsläufig nen Response erfordert, was bei UDP ja nicht der Fall ist. Könnt sein, dass man deswegen nicht ohne weiteres nen TCP Hole Punch hinkriegt weil die Vorgehenseweise da umgebogen werden müsste. Ich werd das mal die Tage testen und posten obs geht oder nicht. Klingt soweit aber logisch. Hät aber schon iwie was böses, wenn man das Paket, welches C2 an C1 schickt, modifizieren m CS statt C2 als Absender eintragen müsste. Falls dir noch was einfällt mach mal bitte meldung.

Danke!
Daniel

UPDATE:
Wie kriegt man die Prozedur denn gesynct, sodass das Paket von C2 rechtzeitig bei C1 ankommt, bevor der Router von C1 die Ports wieder dicht macht?! Hab da was im Kopf, kommt mir aber iwie nen bisschen spartanisch vor:

1. C1 sendet an CS ein Paket -> Router öffnet Ports
2. C2 verbindet sich mit CS -> C2 Router öffnet Ports
2. CS sendet an C2, dass C2 C1 ein Paket schicken soll (C2 übernimmt quasi den Response von CS)
3. C1 erhält Response (von C2) und Connection is established

macht das Sinn, und wenn ja, wäre das die von dir beschriebene Methode oder die Wiki-Variante? Schritt 2/3 kommt mir etwas problematisch vor.
 
Zuletzt bearbeitet:

Ähnliche Java Themen


Oben