P2P hand-shaking without a central server - c#

I wrote a client-server application designed to exchange files (among other things) over the local area network. In server mode, the application listens for TCP connections with a specific identification header. In client mode, it tries to establish TCP connections to IP Addresses that are provided by the user.
I now need to adapt this application to work over the internet. Without much exposure to network programming, I am not sure how to achieve this without some kind of a central server (for announcing presence, etc.). This is not an option.
Suppose I have the app running in server mode on my machine which is behind a home network. You (the reader) have the app in client mode and we need to connect. Neither of us have static IP addresses. Is there a way for the client to reach the server? Both the server and client could figure out their public IP addresses but beyond that, I'm not sure what to do.
Any guidance would be appreciated.
EDIT: Based on the answers, some clarification is in order. My question is not about discovery. Both client and server can query their public addresses and users can exchange these IPs over some other medium. The question is, how to establish a connection once each other's IPs are known but both parties are behind networks which do not have the appropriate port forwardings. My app uses port 51200 as a default over TCP for example.

I've learned that the techniques of UDP hole punching to obtain a true direct connection between 2 peers, is imperfect due to some possible combinations of NAT types involved. What this means is that UDP hole punching alone is not always going to work.
The way to claim 100% operability is to, in the cases where a p2p connection is impossible, use a relay server. The process of discovering whether a true p2p connection is possible has been standardized by ICE,TURN,and STUN. All I know is that using ICE/TURN/STUN seems to be the standardized strategy in subverting the NAT problem. It can facilitate a true p2p connection when available and offer relaying services when necessary.
Note: I use the term p2p in this answer to distinguish a truly direct connection between 2 endpoints, not to be confused with overlay networks and the like.
Advanced Users: It is possible to gain more direct p2p connections by introducing more complicated strategies to cooperate with symmetric NAT behaviour, such as port prediction, etc. But the libraries that implement these methods are costly, and seems too difficult for a DIY job.
I have not explained in detail the different types of NAT connection possibilities. You will want to research on NAT types and how they relate to UDP hole punching. There are RFCs out there and I will try to update my answer with links. But the point is that you can avert a lot of this learning by refocusing on implementing TURN/STUN/ICE, learn how they are implemented and how you can use their standardized behavior.
Potential Solutions
PJSIP - contains a stand-alone high level NAT traversal library for C/C++, also has bindings for other langauges. If you just want the NAT Traversal library sub-component, see PJNATH
LibJingle - a P2P (peer-to-peer) and RTC (real-time communication) stack that builds on XMPP. Note that many of LibJingle implementation is not interoperable with actual XMPP Jingle specification and subsidiary specifications.
These may add considerable complexity to the program, which is why it can be compelling to implement some of the mechanisms myself.
Documents
NAT on Wikipedia
NAT Traversal Fundamentals
How NAT Compatible are VoIP Applications
STUN server list
Teredo/Shipworm Doc
Symmetric NAT and UDP Hole Punching
STUN/TURN/ICE Summary
IETF
RFCs
RFC 5245 – ICE
RFC 5389 – STUN
RFC 5766 – TURN (iirc, TURN uses a STUN server.)
RFC 5768 – ICE – SIP
RFC 6336 – ICE – IANA Registry
RFC 6544 – ICE – TCP
RFC 5928 – TURN Resolution Mechanism
RFC 6062 – TURN Extensions for TCP Allocations
RFC 6156 – TURN Extension for IPv6
[Draft] Symmetric NAT Traversal using STUN
[Draft] Network Address Translation and Peer-to-Peer Applications (NATP2P)
Microsoft
MS-STUN – Microsoft STUN extensions
MS-TURN – Microsoft TURN extensions
MS-ICE – Microsoft ICE extensions
MS-ICE2 – Microsoft ICE2 extensions
Notes
I have heard that the eventual migration to IPv6 may squash the NAT traversal problem, but [probably not]. Someone could enlighten this topic. Either way, the progression to IPv6 appears slow from my non-experienced viewpoint, and I wouldn't count on it as a solution.

Few months ago I was looking for a similar solution, but unfortunately I got stuck and henceforth I dropped it.
People say you could use UDP hole punching or TCP hole punching, but I was unable to do this (I'm not a specialist in computer networks though). Whether it will work or not depends on the network itself.
Here is the question I originally asked, maybe it will be helpful to you. Honestly, I don't want to kill your hopes, but I'm afraid it may be a dead end. :(

I don't believe this is possible without some sort of central place to "find" each other. You need some way for the client the find the servers ip address to connect to.
Also, udp or tcp hole punching is an entirely different thing and uses, guess what: a central server.

If you use IPv6 it is possible - but you still need to know the other parties address. It also is possible if you use a DynDns service - but that is already a kind of central infrastructure.

Related

Basic P2P chat application on the .NET framework

I am attempting to make a chat application on the .NET framework that will be able to communicate over the internet and not just LAN. I would like it to be P2P as to not require a central server. I don't mind which protocol it uses (UDP, TCP, etc) so long as I can send messages to almost any given IP.
All I would like to know is how to send data to another IP I know of, nothing else. I've searched around but the code is too complicated for me. (For example I've looked at the source code for torrent clients).
Help will be appreciated a lot thanks.
P.S.: I've heard about a method called UDP hole-punching if that sparks any plugs.
There is a small issue with your plan.
The server-centric approach does not serve only as a slow middle man, but also as a central point with known address to connect to, an anchor in the sea to attach to and clients connect to the static IP/name of the server.
Usually, users do not care what is their IP address on the internet...
So at the minimum, the server is good to get list of clients.
Nowadays you can use some services from Microsoft or Google or other.
Now rest of the P2P communication of clients between NAT comes with more learning: TCP_hole_punching
I would suggest reading all that stuff then look for some code or library that does it.
Here is older topic similar to yours looking for the hole punching library: tcp hole punching library
I have answered similar kind of things here Peer-to-Peer application using java, let me know if it helps or if you have any specific question about this. Basically you need NAT traversal, so you would find many different ways to achieve this based on your need. Even you can achieve this simply configuring your router by enabling UPnP.

NAT Traversal using only free STUN and TURN servers in C#

I am trying to make an online game application, which communicates with another pc peer-to-peer over the Internet.
Since both pc's are likely to be under NAT, and since I cannot afford an external server, I thought the only way is to use free STUN and TURN server, such as Numb.
However, after some research, I couldn't figure out how to use those servers to make a connection.
Is it really possible to use only those servers to do it? If it is, how would you do that?
Or is there an easier way of doing that?
I can use either UDP or TCP for this.
Take a look at the Internet Gateway Device Protocol. Is is an extension to the UPNP protocol, is very easy to use, is supported by pretty much every router out there and there are some free libs implementing this protocol.

STUN server for TCP flow

I am looking for a reliable STUN solution for the TCP flow. I have tried STUNT (by cornell University in the US) and XSTUNT (by a University in Taiwan). But they both seem old and useless.
What I want to do is to transfer files between two clients in two different networks via C#. Please let me know if you have any solution for either of the following:
And UDP-based Client/Server solutions for C#
Any TCP-based STUN server
Stuntman is a STUN server that supports TCP STUN.
www.stunprotocol.org
On that site, there's some links to some sample code, including C# implementations for client libraries. Most all are for UDP, but with a little work you can role your own C# code for TCP STUN by modifying one of the existing UDP code bases.
Afterwards, you will still need to implement a signaling service for exchanging address candidates (obtained directly or via STUN) and doing your own ICE-like connectivity checks.
For TCP, the easy solutions is to have both endpoints using two sockets. One socket or listening and another for connecting - but both share the same local port (ala SO_REUSEADDR socket option).
Another solution is to have each endpoint use just one socket. Both endpoints try repeatedly to do a TCP simultaneous connect. If the NAT's behave nicely, a connection can be made.
NAT traversal, especially TCP NAT Traversal, is not an exact science. There will always be cases where two endpoints can't get connected directly and will either have to fall back to UDP and/or go through a relay solution such as TURN.
Merge all the information above with the answer I wrote up last year on basic P2P/NAT traversal here.

Brokerless Messaging C#

I have a number of WPF clients on the same corporate network. I want these clients to share messages with each other. I don't want to run a separate server process so a brokerless solution would seem best. I have considered using PNRP but this seems to require a PNRP service to be running on each client, I'm not sure I could guarantee all the clients would or could be running this. I have also had a look at ZeroMq which looks ideal it terms of simplicity and its very lightweight, however I would need to know the endpoints for a TCP/IP style communication and each client won't be aware of the others rather they need someway to discover each other. So essentially I want a multicast style of communication but without having to use multicast since this will require me to get a range of addresses set up within the corporate network and involve infrastructure etc.
So I guess the question is are there any options I haven't considered that fit the bill?
Thanks in advance for any help.
The ZeroMQ pub-sub pattern is simple and fast until you reach hundreds of clients; you can switch to a real multicast protocol then (PGM) without modifying your application.
Perhaps you should check out NServiceBus. It is a true service bus, so no broker machines in the middle. It runs on MSMQ so your windows servers will support that out of the box. It also supports transactional messaging. It also supports a pub/sub model that should satisfy your multicast requirement.
If you don't mind using a commercial product: OMG's Data Distribution Service is a standard with several implementations that can do what you are looking for. At least one of them supports C# and does not require anything to be installed on your machines -- just the libraries. Disclosure: I work for this company.
So essentially I want a multicast style of communication but without
having to use multicast since this will require me to get a range of
addresses set up within the corporate network and involve
infrastructure etc.
DDS by default uses UDP/IP over multicast for discovery and communication, but can be instructed programmatically or via configuration files to use UDP over unicast only, or TCP. This does not affect application logics, so the conceptual multicast nature is preserved. However, if you do not have IP multicast at your disposal then you will lose some out-of-the-box automatic discovery features. In this case, you would need to know in advance the IP addresses or host names of all nodes that could potentially participate in the communication. From there, the middleware will be able to discover who of these is actually present and adjust its communications accordingly.
I think the latter is true for any solution you choose though. For fully automatic discovery, you will need either multicast/broadcast, or some known discovery server(s) running in your system.
We've written a peer-to-peer message bus, Zebus, based on ZeroMQ (transport), Cassandra (peer discovery and persistence) and Protobuf (serialisation).
It is open source and production tested https://github.com/Abc-Arbitrage/Zebus
Zebus is being actively developed and it is in heavy in-house production use. Currently there is only a .NET language binding but as the OP mentioned that he only had WCF clients this should meet his needs.
Have you considered the peer to peer protocol for WCF? See here for more details: http://msdn.microsoft.com/en-us/library/cc297274.aspx
ZeroMQ is a good choice for this. To solve the discovery problem, stand a server that every client checks in when starting and stopping. This server can also be running ZeroMQ as both a publisher and subscriber.
The clients publish to one port on the server, which binds a subscriber to that port to get check-in and check-out messages. The server in turn publishes those messages on another port (which it also binds) to which the clients subscribe.

risk related to using winPcap in place of socket

What I have read so far, winPcap allows you to bypass OS and bypass application and transport layer processing for TCP and provides direct access to the link layer.
I am planning to use winpcap to do some user application stuff and not just sniffing. I will be receiving and sending critical information using pcap which I am currently doing via sockets.
Does bypassing OS, and according to my understanding application and transport layers on my side, involve any risks?
As a side question the winpcap documentation I have found so far talks about how to programatically implement it but does'nt tell in detail what it is bypassing and how does it do that. Any link to that will be helpful.
Also, I'd like to know if anyone is using winpcap for any purposes other than network sniffing for monitoring reasons and msn.
Sure, there are plenty of risks:
The OS won't know about your privately-managed TCP connections, so it won't know that the port(s) you've chosen is/are in use. This means that it might try to use the same port for another application's connection, leading to chaos.
The OS won't know about your privately-managed TCP connections, so unless you prevent it from seeing those packets, it will send RST packets to reset the apparently bogus connection.
Your application won't automatically be notified of changes to relevant OS-managed data, configured IP addresses and routing tables. You'll likely have to poll for updates.
Properly implementing the TCP protocol is non-trivial. Most implementations, even very well-used ones, had dormant bugs that weren't found for years. Not all the necessary information is in the RFCs, either; there are places where established practice differs from the documented behaviour, usually for good reason. There's also plenty of code in modern TCP stacks specifically to deal with historical buggy behaviour in other stacks, and replicating all that work isn't simple.
There's a substantial risk of bad interactions with third party network security software installed on the host, which will expect all TCP connections to be made via the OS.
It seems like a support nightmare to me.

Categories

Resources