1

I'm doing a P2P application in C/POSIX and I'm stuck with NAT traversal.

I read about multiple way to do this (MiniUPnP, manual port-forwarding, TCP/UDP hole punching) and lots of questions about it but I found some problems:

  • MiniUPnP: I saw that transmission-cli use it to make the port-forwarding, so I downloaded the source code of MiniUPnP and tried to understand it, but it's too much of a mess and gave up. I searched for something like a documentation to implement it (like "this function need that structure to do someting and will return this") but didn't found anything usefull. (I think that this is the cleanest way to do it, because it just require to use a library made for this purpose. If someone know how to use that code, please help me)
  • Manual port-forwarding: I'd like the user not to mess up with his router's settings, all the work should be done by code.
  • TCP hole punching: I read this article about hole punching, and I think is the easiest way to do it (I also have a VPS with a public IP so i can use it like a rendezvous server) but I can't manage to connect two different users behind different NATs.

Scenario

I have a main server (on the VPS) that keep note of every peer that join the p2p network and this is what happens:

  1. PeerA joins the network and send the server the couple (A_LOCAL_IP:A_LOCAL_PORT);
  2. The server saves A's public IP (X.X.X.X) and his public port (AAA) and the couple sent from A.
  3. PeerB joins the network and and send the server the couple (B_LOCAL_IP:B_LOCAL_PORT)
  4. The server saves B's public IP (Y.Y.Y.Y) and his public port (BBB) and the couple sent from B.
  5. Both PeerA and PeerB enter in a for loop waiting for an accept(), then they spawn a thread to handle the incoming request
  6. PeerA wants to connect with PeerB
  7. PeerA ask the server, the IP:port of PeerB
  8. The server sends to PeerA both couple (Y.Y.Y.Y:BBB) and (B_LOCAL_IP:B_LOCAL_PORT) [this last one in case they belong to the same NAT]
  9. PeerA spawns a thread that enters in a for loop trying to connect or with "Y.Y.Y.Y" through port "BBB" or with "B_LOCAL_IP" through port "B_LOCAL_PORT" while the "main thread" enters in a for loop trying to accept a connection
  10. The server sends to PeerB both couple (X.X.X.X:AAA and (A_LOCAL_IP:A_LOCAL_PORT)
  11. PeerB spawns a thread that enters in a for loop trying to connect or with "X.X.X.X" through port "AAA" or with "A_LOCAL_IP" through port "A_LOCAL_PORT" while the "main thread" enters in a for loop trying to accept a connection

Here's the deal: when I use the (B_LOCAL_IP:B_LOCAL_PORT) couple, it works fine; when I use the (Y.Y.Y.Y:BBB) couple, it doesn't work.

I use an exponential back-off in case of "ECONNREFUSED", and when I try to use the (Y.Y.Y.Y:BBB) couple it prints

Connection refused. Sleeping 1 seconds
Connection refused. Sleeping 2 seconds
Connection refused. Sleeping 4 seconds
Connection refused. Sleeping 8 seconds
Connection refused. Sleeping 16 seconds
Connection refused. Sleeping 32 seconds
Maximum timeout expired. Aborting...

Of course, this also happens when someone under another NAT tries to join the peers under my NAT.

So this is it and theese are my questions:

  1. Why does it work using the (B_LOCAL_IP:B_LOCAL_PORT) couple, and not using the (Y.Y.Y.Y:BBB) one?
  2. Is it possible that my NAT has some configuation/architecture that make it impossible to achieve through hole punch?
Tahlil
  • 2,680
  • 6
  • 43
  • 84
igng
  • 372
  • 1
  • 6
  • 17
  • 2
    I don't see where PeerB tries to make a connection. The point of hole punching is that both peers try to connect to each other, it's explained in the article you linked. – ElderBug Aug 17 '15 at 08:39
  • When you say for B_LOCAL_IP:B_LOCAL_PORT works, do you mean in that case both peers are under same NAT? – Tahlil Aug 18 '15 at 03:32
  • Please see this answer..http://stackoverflow.com/questions/31954219/create-tcp-connection-over-nat/31955934#31955934 – Tahlil Aug 18 '15 at 03:32
  • Added the part where PeerB tries to make a connection, but it still doesnt't work. They are both 'stuck' with the connect(). After some time i get "errno = 110 connect: Connection timed out" – igng Aug 20 '15 at 21:25
  • In what mode are Peer A and B? Like active or passive or simultaneous open? – Tahlil Aug 22 '15 at 04:18
  • I _guess_ they're simultaneous open, because both have two threads: one that tries to connect() one that tries to accept(). – igng Aug 23 '15 at 11:56
  • For simultaneous open socket you don't need to call accept(). You just try keep calling connect from both end and eventually one of them will succeed. – Tahlil Aug 24 '15 at 11:00
  • Forgot to mention, some NAT doesn't support SO connection. It's need to be enabled. – Tahlil Aug 27 '15 at 18:44

0 Answers0