2

Let's say I have a server, and two clients connected to it. (via TCP, but it doesn't matter)

My goal is to allow a direct connection between those two clients. This is to allow direct voice contact between two players, for example, or any other client plugin they may have installed which don't need server interaction (like playing some kind of random game between the two). The server can be there to help setting up the connection.

From duskwuff's answer, I got several leads:

http://en.wikipedia.org/wiki/STUN which describes an algorithm to do that, and
http://en.wikipedia.org/wiki/UDP_hole_punching

From those, I got more leads:

http://www.h-online.com/security/features/How-Skype-Co-get-round-firewalls-747197.html
http://nutss.gforge.cis.cornell.edu/stunt.php -- A possible STUN implementation with TCP

With time, I could surely work out something for my program. For now I'm using C++ and TCP (Qt Sockets or Boost sockets), but if needed I don't mind doing UDP in C and wrapping it.

The bounty is there for any programmer having experience with those in C and C++ that may give tips to make this easier, by linking to example programs, updated libraries, or any other useful information. A documented, flexible & working C++ TCP implementation would be the best but I'll take what I get!

Jérôme Verstrynge
  • 57,710
  • 92
  • 283
  • 453
coyotte508
  • 9,175
  • 6
  • 44
  • 63
  • 1
    Ephemeral ports are used to respond to requests made to a server on a **well known service port** (i.e. HTTP, FTP, etc.). That way the server well known service port is not blocked when responding to requests, and can accept new connections. For instance when you open an FTP connection the initial request goes through port 20, the server accepts the connection request and starts a process to work with that session on another port (ephemeral port). If all sessions went through the same port, only one session would be able to stay connected at a time. – Xint0 Sep 07 '11 at 00:53
  • 2
    @Xint0: That's not really accurate. "Ephemeral ports" are not involved in HTTP at all. A connection is identified by a unique tuple of local ip, local port, remote ip, and remote port. As many connections as your OS can handle can be accommodated on a single local ip and port as long as either the remote ip or remote port differs for any given pair of distinct connections. – R.. GitHub STOP HELPING ICE Sep 07 '11 at 00:59
  • @R.. when I wrote HTTP, I was referring to the port number 80 which is the well known service port for the HTTP Server. HTTP is a protocol of the Application layer. Ephemeral ports are used in the Transport layer (TCP, UDP, etc.) – Xint0 Sep 07 '11 at 01:14
  • 1
    Perhaps you could clarify, but as I read your comment, it's wrong. Specifically, the sentence "If all sessions went through the same port, only one session would be able to stay connected at a time." is not true. – R.. GitHub STOP HELPING ICE Sep 07 '11 at 01:59
  • another important information might be the possibility to replace an UDP socket by a TCP socket, if this isn't detected and blocked by the router. – coyotte508 Sep 11 '11 at 12:50

5 Answers5

3

I'm not aware of any way to reliably punch through firewalls for TCP, but there's a similar method for UDP traffic that's pretty well documented:

  • UDP hole punching is a method for establishing bidirectional UDP connections between Internet hosts in private networks using network address translators. The technique is not applicable in all scenarios or with all types of NATs, as NAT operating characteristics are not standardized. -- right on spot! I'll wait a bit to see other responses – coyotte508 Sep 07 '11 at 08:49
3

Punching TCP holes in NAT is sometimes/often possible (it depends of the NAT behavior). This is not a simple subject to learn, but read the corresponding chapter about NAT traversal from Practical JXTA II (available online on Scribd) to understand the nature of the issues to solve.

Then, read this. It comes from the guy who wrote that: http://nutss.gforge.cis.cornell.edu/stunt.php (one of the links in your question).

I am not a C/C++ specialist, but the issues to solve are not language specific. As long as you have access to TCP from your code base, that's enough. Keep in mind that implementing UDP traversal is easier than TCP.

Hope these tips help.

P.S.: I am not aware of a C/C++ implementation of the solution. The code mentioned in Cornell's link is NOT operational as confirmed by the author. I tried to resuscitate it myself, but he let me know it was completely tweaked for research purposes and far from production ready.

Jérôme Verstrynge
  • 57,710
  • 92
  • 283
  • 453
1

A few links to projects that might be of interest or helpful:

Ioan
  • 2,382
  • 18
  • 32
1

You're looking for rendezvous server for NAT hole punching: the server that is publicly accessible (not behind NAT/firewall or they are properly configured) to help computers behind NAT/firewall to establish peer-to-peer connection.

UDP is more popular in NAT punching because provides much better results than TCP. Clear and informative description of UDP NAT hole punching can be found here.

If you need reliable communication, you can use reliable protocols over UDP:

  1. SCTP (libraries) - standardized one, or
  2. one of many custom protocols, e.g. RakNet (I used this library, it's quite mature and feature-rich and has NAT punching implementation), Enet or many others (Q8)
Community
  • 1
  • 1
Andriy Tylychko
  • 15,967
  • 6
  • 64
  • 112
0

Ephemeral ports won't magically eliminate the need to relay through the server, because they are only valid during the life of the session opened through a well known service port. Basically ephemeral ports depend on a server session.

You will need to use the server to relay communications between both clients, that is act as a proxy server. One option would be to setup a SSH tunnel through a SSH proxy server, with the added benefit of security.

Still this doesn't guarantee that the firewall won't block the connection. That depends on the firewall type and configuration. Most residential routers that act as firewalls, by default block all incoming connections. This is normally fine because most of the time the computers behind the firewall act only as clients, which initiate the connections to the outside. And this setup varies, because some restrict initiating connections only to well known service ports like HTTP, HTTPS, FTP, SFTP, SSH, etc., and if your proxy server uses a non-well-known-service port then the connection will be blocked.

But firewalls can be setup to block outgoing traffic also, this is most common in corporate networks, which don't even allow direct connections to web servers and route everything through proxy servers, in order to control resource usage.

You can also research on the use of UPnP to open ports dynamically.

Xint0
  • 5,221
  • 2
  • 27
  • 29
  • Thanks, it seems ephemeral port don't work. Though I wonder how exactly ephemeral ports are dealt, if the server session establishment or continuation is not managed directly by the OS but by low level code, then there is hope to find a library allowing to tweak that. Anyhow, duskwuff's post proves it's possible in UDP, so there's definitely a way to do it, even though I need to look more into it and maybe it's not using ephemeral ports. – coyotte508 Sep 07 '11 at 09:04