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.
Related
I was wondering if I could create a TCP client on machine A and connect it to a remote host (S) and then close the connection from client side and create a TCP listener on the on the same machine (machine A) with the same port that was used for client(say port 1234). the server which now has the A's Endpoint , sends it to another machine (B) and B can connect to A on A's public Endpoint(say port 4567) and the NAT on A's network redirect the SYN to A because it still has the translation(4567 -> 1234) in it's table.
I want to know how much time is there between disconnecting the first connection and connecting of the node B.
I agree wtih Peter Duniho's comment. But I am answering your question with usual NAT behavior.
What you want to do will not work. NAT doesn't behave same with both UDP and TCP protocol. What you said will work if the protocol was UDP and the NAT type of A was full cone.
Why for TCP won't work
NAT allows incoming SYN from a IP:Port if a SYN was sent previously through the NAT to that IP:Port. And these two incoming and outgoing SYN must cross each other outside the NAT. If before outgoing SYN crosses the NAT the incoming SYN arrives, then NAT will drop the packet and may send RST message as reply. This procedure is called TCP hole punching.
This hole punching will not work on all NATs. For this to work NAT needs support simultaneous open connection.
How long does NAT keep a TCP translation field in it's table
The translation may get timed out and this time out value is totally implementation dependent. Also NAT can receive a TCP RST message and remove the binding.
So bottom line is its hard to define NAT behavior in general as this has no specified protocol. You have to do experiments and find out for yourself.
I’m very new to TURN and I want to create an experimental application which requires a TURN server for its udp communication.
I have used UDP hole punching already and I’m familiar with the subject.Also I know about NAT types and UPnP for port mapping.
To solve port mapping in Symmetric and Port restricted NATs with routers without UPnP capability I must communicate with a TURN server and send UDP packets through it.But I don’t have any idea how to communicate with TURN server and how to work with it in C# programming.
I’d appreciate it if you could point me to the right direction and give me some pointers.
Thanks.
I can answer about how to use TURN for completing a relay call. But to know how to form messages for TURN you need to read the RFC.
How TURN Works
TURN is needed because its impossible to bypass some NATs filtering and establish direct connection with a host. As TURN sits on a public IP, anyone can connect with it.
So hosts under symmetric NAT can send allocation request to TURN server and TURN server will allocate a port for the host. Now the host will have IP information of the other side. And it will send another request to TURN specifying the IP info of other host and packets from that other host in the allocated port will be forwarded to the host behind the symmetric NAT. And packet from the host behind the symmetric NAT will be forwarded to the other host. This way they create a relay connection.
You really need to read the RFC for TURN to know this in more details. Everything you need is there.
#tahili I see this is an old post but I want ask you a question.
If Turn server can reach the peer's server-reflexive address why can't the client just send packages directly to peer's reflexive address. If client can't send data to peer directly because of mapping problems how does the turn server can send a udp to peers server reflexive address.
Mind you peer has not contacted the turn server yet "relay address of the client", so there is no mapping between the turn server(client's relay address) and the peer.
Knowing peers reflexive address alone is nor enough. After all we can just send data directly to the peer.
Assuming is peer is behind NAT as well.
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.
I'm currently trying to make an online video game, which currently uses TCP to send packets. I want to use UDP, but I'm extremely new to UDP and I'm having some issues.
When I test my server/client(s) on the same computer (localhost), the packets seem to be interfering with each other.
For example, if the client sends a packet to the server (UDP, 127.0.0.1:1338), the client ends up receiving the packet, since the client is also listening for packets from 127.0.0.1 on port 1338. Similarly, when I try to test 2 clients and 1 server, the clients may send out packets which are meant for the server, but are picked up by the other client.
How can I test UDP on localhost since all packets are being received from/sent to 127.0.0.1:1338? Do I need to implement some sort of layer in my packets that distinguishes if the packet is meant for the server, or a specific client?
Only your Server should listen on the defined port number (1338). Each client should select a free port number and send the server this port number. The server has to store the client information and send then the packets to the clients in this client list.
The clients should also send a goodby packet when the client is closing to know on the server side which clients are still available and which aren't participating anymore.
You should also implement some kind of housekeeping in this client list. For example store the timestamp of the last received packet from the client and remove clients that haven't sent data for some time (crashed client, lost connection ...) from the list.
An additional layer will not help - because the server may never actually get the packet.
Make the ports on the server and client configurable. That way you could have different ports on the same machine for testing and change it when going to production. Just remember you need to configure both ports in both the client and server. This is a good practice anyway.
You still have another problem - of several clients residing on the same machine and listening to the same port. You can have a random port for each client (the client selects one in random and then notifies the server). Or you can try binding to different IP addresses (one will use 127.0.0.1 an another will use the real IP of the PC), but it's not extensible.
If you are going to use this in a LAN setup, then you can always filter the received packet based on the sender's address -- recvmsg() of UDP allows you to retrieve sender's address and port number. If you are going to use this in a WAN setup, then this likely would not be an issue unless you are trying to do multicast. And, even with multicast, duplciate packets are not send back to the receiver. You can use IP_MULTICAST_LOOP to disable this option.
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.