Practical NAT traversal for reliable network connections
Asked Answered
N

2

14

I've seen and read a lot of similar questions, and the corresponding Wikipedia articles (NAT traversal, STUN, TURN, TCP hole punching), but the overwhelming amount of information doesn't really help me with my very simple problem:

I'm writing a P2P application, and I want two users of my application behind NAT to be able to connect to each other. The connection must be reliable (comparable to TCP's reliability) so I can't just switch to UDP. The solution should work on today's common systems without reconfiguration. If it helps, the solution may involve a connectible 3rd-party, as long as it doesn't have to proxy the entire data (for example, to get the peers' external (WAN) IP addresses).

As far as I know, my only option is to use a "reliable UDP" library + UDP hole punching. Is there a (C/C++) library for this? I found enet in a related question, but it only takes care of the first half of the solution.

Anything else? Things I've looked at:

  1. Teredo tunnelling - requires support from the operating system and/or user configuration
  2. UPnP port forwarding - UPnP isn't present/enabled everywhere
  3. TCP hole punching seems to be experimental and only work in certain circumstances
  4. SCTP is even less supported than IPv6. SCTP over UDP is just fancy reliable UDP (see above)
  5. RUDP - nearly no mainstream support
  6. From what I could understand of STUN, STUNT, TURN and ICE, none of them would help me here.
Nautical answered 1/9, 2010 at 0:54 Comment(3)
Your simple problem, as you've discovered, isn't simple at all. NAT traversal is hard. What makes ICE unsuitable? Its use of SDP? Something else?Odell
Maybe I had trouble understanding anything from the huge pile of obscure terminology, but how would ICE help me here? From what I understood, in simple words ICE just figures out if it can make a direct connection, and if it can't it uses an intermediary server to tunnel the data.Nautical
Also, I kinda refuse to believe that no one has solved this problem yet. I mean, it has to be incredibly common! Mostly in video games (some can deal with unreliable connections but not all). Does everyone just write their own "reliable UDP" protocols?Nautical
O
6

ICE collects a list of candidate IP/port targets to which to connect. Each peer collects these, and then each runs a connectivity check on each of the candidates in order, until either a check passes or a check fails.

When Alice tries to connect to Bob, she somehow gets a list of possible ways - determined by Bob - she may connect to Bob. ICE calls these candidates. Bob might say, for example: "my local socket's 192.168.1.1:1024/udp, my external NAT binding (found through STUN) is 196.25.1.1:4454/udp, and you can invoke a media relay (a middlebox) at 1.2.3.4:6675/udp". Bob puts that in an SDP packet (a description of these various candidates), and sends that to Alice in some way. (In SIP, the original use case for ICE, the SDP's carried in a SIP INVITE/200/ACK exchange, setting up a SIP session.)

ICE is pluggable, and you can configure the precise nature/number of candidates. You could try a direct link, followed by asking a STUN server for a binding (this punches a hole in your NAT, and tells you the external IP/port of that hole, which you put into your session description), and falling back on asking a TURN server to relay your data.

One downside to ICE is that your peers exchange SDP descriptions, which you may or may not like. Another is that TCP support's still in draft form, which may or may not be a problem for you. [UPDATE: ICE is now officially RFC 6544.]

Games often use UDP, because old data is useless. (This is why RTP usually runs over UDP.) Some P2P applications often use middleboxes or networks of middleboxes.

IRC uses a network of middleboxes: IRC servers form networks, and clients connect to a near server. Messages from one client to another may travel through the network of servers.

Failing all that, you could take a look at BitTorrent's architecture and see how they handle the NAT problem. As CodeShadow points out in the comments below, BitTorrent relies on reachable peers in the network: in a sense some peers form a network of middleboxes. If those middleboxes could act as relays, you'd have an IRC-like architecture, but one that's set up dynamically.

Odell answered 1/9, 2010 at 20:47 Comment(4)
Argh... I'm sorry, but as I've mentioned I'm not really up to par with this terminology, and whatever I do understand isn't helpful. What's "session description", who is a candidate, why do I need multiple IP/port targets, why are we even talking about multiple peers if my problem is establishing a connection between two parties? Isn't STUN relying on a STUN server present on the NAT-ed network? What does SDP have to do with establishing a single reliable connection between two computers? Thanks for the in-depth answer but I hope you can understand my frustration :(Nautical
Also, BitTorrent simply uses TCP and relies on at least some people being connectible. Pairs of peers behind NAT will not be able to connect to each other, but that's about it. I think the same works with other major P2P networks (eMule etc.) This still allows the P2P network to keep working, but the same can't be said about my situation, where connectivity is a mandatory part of the design.Nautical
Never mind what I said above about STUN, I've done some more reading and found that it's just a well-established procedure for UDP hole punching (plus gathering extra information about the networks).Nautical
Thanks for clearing up the terminology, unfortunately I'm not any closer to solving my problem (since I already suggested UDP hole punching in the question, and mentioned that relaying the data is not an option). I'll accept your answer as a confirmation of "no, there aren't any better solutions than the ones enumerated in the question". Thanks.Nautical
A
3

I recommend libjingle as it is used by some major video game companies which heavily relies on P2P network communication. (Have you heard about Steam? Vavle also uses libjingle , see the "Peer-to-peer networking" session in the page: https://partner.steamgames.com/documentation/api)

However, the always-work-solution would be using a relay server. Since there is no "standard" way to go through NAT, you should have this relay server option as a fall-back strategy if a connection has to be always established between any peers.

Asp answered 23/2, 2011 at 19:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.