Is there any way to establish true P2P communication through TCP or UDP without an intermediary server? I understand that this is quite doable if the two computers have only public IP addresses but if they are behind any sort of NAT router or on a private network it starts to get tricky.. in fact the more I look into it the more it seems plain not possible. I have discovered STUN, TURN and ICE protocols and hole-punching but as far as I understand they all require some sort of server to at least establish the connection. I am amazed something seemingly so simple seems so hard to do, am I missing something? Ideally I am looking for solutions using Golang any help or examples in C++ would also be useful, thanks.
Asked
Active
Viewed 1,306 times
0
-
`if they are behind any sort of router` The main problem is NAT, which in turn is because of the lack of addresses in IPv4. Without NAT, it would be simple, yes. And no, without third host this is not doable (in IPv4). One end has to start the connection, and the other router has no way to know which host behind it is the target. – deviantfan Nov 11 '16 at 14:02
-
Have you looked at [libp2p](https://github.com/libp2p/go-libp2p)? – Christopher Waldon Nov 11 '16 at 19:26
-
@ChristopherWaldon Looks interesting but is still WIP and doesn't seem to offer anything ICE doesn't, ie still falls back on a server relay if other connection types aren't possible. Thanks though. – Chrysm_Seal Nov 11 '16 at 22:28
-
To setup a P2P connection requires *exchange* of IP address and ports. Hence, at least some service is needed to get those IP addresses and ports passed around. How else would you do it? I'd previously answered this question [here](http://stackoverflow.com/questions/8523330/programming-p2p-application) with some of the lightweight overview of how to do ICE. – selbie Nov 15 '16 at 23:51
1 Answers
2
This is not strictly a Go question — it's a general networking question.
The reason this is so difficult is that the Internet was never designed to support NAT, NAT just happened and broke a lot of functionality. The clean solution to your problem is to switch to IPv6, where there is no NAT, but that might not be possible
If your NAT box supports NAT-PMP or uPNP, you could use that. The simplest way would be to create a cgo binding to libminiupnpc
, or you could go fishing for a native Go library.
If your NAT doesn't support either of these protocols, then you're probably out of luck, as hole punching is a fragile and difficult technique that you will probably find difficult to implement.

jch
- 5,382
- 22
- 41