How to create a P2P connection when both clients are behind NAT - c#

Is it possible to establish a direct connection between 2 clients that are both behind different NATs?
Of course I realize that to some extent a server with a public IP will be essential, but I don't want it to be a proxy. Take a look at the following scenario:
I don't want to have anythig to do with configuring network devices. I just want to do it in code.
I don't want the server to take part in file transfer process (for performance reasons)
we have: client A, client B, and a Server S and it looks somewhat like this:
A--[Router1]--S--[Router2]--B
A connects to S and authorizes
B connects to S and authorizes
A wants to send a file to B
A asks S for a connection to B
S [does it's magic here] and A now has a connection to B
A starts to send a file
S goes down (or at least the file transfer bypasses is)
there's still the connection between A and B
A continues sending the file to B
My questions:
Is that possible?
How to do this?
Have encountered a sample project that can do this?
I found WCF / WPF Chat Application, but it turned out to be a proxy.
I also found some posts suggesting using UPnP and NAT Traversal, but none answered my 1st question directly so I didn't dig deeply into it.

The term you are looking for the "magic part" is called NAT Hole Punching. Unfortunatly the topic is a bit too broad to be explained fully here on how to accomplish it, but now knowing the correct term should at least be able to get you started on looking for the correct tutorials.
Here is the summary of the algorithom from the UDP Hole Punching page.
Let A and B be the two hosts, each in its own private network; N1 and
N2 are the two NAT devices with globally reachable IP addresses P1 and
P2 respectively; S is a public server with a well-known globally
reachable IP address.
A and B each begin a UDP conversation with S; the NAT devices N1 and N2 create UDP translation states and assign temporary external
port numbers X and Y
S examines the UDP packets to get the source port used by N1 and N2 (the external NAT ports X and Y)
S passes P1:X to B and P2:Y to A
A sends a packet to P2:Y and B sends a packet to P1:X using the same source port as the conversation with S thus "punching" a hole in
the NAT towards the other host
If either host receives a packet, the hole punching is successful and both hosts can communicate.
If both hosts have Restricted cone NATs or Symmetric NATs, the external NAT ports will differ from those used with S. On some
routers, the external ports are picked sequentially making it possible
to establish a conversation through guessing nearby ports.
Whether or not it will work is highly dependent on how both endpoint's NAT routers behave, it is very likely that a significant portion of your uses will be paired up and both have routers that are not "hole punch friendly".
In your situation I would have my software try these steps in order.
Check and see if we can just connect (The user did manual port forwarding)
Use UPnP and open a port
Use some form of hole punching using a public server as the go between
Use another peer that does have ports open as a proxy for the data (a Supernode).
Use a server I host as a proxy to forward the data.

Related

UPnP hole punching can't use external IP to access device on local subnet

I have a somewhat unique situation where I require the ability to perform NAT hole punching for a multi node peer to peer type application; where all nodes must reference each other from publicly accessible IP addresses, even when some of those nodes might reside on the local subnet.
I have been able to successfully map ports with help from this question (UDP hole punching implementation) using Open.Nat.
My code is basically as simple as this:
var discoverer = new NatDiscoverer();
var device = await discoverer.DiscoverDeviceAsync();
await device.CreatePortMapAsync(new Mapping(Open.Nat.Protocol.Tcp, port, port));
This successfully creates a map in my router
I can now successfully connect to this IP and port number from an external network (tested on mobile data connection) by doing something like this
TcpClient client = new TcpClient();
client.Connect("publicip", 6968);
However when I attempt to connect to the same public ip address from the local subnet the connection will fail with 'No connection could be made because the target machine actively refused it?'.
I have used wireshark to see if any packets land to the target machine and it appears they do not.
Obviously it is clear that the router is probably failing to forward/route the connections correctly on the local subnet, so what I am trying to understand is if this is a known limitation of the UPnP protocol or specific to my router? Perhaps there is a trick when you create the mappings that I have missed?
I note that my router appears to use MiniUPnP http://miniupnp.free.fr/ Version 20160321
I realise this is a tricky question to answer but hoping that we can get some clarification of what UPnP should be doing in this situation from an expert.
EDIT:
A bit more context to my question; let me elaborate why I have such a requirement. I am using Akka.NET clusters on mobile devices across network boundaries, the key point to remember with Akka clusters is to successfully get a Akka.NET cluster to form all members of the cluster must be bio-directionally reachable to one another.
Now consider a situation like this
My goal is to only have to assign a static ip to the server node and allow all the cluster nodes to move in and out the network boundaries seamlessly. The ideal way to achieve this is to assign publicly reachable addresses to each node on the network regardless of where it is physically located.
This isn't really something you can fix, and it isn't really specific to C#. Most routers will only match NAT packets that arrive on their internet facing interface. If you want to allow for multiple nodes running behind the same NAT to connect directly to each other, you will need to implement another solution.
For example, you could share each node's private interface addresses. Then attempt to connect directly if the public address matches.

UDP P2P connection behind NAT

I want to make P2P connection between 2 clients behind NAT. I studied methods to make it work and I want to try "UDP hole punching method".
So...
I made a server in PHP, which can send connection details to clients on demand (Like remote IP, remote port).
Source code as example is here: http://pastebin.com/FdiKMSFq
Next, I made an Client in C# which permanently connects to server and ask him about another client info. Client recieves remote IP and remote port (used for connection with server) of another client and tries to connect.
Full source code here: http://pastebin.com/VUJyZivW
First step (connecting, and asking for details) are OK, but when client (A) connects to another client (B) and send some data (A->B), client B do not recieve any data.
I set both IPEndPoints working with port 2000. But it didn't work anyway.
Example:
A: 192.168.1.11:2000, server gets 32.14.15.16:56666
B: 192.168.1.5:2000, server gets 32.99.15.16:56699
A tries to connect on 32.99.15.16:56699 and send some data
Looking over your example, B's NAT is going to drop the packet destined for its public endpoint (pair of address and port). This is because B's NAT sees this as an unsolicited request.
In order for B's NAT to let the packet from A through, it has to think that B had communicated with A prior, thus considering the request solicited. The NAT keeps an internal table to track this.
The way you can establish the connection is by having B send a packet to A's public endpoint (32.14.15.16:56666) as well. Doing this will "punch" a hole in B's NAT. In your example A is already "punching" a hole by sending traffic to B.
Keep in mind that this will only work if at least one of the NATs consistently translates private source endpoints to public source endpoints (regardless of destination address). This is because otherwise the public endpoint seen by your server may be different than the one seen by the P2P peers' NAT even when the peers are using the same private endpoint.

How to spoof an IP Address using a socket?

I'm working on a website testing framework, and I'd like to be able to spoof the user ip. I've read, that software like Loadrunner can do this, and I'd like to be able to do this as well.
A tutorial on how to use a socket normally can be found here, but I if I want to spoof the ip, I'll have to somehow edit ip header. Is this done on socket level, or is there an other, deeper level in .Net, which would let me do this?
You can't anymore, as access to raw sockets has been restricted in the desktop versions of Windows:
On Windows 7, Windows Vista, Windows XP with Service Pack 2 (SP2), and Windows XP with Service Pack 3 (SP3), the ability to send traffic over raw sockets has been restricted in several ways:
TCP data cannot be sent over raw sockets.
UDP datagrams with an invalid source address cannot be sent over raw sockets. The IP source address for any outgoing UDP datagram must exist on a network interface or the datagram is dropped. This change was made to limit the ability of malicious code to create distributed denial-of-service attacks and limits the ability to send spoofed packets (TCP/IP packets with a forged source IP address).
A call to the bind function with a raw socket for the IPPROTO_TCP protocol is not allowed.
Note The bind function with a raw socket is allowed for other protocols (IPPROTO_IP, IPPROTO_UDP, or IPPROTO_SCTP, for example).
(From Dev Center - Desktop - TCP/IP Raw Sockets)
You can create a raw socket fairly easily:
Socket s = new Socket(ip.AddressFamily, SocketType.Raw, ProtocolType.Ip);
At which point its on you to construct the appropriate datagram (which would be a separate question if you don't have the documentation on how to do this to hand)
LoadRunner can spoof IP addresses only when the actual IP address exists on the Load Generator. So, if I have 200 IP addresses assigned to my host then I can distribute my load across these IP addresses instead of having least cost routing or primary vs secondary network interfaces come into play in the operating system. This is true not only of LoadRunner but other application performance testing tools that spoof, the address needs to be assigned to the host generating the load.
If you are looking for raw spoofing solutions where the IP address need not be assigned to the host for testing purposes then you might consider network performance testing tools, particularly the chassis-based solutions, from companies such as Spirent and Ixia. These network solutions can also generate tens of thousands of unique bogus MAC addresses to go with the bogus IP addresses if needed.

Can lidgren-network library connect directly peer to peer given both IP addresses

I am using lidgen-network library 3 to try and create a peer to peer connection. I am new to network programming which is why i'm using this library.
Using the DiscoverKnownPeer() function i have been able to connect within my network. What i have read online is that i need to do a NAT punchthrough which requires a running server that is outside the router. I am hoping for a solution that doesnt require this extra server.
If i can store both ip addesses on a web server, and get create a web service to send the ip's to each respective client through XML, would I be able to create a peer to peer connection?
Thank you in advance.
No, you won't be able to establish a connection through NAT without a rendezvous server
NAT stands in your way because even if you know the IP address, that only gets you as far as the router. The router receives a request coming from the internet, and doesn't know which internal IP to send it to, so it throws it away.
NAT punchthrough works by making both peers send outgoing request to each other, the router then "knows" that packets directed at its public IP on the given port should go to the given computer.
So, you need to connect both computers to an external server not behind NAT, and then use that external server to coordinate connecting the two NAT obscured peers together (this is the peer introduction thing that Lidgren has built in).
I know this is old but...
You didn't specify that using the DiscoverKnownPeer() was necessary in your setup. If it isn't then you can setup peer to peer by appplying port forwarding rules in your router.

Testing NAT Breakthrough Code

I am very interested in at least trying to implement NAT break through for my senior project.
(I am doing a networking API).
It's not even a requirement of my project, just a interest of mine.
I know the basics of how it works, correct me if I'm wrong:
Two clients connect to a server that isn't behind a NAT and this server, knowing the IP of these two clients, tell the clients to connect to each other at the same time. Thus the "Breakthrough".
This seems not terribly easy or terribly hard to code.
However, the part I'm stuck at is the testing of this. Is there a reasonable setup I can do with just one router/one NAT and my three available computers?
Thanks for any advice!
In terms of code/theory on NAT breaking, I cannot offer advice, but I can make some suggestions on setting up a test environment.
You can download a copy of m0n0wall and run it inside of a Virtual PC image (both free). This will give you a second router w/out purchasing any additional hardware. With this extra router, you can create a seperate subnet for your two clients.
Another, easier to grasp option is simply to pickup a second router, you can get a good one pretty cheap.
Then setup your existing router and server as they are now, a 192.168.1.x /24 subnet; then setup your second router (m0n0wall/hardware router) as 192.168.2.x /24 subnet, and plug the second router's "internet" port into one of the "PC" ports on your first router. Then plug both clients into the second router.
(I realize thats a bit confusing, comment if you cannot follow what I mean)
Let me see if I have this straight. You have two clients that are both behind NAT and a server that is not. Both clients connect to the server and are informed of the public facing IP address of the other. Since each now has a destination, they disconnect from the server and connect directly through their respective NAT boxes to each other. Is that your thinking? If so, I may have some bad news for you.
In order for this to work at all, you will have to have dedicated ports set up in each NAT configuration to forward at least one external port to a predefined internal IP address/port number. In a generic NAT setup outgoing connection requests will be captured by the NAT which will open a temporary external port. That external port number is used only for communications to that one originating address and port. When the connection is closed, that external port goes away and will be reassigned for another connection later. So if both clients talk to the server and then disconnect, the information the server sent them is now invalid.
Assuming you've worked around this somehow, it should be fairly easy to just connect both clients to the "internal" side of the NAT and the server PC to the "external" side. Then you have to hope that your NAT box is smart enough to loop back packets from one local external port to another. I'm sure that netfiler could be configured this way but I doubt a home internet "router" (e.g., Linksys, NetGear, etc.) would do it of the shelf.

Categories

Resources