Enabling NAT Open for all your devices

Created
May 13, 2021 03:57 PM
Tags
Linux
Networking

Why does it matter?

This makes your games on game consoles run with fewer hiccups. A lower NAT type (say NAT C/D on Nintendo Switch, NAT Type 3, or even "failed") will prevent P2P connections with other players.
Typical scenarios include:
  • Voice chatting on most games
  • Visiting other players' islands on Animal Crossing
  • Video meetings
  • Remote play
    • Xbox game streaming
    • PlayStation Remote Play
    • PC remote desktop or game streaming
notion image

How it's typically fixed

A typical suggestion from game consoles would be enabling port forwarding on your router:
Within the port range, enter the starting port and the ending port to forward. For the Nintendo Switch console, this is port 1 through 65535.
Seriously, Nintendo?
Yes, it indeed works, to some extent. However, this kind of static port mapping is EXCLUSIVE and will prevent any other devices in your network from using these ports properly. In other words, only one of your devices will be able to achieve a higher level of NAT.
Another similar solution called "DMZ" is effectively similar to forwarding all possible ports like above.
What if I want more than one console or device with a higher level of NAT type? Is this even possible?
 

How NAT works

Before we jump to the conclusion, let's recall what NAT means:
Network address translation (NAT) is a method of mapping an IP address space into another by modifying network address information in the IP header of packets while they are in transit across a traffic routing device. (Wikipedia)
notion image
In other words, a connection from your intranet device will be mapped and altered before released to the Internet. For the target server, the connection will be seemingly come from your router's Internet IP address instead of the actual intranet address your device possesses, with this change the server will be able to send the data back to your router, then eventually to your device.
This seems straightforward for one connection with one server, but for the cases when multiple servers exist, how do we maintain that mapping of connections? As the game consoles suggest, there will be multiple types of limits for NAT mapping.

Full-cone NAT as the savior

Among all kinds of NAT types, the Full-cone NAT is the one with the least restrictions. Let me borrow the image from Wikipedia again:
notion image
Full-cone NAT, also known as one-to-one NAT Once an internal address (iAddr:iPort) is mapped to an external address (eAddr:ePort), any packets from iAddr:iPort are sent through eAddr:ePort. Any external host can send packets to iAddr:iPort by sending packets to eAddr:ePort.
In English, when a port on one device is mapped on an external port of your router, any other server can talk to the device through that port. This effectively exposes the device's port automatically, and from the servers' perspective, your router is openly creating connections by itself.
 

Enabling full-cone NAT, on my Linux router

My home router is a x86 box running Linux. Thankfully, there is one guy implemented a full-cone NAT on top of iptables:
Let's just install that on my router:

Downloading the source

For iptables:
git clone git://git.netfilter.org/iptables.git
For the module itself:
git clone https://github.com/Chion82/netfilter-full-cone-nat.git
 

Building and installing the kernel module

cd netfilter-full-cone-nat
make
insmod xt_FULLCONENET.ko
# lsmod to see if xt_FULLCONENAT exists
lsmod |grep xt_FULLCONENAT
# you should see something like
# xt_FULLCONENAT         40960  0
# nf_nat                 49152  3 xt_FULLCONENAT,iptable_nat,xt_MASQUERADE
# nf_conntrack          163840  3 nf_nat,xt_FULLCONENAT,xt_MASQUERADE
# x_tables               49152  4 iptable_filter,xt_FULLCONENAT,ip_tables,xt_MASQUERADE
 

Building and installing iptables with the extention

cp ./netfilter-full-cone-nat/libipt_FULLCONENAT.c ./iptables/extensions
cd ./iptables
./autogen.sh
# check where your iptables resides
which iptables
./configure --prefix '/usr/bin' # replace the prefix with the parent path above
make
make install
You may also want to make it loaded automatically, check Automatic module loading with systemd on Archlinux wiki for a possible approach.

Setting up iptables

iptables -t nat -A POSTROUTING -o eth0 -j FULLCONENAT
iptables -t nat -A PREROUTING -i eth0 -j FULLCONENAT
# remember to confirm everything works before doing iptables-save
 

Tips

  • The scripts above are for illustration only, not the exact one I used, don't just copy it since I don't know what distro you're using. Also please refer to the official readme
  • You might have missing dependencies while building, try installing the base-devel equivalents of your distro or the ones you're missing
  • If iptables complains, check if you're using iptables-legacy or iptables-nft
  • I hope you know what you're doing
 

Enabling full-cone NAT, on your router

Some routers may have full-cone NAT as a switch in the firmware, OpenWrt also supports it. Try finding it in the web UI or opkg packages.
 

The result

If everything works, all your devices should have a open NAT type at the same time, just like mine, cheers 🎉
notion image
notion image
notion image

Loading Comments...