I am currently implementing a (UDP) p2p application in C using the "hole punching" method. I found really illustrating previous posts by J. Selbie where he explains the basics
and proceeded accordingly (post1, post2) but probably i'm missing something and only one of the peers is receiving data while the other one is not.
Here are the steps i am taking:
Setup: One of the peers is connected to a 4G cellular dongle (NAT A) and the other one is connected to a router that goes to the ISP provider (NAT B).
These are the results reported for stunclient (stuntman client) for both NATs.
NAT A:
Binding test: success
Local address: X1:48383
Mapped address: Y1:28265
Behavior test: success
Nat behavior: Endpoint Independent Mapping
Filtering test: success
Nat filtering: Address and Port Dependent Filtering
NAT B:
Binding test: success
Local address: X2:49158
Mapped address: Y2:49158
Behavior test: success
Nat behavior: Endpoint Independent Mapping
Filtering test: success
Nat filtering: Address and Port Dependent Filtering
Now, according to these results, it is my understanding, that both NATs have a reasonable behavior and hole punching might succeed (note that NAT A does not do port preservation).
Hole punching attempt:
Both clients contact a public facing server (STUN/rendezvous) by means of UDP to discover/interchange ip:port pairs. When each of the clients receive the response from the server, they send a UDP datagram to the other peer (ip:port as seen by the contacted public server), and then proceed to send some more and receive and reply the message to the address from which it came.
I am sending the datagrams using the same socket that contacted the public server, only changing destination ip:port on the sendto function.
The thing is, that the host behind NAT A (hooked up to the 4G dongle) always receives the message, and in spite of replying to the correct ip and port of destination, the other one behind (NAT B) never gets the message. Any ideas what i am missing here ? or how to diagnose the problem ??
Thanks in Advance.
This is standard and general scenario where p2p(peer-to-peer) call between cellular and wifi(ISP) network is not possible. Now why?
Why?: All of the cellular network uses a cost effective method where no user can have a dedicated public IP or NAT. Meaning mobiles public IP may change after a few hour or so. As a result cellular network provider can use less number of public IP for huge number of user. This process is done generally by assigning new ip:port for every request, which is a feature of symmetric NAT. So in your case as the NAT B is Nat filtering: Address and Port Dependent Filtering that means if the data comes from NAT A has unique ip:port for every send/request then the NAT B will filter the data and the call will fail.
Solution: In general you need a relay server hosted on public IP which will receive the data from A and forward it to B and B will also do so without doing any filtering. This kind of server is called TURN server.
Now I am not sure why your stuntman test client is detecting PRC NAT(Nat filtering: Address and Port Dependent Filtering) for both A and B. For A it must be Symmatric NAT as it is on cellular network.
Related
How we can share any type of data over the two separate networks without violating security mechanisms using UDP ?
There are a few things you'll have to remember:
Every network has its firewall, and it depends on the firewall rules, whether to allow your traffic into the network or not. First, ask your client or receiver to make changes in the firewall so that it accepts your IP address and also remember most of the systems have an edge firewall too.
Be clear with the type of connection i.e., p2p (or) server & client. It's better if it is a client & server type connection.
UDP by definition is NOT a connection-oriented protocol, so there is no state to keep track of as far as OSI layers 2-4 are concerned. All incoming UDP connections are treated as "new" or the same.
Also, see that none of the systems is under NAT connection, as the router will remember the IP and port of the device just for a while. And if there is any delay in response from client-side then the system under NAT will not know the IP or the port of the device, where it is supposed to send the traffic.
I have created an P2P application which is FULLY decentralized and is using a Kademlia algorithm to make it so. This has been tested on the local network and it completely successful.
I heard about UDP Hole Punching, however hole punching requires the peer to know about the clients IP and vice versa, however as said due to design it is impossible. As it would require each peer to keep on asking the supernode\server for new arrivals and keep them assigned and so naturally it is not too dependable especially if the supernode is down.
Due to the design of the algorithm 1 peer does not know the other peers IP address so I need 1 peer to completely open a port up for PUBLIC to be able to connect to, how can I do this, in Windows? could someone perhaps also give me suitable links that might give me a direction?
It would be preferable (but not absolute) if they use c++\c as example
I think you will have to change your architecture a little. There is no other way for NAT traversal unless you configure your NAT for port forwarding (I think you don't want this). You might need to implement three layers:
Lower layer 1: it knows about IP addresses and ports and can solve problems like hole punching or dealing with servers (which could be down but first you have no choice and second you can add alternatives for connectivity).
Layer 2: implements special naming, addressing and location services for your solution (instead of using IP addresses).
Upper layer 3: implements your p2p solution using lower layer naming and location services.
First of all, you need to examine your design. If it needs 100% connectivity between all nodes (without relays) it's probably going to fail under IPv4 since not all NATs are traversable. And possibly under IPv6 due to stateful firewalls.
Now, for the nat traversal: A solution for DHT-assisted NAT traversal is for NATed nodes to have a rendezvous node.
To keep the UDP NAT mappings open it has to regularly ping that rendezvous node.
Additionally it has to announce the address of the rendezvous point on the DHT, e.g. under hash("rendezvous" + node ID) or simply on its reachable neighbor nodes.
The rendezvous node can then act as coordination point for hole punching.
This does not require any special "supernode", just other (possibly multiple, thus eliminating the SPOF) nodes in the network that are not NATed and can assist.
Additional mechanisms such as UPnP IGP, NAT-PMP, PCP and ultimately instructing users to forward the needed ports can also help to reduce the need for nat traversal.
Due to the design of the algorithm 1 peer does not know the other peers IP address so I need 1 peer to completely open a port up for PUBLIC to be able to connect to
First of all this will only work for Full cone NAT. For other types of NAT that public IP:Port you open will only work for specific destination. In your case you don't know the destination so it's impossible.
In case of full cone NAT, you send a packet to a random address with low TTL value so that the packet drops in the middle and doesn't reach that address. If it reaches than that address's NAT might block you. If you do this then a port will be opened for anybody to send you a packet. You need to keep sending packets after some short interval for that port to be remained open. Here is a problem that you can't choose which port to open in the NAT. The NAT will assign you a free port on its own.
Finally I don't see any point doing any of the above if peers can't exchange their IP information with each other. You should use a signalling protocol like SIP or XMPP to exchange IP information between peers.
To learn more about NATs please read this answer.
RFC 5780 for STUN defines a Response-Origin attribute for STUN messages responses sent by the server back to the requesting client.
It describes it as:
The RESPONSE-ORIGIN attribute is inserted by the server and indicates the source IP address and port the response was sent from. It is useful for detecting double NAT configurations. It is only present in Binding Responses.
How does the client use the server's source IP and port to detect double NAT configurations? Couldn't the source address information be just as easily read from the UDP packet's source field, seeing as inbound NAT only re-writes the destination address and not the source address?
Server can tell two things:
i) What IP address it sees for you. If it does not match your ip address, you know there is a NAT between you and the server. You have been translated.
ii) What IP address it sees for the remote peer, and the IP address the remote peer communicated to the server. If they don't match, the remote peer is behind NAT too.
Hence, you can find whether you are dealing with a double-NAT situation.
Now this is not to be confused with situation where there are two NATs between you and the server for example. But in this case, you don't need to worry, because the server will work with the last NAT on your way from you to the server.
I have took a look to STUN Server settings in openfire, and this statement from there:
"In order to act as a STUN server, two different public IP addresses on the same machine are required, as well as two different port numbers for each IP."
I have researched on google, and generally stun servers need two public IPs, what is reason for that?
For attempting to establish P2P connectivity, the STUN binding request and response to/from the STUN service's primary address (IP and port) is all that really matters. The mapped address returned in the response body of this request is passed (via XMPP or other service) to the remote node that the local client is attempting to establish directly communication with.
The second IP and port that the STUN service listens on are useful for determining NAT port mapping behavior and NAT filtering behavior.
By making binding requests to the alternate IP:port on the service, a client can discover if his NAT has consistent mapping semantics for local ports. In the event he gets different port mapping values for each test, the client can conclude it is behind a "symmetric NAT" - which are the most difficult to traverse for P2P.
By sending up a bind request with a "change request" attribute that asks the service to respond from the other IP or port, a client can detect if his NAT just filters datagrams from remote hosts based on IP and port, or allows for datagrams from alternate ports on hosts it has sent outbound datagrams to.
The mapping behavior and filtering tests only provide limited information for subsequent P2P connections. In the case of determining a symmetric NAT is between the host and the Internet, some implementations may observe the NAT to have a consistent incremental value of the port value in each binding response. (e.g. the external port observed by the STUN service increases by one). As such, the client can offer an IP and guessed port number for the remote client to try to send to instead of the one mapped back from the first binding request. Or the client may use this behavior/filtering test for logging. Or to automatically allocate a relay in the event of symmetric NAT.
Because in some rare cases, the behavior of NAT translation is a function of the target IP address. Meaning, you must 'ping' two different IP addresses to find the precise behavior of the NAT (does it depend of the target IP address or not?)
If you 'pinged' twice the same server with two distinct ports, that would not cover this case properly (i.e., you would not be covering all your bases).
P.S.: The two IP addresses don't need be on the same server, it could be different servers.
I'm guessing that it is required to identify the type of NAT being performed - some NAT will use the same source IP address and encode the session id via the port number (I think it's called cone NAT but not sure), some NAT will use a combination of source IP and port to encode the session ID. The answer the STUN server needs to give the client is different based on NAT type.
Such as Skype/Team viewer/Logmein etc application, which send audio/video behind NAT (behind firewall). But when i make a small tiny application which send text to another NAT location it failed to do the same.
Example:
Sender:
-> Public ip: 91.1.2.3 My lan ip is: 192.168.1.2 with port 14446 udp
-------> Data format: RTP packets
Receiver:
<------- Data received: 0 packets
-> Public ip: 92.1.2.3 Friend lan ip is: 10.0.0.2 with port 14446 udp
* same in both way
How others does this? What is the way of doing peer 2 peer application development to overcome NAT issues? Always we have public ip's and mostly it has NAT issues.
But how does then Skype works in such cases too? Do we have a audio/video port range for UDP or always UDP is open from anything? But mine does not work above range ports for UDP i also tried. What is the secret? that is making me curious!!.
Note:
My goal is audio packets handling where i believe too much filtering or firewall cause latency and delay and other issues gets involved relatively too. So i would like to know very clearly for my application that some of the ports (which port ranges?) can be used for such purposes, where it really not blocking development stress.
There are a number of types of NATs, which vary in what traffic they'll allow in.
See the Wikipedia article on NATs
For most NATs, STUN will let you open ports AND find out what port you opened (may be different than the port you sent from). In SIP and RTSP you'd typically provide the external IP and port determined by STUN to the other end.
A fully-symmetric NAT means that STUN won't let you use a 3rd-party server to prop ports via STUN, so you'll have to use UPnP (if enabled) or map ports in the router (or set up triggers), or you'll have to play evil games to make both sides think they initiated the connection. (Not easy and not guaranteed.)
See the ICE & TURN specs (RFCs) from the IETF for detailed mechanisms to traverse NATs - though note that in some cases you must use an external proxy to forward packets.
One common solution is that the client program connects outward to the server and thus establishes a connection. Most firewalls allow outward connections - the assumption being that you are trusted and can always connect to the outside. When the server then wishes to send a message to you, it responds on the open connection.
I believe the port that you use is what is usually used to determine if it should be allowed or not. Certain ports are always let through. I'm not sure of the exact ports, but that will be different for all NATs and firewalls.