Setting up a Server Behind NAT

server
 
config
 
network
 
dns
 
NAT
 

Setting up DIY servers is fun, but some issues are inevitable when running it from a home environment. The most notable issue is when an NAT layer (from ISP or even home router) obscures the server address and port from the users. We ran into this exact issue in a previous NextCloud server setup, and we discuss the issues and solutions for the problems in this post.

NAT and Why It Causes Problems

NAT (IP Network Address Translator) is a technique to that maps and translates end points to connect users inside a private network to the public network. NAT is widely used in our existing network infrastructure due to IPv4 address depletion by enabling communication from a private network to the public Internet using limited number of available public IPs. It is achieved by mapping private IP addresses (and ports) to the available public IP addresses (and ports) and translated on the fly depending on the direction of the network packet. These mappings and translations are transparent to the user and the server, and has no impact on their communication.

NAT exists in many forms, and NAPT (Network Address Port Translation) is one of its most prominent use cases. NAPT creates mapping of private (IP,port)of the client to another (IP, port) on public WAN address that connects the private network to the public Internet. This process is illustrated below:

RFC does not specify the implementation for the mapping creation (e.g. 10.1.1.2:X to 1.1.1.1:Y in the example above), but in general, these mappings are dynamically created when a client initiates a connection to a server outside the private network and released from the map when the connect is terminated or timed out.

Basically, NAPT makes use of the available space in (WAN IP, port) and leases them to the clients inside the private network. It has some limitations:

  1. The number of simultaneous connections is limited by number of available ports on WAN. When used in a SOHO (Small Office, Home Office), this rarely is an issue, unless some users are hoarding an abnormal number of connections or if the NAPT implementation fails to release the expired connections from its mapping;
  2. Connection needs to be initiated by the client inside the private network. Meaning, a server residing the private network will not receive the requests from clients outside of the private network.

NAT-PMP To The Rescue: Port Forwarding

Another NAT technique solves the issue #2: NAT-PMP (NAT Port Mapping Protocol), also known as Port Forwarding technique. Its concept is really simple: rather than having a transparent layer of mapping like NAPT, NAT-PMP offers a fixed mapping from (WAN IP, port) to a predetermined (IP, port) of a host inside the private network. This exposes the host’s (IP, port) to the external Internet, and thereby enabling it to function as a server (to the public Internet):

Configurations

Modern routers has sets up a private network behind a single WAN address

and has NAPT setup but transparent to users (even router admin). NAT-PMP is usually configurable under Port Forwarding:

Another tricky issue is that your internal server might be behind more than one layer of NAT. My ISP provider Silver IP for example, has a CGNAT layer for end users:

In order to expose my server to the public Internet, my ISP provider set up a Basic NAT layer to expose my router WAN in the CGNAT. End result looks like this:

DNS Configurations

Dynamic DNS

At the end of the previous section, we discuss an issue where the ISP has an additional layer of CGNAT and we fix it by requesting a Basic NAT setup from the ISP. When that isn’t the case and no additional CGNAT layer exist, the solution is much simpler. Of course we could still request a static public IP tied to our server, but an easier solution is to configure dynamic DNS. It is very simple to configure:

Crossing Network Boundary

There is one remaining issue with having the server behind a NAT and using Port Forwarding to serve the client: the client cannot reach the server when the client moved into the same private network as the server.

For clients outside LAN, they can access the server with NAT router forwarding the requesting to server (apologies for the ugly and overly-simplified UMLs):

However, when the client resides inside the LAN, router will not forward the request (and rightfully so) to the server, causing the client’s request being dropped:

One solution is to map the server’s domain to its private/internal IP inside the client.

Or even better, switch the host file depending on the network:

# /etc/NetworkManager/dispatcher.d/update-host.sh
if [[ ${CONNECTION_UUID} == ${HOME_WIFI_UUID} ]]; then
	HOST_FILE="/etc/hosts_home"
else
	HOST_FILE="/etc/hosts_regular"
fi

A better solution is to set up an internal DNS server:

This way, queries for the domain are answered

  1. with the private IP when queried from inside of LAN (internal DNS server answers the query);
  2. with the public IP when queried from the outside of LAN (public DNS server answers the query).

It is not too difficult to set up an internal DNS server with bind9 and use it as the primary DNS server in the router:

References