NAT translation not working from inside the network (hairpin condition) - networking

I'm writing a P2P application. Peers regularly ping a main server to update their current IP/port, so when a peer wants to reach another one it can ask the server for that information. For now peers use UPnP to configure the NAT (for classic home setups) to be accessible from outside.
So everything works, except when a peer's client tries to reach another (or the same) peer's server and both are behind the same NAT. Since in that case the client is trying to reach its own "external" (public) IP address from behind the NAT, the NAT doesn't do the port forwarding and is unable to route the IP packet.
For now I'm thinking of two solutions:
query the NAT with UPnP to see to which local IP the port is forwarded
store on the main server the internal IPs of the peers
Can you think of other solutions? What strategies do mainstream P2P applications implement to solve this problem?

Since in that case the client is trying to reach its own "external"
(public) IP address from behind the NAT, the NAT doesn't do the port
forwarding and is unable to route the IP packet.
This is known as the hairpin condition. Not all router/NAT solve this properly. The solutions are:
a) Check whether your router/NAT can be configured to enable 'hairpining'. This solution works iff you control all router/NATs in your deployment.
b) Buy another router/node allowing this. Just like a), it works iff your control all router/NATs in your deployment.
c) If you can get obtain the port information for from UPnP, this is a solution too, but not all Router/NAT know or support UPnP. It does not cover for all cases in large deployment.
d) Using multicasting to 'discover' other nodes on the LAN and even communicate with them is a common solution to this problem. You need to agree on an IP address and have peers listen to it.
e) Storing the private IP address on the server is a solution too, but it requires more storage capacity on the server than solution d. There is a timeout (i.e., expiration of data validity) to handle too.
f) Use a TURN like communication between peers (i.e., communication between nodes pass through central server). This solution is rock solid, but not the most efficient in terms of bandwidth consumption.
Hope this helps.

Interactive Connectivity Establishment (ICE) was specifically developed for solving that type of NAT problems. It uses STUN and TURN to achieve the result and is used in modern p2p applications. (e.g. Voicechat)
The PJNATH library has a document explaining
unlike standalone STUN solution, it (ICE) solves the hairpinning issue, since it also offers host candidates.

Related

How to connect to peers in obtained from bittorrent

I'm looking to build a bittorrent client in Ruby (although language is not important over here).
I read a BEP specification which says querying at /announce (without DHT support) to tracker would give a list of peers currently connected for a given info-hash.
To examine this. I created a torrent file and I found that tracker return the IP of my machine along with the port (which i confirmed is the running port of Bittorrent client on my machine i.e Utorrent)
But here is the problem the Peers info returned the IP of my ISP i.e 111.125.209.41 (the public facing IP since I'm behind the NAT).
Now I cant connect (via TCP) to the Process running on my machine with the public facing IP of my ISP.
Can anyone suggest how does bitorrent work on this and what should I do to solve this.
It could that over UDP Bittorrent would be using UDP hold punching not sure what happen on TCP.
There are two separate concerns.
How do peers on the internet (aka 99.99999% of the world) connect to your NATed node
How do peers inside your network connect to a node on the same network.
The first is achieved by various nat traversal methods, including negotiating with the nat device or manually configuring it.
The second issue either requires a router capable of hairpin routing in combination with a forwarded port or local peers discovering the internal address through other means, such as LSD.

find out/predict the port the router is/will be using for a given connection

I know that ipchicken.com will tell you your router's ip address and the port it is using for your connection. But can this information be obtained "locally"? (Without relying on a website).
What I want it for is establishing a connection between two random hosts...without a "dedicated server" in the middle. My problem is to reach through the NAT. I think the best bet is a kind of TCP hole punching, where both hosts connect somewhere and then just tell each other (it can be by phone or chat or similar) the current ip address and the port number their routers are using. It should trick the routers into forwarding the packets to the hosts, albeit coming from a different source than they originally connected to.
Is it possible to find the port number your router is using to patch you through in a more local manner than ipchicken.com?
Are there any ideas on other possible approaches to this problem?
EDIT: Setting port forwarding on the router is not an option in this case, as many people (including me) do not have admin powers over their routers and I do not want to impose such a task on the "users" of my application
The router would use a different source port for every outgoing connection, so checking based on an outgoing connection will not work for your use case.
For an incoming connection, i.e., if you want to reach a specific machine behind a NAT device (like a home router), you'll have to explicitly open up some ports on the router and set up forwarding rules. The router would then listen for incoming connections on that port and forward it to a machine:port based on the configured rule.
How you do this would depend on the specific router make/model. Search the web or logon to the admin interface and look around, it should be easy to find. However make sure you understand the security implications of opening up a port on your router!
UPDATE based on edited question:
Without port-forwarding and if both devices are behind NAT, your only solution is to have an intermediary server! If only one of them is behind NAT, you can have that machine initiate the connection.
You could use a Stun server as the external globally reachable server.

if I have a local ipv4 address can I use it from outside a network to talk across a NAT

I have an application where I want a device inside a network behind a NAT to make a call to the public network giving a server its local address, Later, say 10 or 20 minutes later, I'd like the server to be able to contact the device inside the network.
Is there any protocol generally supported by firewalls/routers etc. that would direct me to the local node if I provided its actual current local address?
Thanks
No, there is no such protocol. Moreover, in the case of multiple NAT, the local node can only know its address behind the innermost NAT, and the server can only know the public address outside the outermost NAT, so you have no means of mapping through multiple NATs, or even knowing how many exist in the path.
The local node will have to initiate and maintain an open connection with the server if it wants to receive anything from the server.
No there is not a protocol for mapping the IP address, though you can use portmapping/port forwarding to map specific a port to an IP Address
This is the sort of thing UPNP is meant to solve. Note that there are still challenges -- the network equipment needs to support it and the feature needs to be enabled. Many network admins will not enable it for good reason.

how to redirect connections to IPs behind the NAT to NATted (public ) IPs at the source?

I have an application that relies on IP addresses for communication (Domain names simply does not work. :(... )
Its function is to connect to its peer on the other machine and send data over after establishing trust. During the "trust establishing" phase they both exchange their IPs for future communication. They both are behind the two different firewalls and are NATted. One is in our NATted office network and other is in the cloud NATted behind their firewall. The applications knows their respective private IPs and exchange that (the 10.x.xxx.xxx range), when they try to connect back to each other (using the private IPs with range 10.x.xxx.xxx) for transferring data they fail. The connection is TCP and the port range is pretty varied.
I am curious if there is anyway I can hard code (for this one time) a rule (at may be firewall level or some place outside my application) that says if there is a connection being initiated for IP address 10.x.xxx.xxx then redirect it to 205.x.xxx.xxx?
Private IP address ranges like 10.x.y.z are, by their very nature, private.
You can't do any meaningful resolution unless each node in between the endpoints has rules in place to translate these.
Translation is tricky, all the main tools you would use cater for static translation (port forwarding, e.g. where a particular port is forwarded to a particular IP). This is one avenue, but it is a hacky one (it requires you to open lots of ports, procedurally update your router and probably have some sort of broker server to maintain mappings).
Alternatively, you could run the isolated networks over a VPN, which would give your endpoints mutual private IPs which you can use to connect to eachother. It would simply be a case of binding to this new address and communicating across the VPN. This would also potentially encrypt your communication over the internet.
Other possibilities are to use NAT/TCP punchthrough techniques which can allow traversal, but these are really a patch to a broken network topology (Read up on IPv6 to see how this can be alleviated).
Alternatively, you could route all the connections over a proxy, but this will complicate matters compared to a VPN.
To answer the question about hardcoding a rule, port forwarding is the solution here. It will obviously depend on your router configuration for the peer accepting the connection, but this client should have the port target port forwarded to the machine. This will obviously not scale very well and is really shifting to a server/client architecture for one connection!
Depending on your hardware, you may be able to forward a range of ports (if a single port cannot be established) and limit the port forwarding to certain incoming connections (the external IPs).
Information on port forwarding can be found at http://portforward.com/
This sounds a lot like what you'd want out of a VPN. Is there anyway that you could set one up? Basically the Site-To-Site VPN between you and the cloud would say 'oh hey, here is an ip located on the remote network, go ahead and connect through the link'. Would this kind of solution work in your case?
Something along these lines: http://i.msdn.microsoft.com/dynimg/IC589512.jpg

How to applications listen in local network on internet?

I was wondering that how application like skype ( a popular chat client ) works in local network with one router, How it can listen on particular port?
for example:=
In one network A and B are two machines running skype , gateway of both is G1,
now how A and B will have same IP on internet that is of G1, but how can they ensure that they are listening on different ports? How can they ask to router G1 for unique port.
I want to make a simple text chat server on linux. How can I have connections between two different computers in two different networks?
Solution to your problem is to have a forwarding server somewhere in the net.
Different programs use different means to connect to each other. But every chat server, including Skype, has a server, which forwards data or information about subnet IP/port availability.
There are two types of clients: "listening" clients and "passive" ones. Listening clients have direct access to Internet via router port forwarding, and "passive" ones have to use additional tricks to get their hands on external data, line external servers or additional ports to listen.
The point is, not clients connect to each other, but they connect to a server, which then connects back to them to verify they are available, and, if at least one of them is not firewalled, direct another on to connect to the first one, excludint itself from further communication. And if both are firewalled, then is has to forward their messages through itself.
Host Discovery
Manual discovery, client A knowns who client B is
Discovery through broadcast UDP which is used by lot of games for LAN play. A client sends out a packet to the broadcast address for their subnet. The peers can choose to pick up this broadcast and respond. The downside is that this is limited to the current subnet. The more general INADDR_BROADCAST (255.255.255.255) works for all subnets on the local-link, but it cannot be routed, so won't work over internet (this is what DHCP auto-configuration uses).
Discovery through a central (Rendezvous) server. Each individual client knows the address of the server, and the latter informs them about each other. This technique is used by IRC, Voip, IMs and by most 'peer-to-peer' networks.
Communication
After the initial discovery is done you want to be able to talk to eachother. On the internet this can get tricky. Most people nowadays have their own router and sit behind a NAT, so direct connections are impossible.
Using a Rendezvous server, you can possibly talk to each other using the server itself. client A tells the server what to say, and it in turn tells client B, since both clients have an outbound connection to the server.
It is possible for the clients to talk to each other without the server proxying. This requires either DMZ, port forwarding or UPnP. DMZ will basically forward all incoming connections on all the ports to a given local IP. Port forwarding only forwards certain ports to local IPs. UPnP is a bit more advanced, the client requests that the router temporarily forwards a port to it, and you tell the other client via the rendezvous server where to connect.
Chatting app implementation
The easiest solution to your problem is most likely to use a central server, which is known by all the clients, that proxies host discovery and possibly the communication between the clients. If you want the clients to communicate directly, you can just proxy host discovery, and then let either DMz, manual port forwarding or UPnP do the rest.
Another solution would be to just have direct communication through NAT traversal techniques discussed above, and do manual host discovery.
Yet another solution would be to use a public webserver and 'abuse' its ability to insert content to chat with each other.
You need a central UDP Rendezvous Server.
After the initial connection from the client to the server the UDP clients can be redirected to talk to eachother directly even if firewalled.
The trick is to open an UDP connection from the inside.
Check out Real-Time Media Flow Protocol and how they use it.
Check out UDP Hole Punching
alt text http://labs.adobe.com/technologies/stratus/images/p2pvideo_250x215.jpg
Traditional NAT servers replace the source address and port with the address and a random port number of the external interface of the NAT server. This works well for simple protocols such as HTTP and SMTP, but it can create problems for more complex protocols that require multiple response ports on the external interface of the NAT server. NAT servers also aren’t aware of information stored in the data portion of the application layer header without the help of NAT editors and similar software fixes.
Windows XP’s answer to these problems is NAT Traversal, which can automatically allow the UPnP-enabled NAT client application to communicate with a UPnP NAT device. NAT Traversal provides methods to allow the UPnP client to learn the public IP address of the NAT server and to negotiate dynamically assigned port mappings for UPnP NAT client applications.
NAT Traversal features can be built into any hardware device or software application. Applications that commonly cause troubles for NAT devices but work well when UPnP-enabled include the following:
Multiplayer Internet games
Audio and video communications
Terminal Services clients and servers
Peer-to-peer file sharing applications
When these applications are UPnP-enabled, access through the Windows XP ICS allows them to work seamlessly.
Unless A and B are actually "listening" to the responses to outgoing requests, your router will need to be cofigured to forward the relevant port numbers to the relevant hosts. This isn't something that you can request in the code, it's something you need to configure on the router itself.

Resources