Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a P2P connection when both clients are behind NAT

Tags:

c#

.net

tcp

Is it possible to establish a direct connection between 2 clients that are both behind different NATs? Of course I realize that to some extent a server with a public IP will be essential, but I don't want it to be a proxy. Take a look at the following scenario:

  • I don't want to have anythig to do with configuring network devices. I just want to do it in code.
  • I don't want the server to take part in file transfer process (for performance reasons)
  • we have: client A, client B, and a Server S and it looks somewhat like this:

A--[Router1]--S--[Router2]--B

  • A connects to S and authorizes
  • B connects to S and authorizes
  • A wants to send a file to B
  • A asks S for a connection to B
  • S [does it's magic here] and A now has a connection to B
  • A starts to send a file
  • S goes down (or at least the file transfer bypasses is)
  • there's still the connection between A and B
  • A continues sending the file to B

My questions:

  1. Is that possible?
  2. How to do this?
  3. Have encountered a sample project that can do this?

I found WCF / WPF Chat Application, but it turned out to be a proxy.

I also found some posts suggesting using UPnP and NAT Traversal, but none answered my 1st question directly so I didn't dig deeply into it.

like image 472
Andrzej Gis Avatar asked Mar 23 '23 14:03

Andrzej Gis


1 Answers

The term you are looking for the "magic part" is called NAT Hole Punching. Unfortunatly the topic is a bit too broad to be explained fully here on how to accomplish it, but now knowing the correct term should at least be able to get you started on looking for the correct tutorials.

Here is the summary of the algorithom from the UDP Hole Punching page.

Let A and B be the two hosts, each in its own private network; N1 and N2 are the two NAT devices with globally reachable IP addresses P1 and P2 respectively; S is a public server with a well-known globally reachable IP address.

  1. 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 X and Y
  2. S examines the UDP packets to get the source port used by N1 and N2 (the external NAT ports X and Y)
  3. S passes P1:X to B and P2:Y to A
  4. A sends a packet to P2:Y and B sends a packet to P1:X using the same source port as the conversation with S thus "punching" a hole in the NAT towards the other host
  5. If either host receives a packet, the hole punching is successful and both hosts can communicate.

If both hosts have Restricted cone NATs or Symmetric NATs, the external NAT ports will differ from those used with S. On some routers, the external ports are picked sequentially making it possible to establish a conversation through guessing nearby ports.

Whether or not it will work is highly dependent on how both endpoint's NAT routers behave, it is very likely that a significant portion of your uses will be paired up and both have routers that are not "hole punch friendly".

In your situation I would have my software try these steps in order.

  1. Check and see if we can just connect (The user did manual port forwarding)
  2. Use UPnP and open a port
  3. Use some form of hole punching using a public server as the go between
  4. Use another peer that does have ports open as a proxy for the data (a Supernode).
  5. Use a server I host as a proxy to forward the data.
like image 166
Scott Chamberlain Avatar answered Apr 05 '23 23:04

Scott Chamberlain