Nat-Traversal Implementation for P2P Connection

NAT-Traversal implementation for P2P connection

Basically, if you can port forward, then this is more of a infrastructure question than programming. You Just need to configure the routers to direct traffic from the public IP / Port to the Private IP / Port, e.g.:

R2: Port 500 - TCP -> Laptop-PT - Port 500
R3: Ports 16000/16500 - TCP/UDP -> PDA-PT - Port 16000/16500

If you want to get fancy and your routers support UPnP, just resort to a library that implements the IGD protocol (e.g., MiniUPnP), in order to make your application control the port mapping. This article provides a good starting point as well as some sample code (although I would really recommend a robust library).

How NAT traversal works in case of peer to peer protocols like bittorrent.

BitTorrent does not need to connect to any particular member in a swarm, it's not a p2p chat protocol where two specific end points want to talk to each other. All it cares about is that the connection graph of the swarm has a sufficiently high connectivity degree.

In other words, getting clients behind a NATs to talk to each other is somewhat desirable, but not to the point where major resources, such as traffic forwarding, would be expended on that goal. On the individual node level failure is an option.
Thus it does not use sip/turn/etc.

Of course on the aggregate swarm level performance will still degrade with an increasing fraction of non-reachable nodes. If nobody can accept incoming connections then BitTorrent doesn't work.

Various clients use some combination of the following approaches to improve connectivity for the bulk transport connections:

  • PCP, NAT-PMP or UPnP-IGD negotiation with the gateway to forward a port as long as the application is running.
  • For TCP one can use source port binding (outgoing connections) and port reuse (listen + outgoing) socket options to use the same local port for all connections to exploit end-point independent (EIM) NAT mappings (also known as full cone NAT).
  • Similarly for UDP one should use a single socket in combination with sendto/recvfrom or equivalent APIs to multiplex all application-level connections over a single port instead of creating one socket per peer.
  • the largely undocumented ut_holepunch extension that uses mutually reachable swarm members in place of stun servers.
  • an optional UDP-based transport protocol (µTP) that can be used in combination with the previous points. generally nat traversal is easier to achieve with udp
  • IPv6 capability signalling, which in principle allows clients to upgrade their connections and then gossip about v6 peers via PEX/DHT.
  • prompting the user to perform manual port forwarding

In the case of the DHT only the first two points (gateway negotiation and port reuse) are used. The overhead of attempting nat traversal for a single request-reply cycle would be >100% and is not worth it.

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

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.


Related Topics



Leave a reply



Submit