Find a file
2026-02-14 01:28:50 +05:00
bin Documentation improvements 2026-02-14 01:28:50 +05:00
lib Documentation improvements 2026-02-14 01:28:50 +05:00
LICENSE.md Documentation improvements 2026-02-14 01:28:50 +05:00
Makefile Documentation improvements 2026-02-14 01:28:50 +05:00
README.md Documentation improvements 2026-02-14 01:28:50 +05:00

fcnatfw

fcnatfw is a tool that allows you to "forward" a UDP or TCP port to the public internet through NATs (including CGNATs). Because it relies on the specifics of Linux's SO_REUSEPORT implementation, it only works on Linux (and possibly DragonFly BSD and FreeBSD, but I did not test this). It also only works on systems that use dynamic linking and specifically ones that allow shared library interposition (LD_PRELOAD).

The name is an abbreviation for "Full Cone NAT forward".

Installation

Before using this tool, you will need:

  • a C compiler and make (unless you are using a pre-built release)
  • GNU bash and coreutils (other coreutils may also work)
  • a compatible ping implementation
  • miniupnpc (optional, but will not do UPnP requests if missing)
  • nmap's ncat
  • stunclient from STUNTMAN software suite. Note that until #67 is merged, you will need to use my fork instead of the original, otherwise UDP mode will malfunction.

Note that while most of these tools usually can be installed with a package manager, stuntman lacks a package on GNU Guix and Debian and so you likely will have to install it manually, especially to use my fork. To do this:

  • clone the STUNTMAN repository with git clone
  • navigate into the created directory and run make (Boost and OpenSSL development files must be installed)
  • copy stunclient into one of the directories specified in PATH. a good choice would be ~/.local/bin or /usr/local/bin. If the directory of your choice is not in the PATH shell variable, you can add a line that says something like PATH="$HOME/.local/bin:$PATH"; export PATH to ~/.profile or ~/.bash_profile or ~/.bashrc or another file depending on your shell.

After all dependencies are ready, clone this repository with git clone https://git.kimapr.net/kimapr/fcnatfw and run make in the created directory. Two executable files are available:

  • bin/fcnatfw
  • bin/fcnatwrap

Optionally, you can run sudo make install or make prefix=$HOME/.local install which will install to /usr/local and ~/.local respectively. That way you can invoke the executables more conveniently. If you skip this step remember to replace occurances of fcnatfw and fcnatwrap later on with the proper relative or absolute path to the executables.

Usage

First of all, it's very possible that this tool will never work for you. Its operation is highly dependant on specifics of the NATs deployed in your network. At minimum, your CGNAT must be of Full Cone NAT type (or missing entirely, that's even better); all home routers in your chain towards the Internet must either be Full Cone NAT / Direct or support UPnP IGD dynamic port forwarding. If you don't know what any of this means, just try it and any see if it works.

Run the fcnatfw command to forward a port:

fcnatfw 20000 tcp stun.kimapr.net

Arguments as follows:

  1. The port number. Optionally followed by : and another port number (repeated as much as needed), this will make the UPnP mapping choose said another port number as the "external" port instead of the first one - however I do not recommend to do that.
  2. Protocol (tcp or udp) (optional, defaults to tcp)
  3. The STUN server (host:port) (optional, defaults to stun.kimapr.net but I guarantee no uptime for this server thusly you may have to choose another)

The program will trace the network path to the STUN server to find any UPnP servers it can find, install a port mapping on them, and then enter an infinite loop making binding requests to said STUN server. The external address (the ip:port others will use to connect to you) will be printed to both stderr and stdout (for stdout, it prints a new ip:port line at the beginning and every time it changes. You can thus pipe the output of the script into another script to, say, automatically configure your Dynamic DNS A and SRV records with the appropriate IP and port). Note that the external port will typically be different from the internal one, and will change dynamically just like the IP. This will make many types of usage difficult.

Concurrently with the fcnatfw program you shall run the whatever server program you wish to expose to the Internet. You need to either configure the program to set SO_REUSEPORT option on its listening socket, or if it doesn't support this, run the program under the fcnatwrap wrapper (this will set the socket option on EVERY socket it creates). SO_REUSEPORT allows two programs to bind to the same port at the same time, which is important for the way this all works.

Example usage for Minecraft:

  • set fcnatwrap as the "wrapper command" in your minecraft launcher
  • open a world, then click Open for LAN in pause menu
  • in a shell prompt, run fcnatfw PORT tcp, where PORT is replaced by the port number that Minecraft printed in chat.
  • tell others to connect using the ip:port printed by fcnatfw.

Contact

You can direct questions about this software suite, as well as improvements, to kimapr using the e-mail root@kimapr.net.

License

Copyright (C)2026 kimapr

fcnatfw is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

fcnatfw is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.