fcnatfw/README.md
2026-02-19 02:15:39 +05:00

135 lines
6.5 KiB
Markdown

# 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](https://miniupnp.tuxfamily.org/) (optional, but will not do UPnP requests if missing)
- nmap's [ncat](https://nmap.org/ncat/)
- `stunclient` from [STUNTMAN software suite](https://www.stunprotocol.org/).
Note that until [#67](https://github.com/jselbie/stunserver/pull/67)
is merged, you will need to use [my fork](https://github.com/Kimapr/stunserver)
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.
- if you are using my fork, you can use `make install` similar to how
is shown below instead of copying `stunclient` manually.
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.
Note that, even though there is a `configure` script present, you do not
need to use it. It is only there to improve compatibility with the
GNU Build System. `configure` understands only install prefix options
and environment variables, and silently discards anything else. Notably,
cross-compilation options are ignored (but you can set the CC variable).
When using `configure` shell script code will be transformed to
hardcode executables used in the script by absolute path found at
configure-time instead of finding them in PATH at run-time (except ping).
## 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/>.