Can I determine if my router is using NAT?

Started by
7 comments, last by ItsDan 14 years ago
I'm trying to write the networking part of my game. It uses fully connected TCP sockets in C#. The problem I'm having is getting the players fully connected when 2 players including the host are behind a NAT and a third player is trying to join. Is there a way for me to tell if my LAN is using NAT? If there is, can I just use System.Net.Dns.GetHostEntry(IPAddress.Parse(playerIp)).HostName and compare it to my host name System.Net.Dns.GetHostName() and if they're equal then I know we are both behind the same router with NAT?
Advertisement
If all the computers are plugged in to the router and they are all on the LAN there is no NAT happening. NAT is when you go from one side of the router to the other.

If one of them is a wireless client you may have your router set up to put each wireless connection in it's own jail. That's a standard option for routers but is disabled by default. Log in to the router and check the configuration settings to see if that's enabled; again this only matters if someone is on wireless and it's all wireless clients that have a problem.

-me
Ok how about this. Is there a way when a player connects to my listening socket for me to determine that we are both behind the same router using NAT and not allow him to join my game?
I don't understand what the problem is. Can you please explain exactly who is where and what the problem is?

If you're both behind the router there is no NAT between your 2 computers.

-me
Player A and B are on the same network, behind a router using NAT.
Player C is on a separate network.

Player A hosts a game.
Player B connects to Player A to join the game.
Player C connects to Player A to join the game.

Player A now has to tell Player C how to connect to Player B.

If Player A sends Player C the ip:port his socket is using to connect to Player B then Player C won't be able to connect since the ip is just the local one used in NAT.



My fix for this is that everyone queries whatismyip.com to get their ip, and then sends that ip to the host who stores it. In that case Player A can send Player C the stored external address of Player B (which would be the same address Player A uses, but a different port) and then Player C would be able to connect.

The problem is if the query fails, I don't think there is a way for Player C to connect to player B. So I would like Player A to block all connections which come from his own network, but only if his network is using NAT.
Why not just use a client server setup (have A run the server if A starts the game) and use NAT punch through.

In general any network you run from your home, or even business (with some rare exceptions) will be using NAT when connecting out to the internet, or more appropriately PAT (port address translation). The main reason being is that you a) almost never need more than one IP address per client (for consumer networks), and for business networks they also almost never need more than one per-site (for small to medium sized businesses).

There are many methods for NAT punch through, but the best solutions are ones that utilize many different methods (as some work with some routers, and others don't). One thing to especially not rely on is UPnP as many retail routers now come with it explicitly disabled due to security concerns.

Peer to peer networking is rarely a good idea for games as it not only increases the problems with regards to NAT, but also introduces many other problems (such as validation and verification to prevent cheating)

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

Coincidence! I have been doing massive NAT-related research lately. You may want to have a look at this:

Session Traversal Utilities for NAT (STUN) - Wikipedia

RFC 3489 - STUN (old version)

RFC 5389 - STUN (newer version)


Determining if you are behind a NAT (and what kind of behavior the NAT uses) without using UPnP is a bit of a pain - you need cooperation from WAN-side servers that you control, called "STUN Servers". There don't actually need to be two physical STUN servers, just at least two separate UDP endpoints (the server needs two static WAN-visible ports forwarded to it). The following tests are more effective if the STUN server(s) can be set up to have separate IPs as well as ports.


The quick-and-dirty summary of NAT determination goes something like this (I'll probably screw it up somewhere since this is all new to me):

TEST 1:
Your machine sends a UDP packet to Stun Server #1 and waits for a reply that tells you what your public IP and port are (similar to whatismyip.com but tells you your port number as well). If this fails then you probably have a firewall blocking your outbound packets (the STUN servers could be down though).

If Test1's reply information matches your host-local endpoint IP/Port, then effectively you are not behind a NAT at all and do not need to continue with Tests 2 or 3.

TEST 2:
Your machine sends a request to Stun Server #1 that tells Server #2 to send a packet back to your machine back to your machine. Your NAT will either block Server #2's packets or accept them. If it accepts them, you have the second most relaxed type of NAT and can participate in standard UDP punching.


TEST 3:
Your machine sends a packet directly to Stun server 2 (similar to test 1) using the SAME local endpoint (same host-side port) and gets the same kind of reply - your public IP/Port information that Server 2 received.

If this test indicates that your WAN IP/Port combination is DIFFERENT than in Test 1, that means your NAT is a Symmetric/Strict NAT. Symmetric NAT means that even if you use the same LAN endpoint to send a packet, if the WAN destination endpoint is different, your NAT allocates a DIFFERENT public port. This is a bitch and prevents you from UDP-punching at all.

If the public port is the SAME, that means you have Address-or-Port restricted NAT, and UDP punching is possible, but both sides of the UDP punch have to coordinate their connection attempts.


I'm missing a few checks - other things can go wrong (you might have a firewall that doesn't do NAT but prevents different WAN endpoints from sending your machine data). Check out the full flowchart on the Wikipedia page for the *thorough* test plan.


Another thing to keep in mind is that it's not standard. Any given device might not fall into any of the above categories.

[Edited by - Nypyren on March 30, 2010 10:19:12 PM]
Hmm ok to handle this properly is going to take too long so I'm just going to try and handle it this way.

When I host a game it asks whatismyip.com for my external IP.
If it doesn't find it, then I will block all connections coming from within my network (I have a separate LAN multiplayer mode if they want to play within their network).

When I join a game I ask whatismyip for my external IP.
If it finds it I can join (and send the host the found IP).
If it does not find it I can only join if the host is on a separate network.


So couple of questions about this.

In general does this seem like a reasonable approach?

Is comparing my HostEntry.HostName with the connected socket's HostName equivalent to asking if we are on the same network?

If I host a game from a separate network and 2 players who are from a different network with a NAT connect to me, this is fine because I automatically see their external IP right?
The issue is there's really no 'reasonable' approach to this, and it's why client-server models are generally favored to peer-to-peer. When a group of computers is sharing an IP address you have to configure your router very specifically to allow it.
-----------------------------------------------“The best, most affordable way to save the most lives and improve overall health is to increase the number of trained local, primary healthcare workers.”Learn how you can help at www.ghets.org

This topic is closed to new replies.

Advertisement