How do p2p clients exchange files directly? - sockets

Apologies in advance for not knowing the proper terminology.
I was wondering how p2p (e.g. BitTorrent) clients exchange a file directly.
My computer is behind a router. It has no public IP and therefore no one is able to connect to it from the outside of its local network.
My current understanding is that there should be a computer with a publicly accessible IP to serve the peers. But the whole point of peer-to-peer protocols is to allow direct communication between two peers.
How is that done?
Thanks!

Your router has its own public IP that it uses when talking to the outside world. If it did not, there would be no point to your question, since you would only be able to transfer data with other computers within your private network, you would have no Internet connection, etc.
What you are looking for is called NAT traversal. It is what allows peer-to-peer connections through routers and other NAT (Network Address Translation) devices.

Related

Private P2P Chat (NAT Traversal question)

I am new to networking and have a question regarding p2p and NAT traversing.
I have two PCs with known different static public IPs (IPv4). The first PC (#1) belongs to me, the second one (#2) belongs to my friend.
I want to write a simple P2P chat app which would allow me to exchange messages between these two PCs. The public IPs are known to me and my friend. Also, our local IPs are also known ( #1 is connected to a local private network where all devices share the same public IP). I would like to avoid port forwarding thus I am looking for a way to use some NAT traversal techniques. I would appreciate it if you can share thoughts on this matter.
P.S.
I am familiar with Python, C/C++, Java, C#
P.S.S.
The answer here
NAT-Traversal implementation for P2P connection
assumes port forwarding.
Here are two NAT traversal methods we always use: upnp & nat-pmp, you can search them in github and use them to realise P2P communication between two different internal IP. But one thing you need to notice is that these techs need the support of router.

How a peer to peer (P2P) socket connection is established in general, in the context of WebRTC?

Conceptually I am unable to comprehend that how 2 devices, which are connected to their respective Wifi networks (for example) are able to establish a peer to peer connection, even with intermediate temporary server in between.
E.g. Computer A's public IP is 1.1.1.1 & private IP is 192.x.x.x. Computer B's public IP is 2.2.2.2 & private IP is 192.y.y.y. Without any firewall etc. (general case), how will they make a direct socket connection among them?
Will appreciate if you can explain in slightly layman's term.
Context: I am studying a server, which intends to provide WebRTC in the browser. Using Google's STUN server, they are able to exchange media in many cases. But conceptually I am unclear, on what takes place in between.
WebRTC uses a process called ICE for establishing the connection. Its a suite of techniques for NAT holepunching that mostly rely on the STUN protocol.
The formal description is in RFC 5245 (updated by a newer version)
This presentation from the IETF 92 is one of the best slide decks I've seen so far.

How exactly do p2p networks connect?

If I establish a connection with a friend on Skype, the audio and video data does not go through Microsoft but directly. I also have a p2p client X that does a similar thing. I do not fully understand how this happens internally. How does a machine establish the connection with the other if there is no direct identifier such as a public IP address? Multiple computers in the same network can each do p2p or Skype calls at the same time.
I have been wondering about this for a week because I want to connect two Nodes with each other (like a socket server/client). Can you point me in the right direction?
If two clients want to connect, but neither knows the address of the other, some sort of intermediary that they both know has to be in place to help set up the connection. They both contact the intermediary with the desire to connect, the intermediary tells them both what the others direct address is, and the connection can be set up directly.
Sometimes (read: always) one or both machines share a public IP with others behind NAT, and NAT traversal techniques are needed to establish end-to-end connectivity, usually some form of ICE or SIP.

Possible to send data between two iOS devices?

I've read tons of questions about this all over the web, and can't seem to find a solid answer. If I have an iPhone that's running on cellular data and another iOS device on wifi (in two separate locations), is it possible for them to send data to each other directly without sending it first to a web server, then retrieving it? Are the only options sending and receiving from a server/Apple's iCloud? What if I knew the devices' ip addresses? Note that the iPhone has WiFi disabled.
I'm not looking to put this in the app store, it is for personal use. I know NSNotificationCenter isn't an option.
Using the gamekit framework you can send data between two iOS devices. It is easy to implement. Other than that I don't think there is any other way to send data between two iOS devices.
Actually, it IS possible. You may want to google for something called "UDP hole punching" or "TCP hole punching".
The main approach in short: Assuming you got something like a relay server, that is some server in the internet that is publicly addressable from every private LAN that is connected to the www. No you have your two clients A and B in (different) private LANs, with some Network address translation (NAT) going on, that want to establish a peer to peer connection.
First of all both will tell the server their IP address and the port they have in their own LAN. In the UDP or TCP packet, the server will find the public address and port of the device (or the NAT (router)). So the server knows the private and the public IP address as well as the ports.
If now A wants to communicate with B, it asks the server for help. The server will send a message to B that A wants to communicate with her telling her A's public and private IP and port. A gets back B's public and private information and port.
Now here is where the magic happens. Both clients now send packets out to establish a connection simultaneously to the private and public addresses of the other party and thus punching a whole in their NATs such that incoming connections will not be blocked. Even if one party's connection establishing packets will arrive before this whole is created, the other's packets will get through to such that a connection can be created.
Beware of some NATs that scan the data for IP addresses and translate them as well, but if you encrypt your data or change the appearance of the address (complement, ...) you will be fine.
Now the master question, how can the server communicate with one of the clients without an active connection. Well in this case you can use "connection reversal" and apple's "push notifications". Use the "push notifications" (pn) to tell a client behind a NAT that there is something of interest going on and that it should contact the server. Once it has done that the connection is active and can be used in the previous described fashion.
I hope this helps some people that get to this problem although the post is quite old!
You can only use direct IP address communications if the IP address are publicly reachable IP addresses accessible over the internet, and they are static (enough) so that they are not changing on you regularly as devices get assigned to addresses dynamically. In many (most) cases, that won't be true because your devices will be assigned their IP address dynamically and those addresses are frequently going to be self-assigned IP addresses that aren't publicly addressable.
As others have commented, using Apple-provided mechanisms like iCloud are probably the easiest options. If that's not something you'd like to entertain, there are probably ways to make use of a dynamic DNS service like DynDNS to manage the actual IP addresses of your devices. With something like that you might be able to use a direct IP connection between devices based on a named DNS lookup. You'd probably have to jump through some hoops to make that happen though and I'm not sure you'd want to go to that extent.
I think that Bluetooth would be a good option for you

Coordinating peer-to-peer messages using multicast, how to get receiving IP?

I have been working on a local LAN service which uses a multicast port to coordinate several machines. Each machine listens on the multicast port for instructions, and when a certain instruction is received, will send messages directly to other machines.
In other words the multicast port is used to coordinate peer-to-peer UDP messaging.
In practice this works quite well but there is a lingering issue related to correctly setting up these peer-to-peer transmissions. Basically, each machine needs to announce on the multicast port its own IP address, so that other machines know where to send messages when they wish to start a P2P transmission.
I realize that in general the idea of identifying the local IP is not necessarily sensible, but I don't see any other way-- the local receiving IP must be announced one way or another. At least I am not working on the internet, so in general I won't need to worry about NATs, just need to identify the local LAN IP. (No more than 1 hop for the multicast packets is allowed.)
I wanted to, if possible, determine the IP passively, i.e., without sending any messages.
I have been using code that calls getifaddrs(), which returns a linked list of NICs on the machine, and I scan this list for non-zero IP addresses and choose the first one.
In general this has worked okay, but we have had issues where for example a machine with both a wired and wifi connection are active, it will identify the wrong one, and the only work-around we found was to turn off the wifi.
Now, I imagine that a more reliable solution would be to send a message to the multicast telling other machines to report back with the source address of the message; that might allow to identify which IP is actually visible to the other machines on the net. Alternatively maybe even just looking at the multicast loopback message would work.
What do you think, are there any passive solutions to identify which address to use? If not, what's the best active solution?
I'm using POSIX socket API from C. Must work on Linux, OS X, Windows. (For Windows I have been using GetAdapterAddresses().)
Your question about how to get the address so you can advertise it right is looking at it from the wrong side. It's a losing proposition to try to guess what your address is. Better for the other side to detect it itself.
When a listening machine receives a message, it is probably doing do using recvfrom(2). The fifth argument is a buffer into which the kernel will store the address of the peer, if the underlying protocol offers it. Since you are using IP/UDP, the buffer should get filled in with a sockaddr_in showing the IP address of the sender.
I'd use the address on the interface I use to send the announcement multicast message -- on the wired interface announce the wired address and on the wireless interface announce the wireless address.
When all the receivers live on the wired side, they will never see the message on the wireless network.
When there is a bridge between the wired and the wireless network, add a second step in discovery for round-trip time estimation, and include a unique host ID in the announcement packet, so multiple routes to the same host can be detected and the best one chosen.
Also, it may be a good idea to add a configuration option to limit the service to certain interfaces.