If you use Proton VPN with the paid plan, you have access to their port forwarding feature. It allows you to expose a TCP and/or UDP port of your machine on the public IP of your current VPN connection.
This can be useful for multiple use cases, let's see how to use it on Linux and OpenBSD.
Proton VPN documentation: port forwarding setup
If you do not have a privacy need with regard to the service you need to expose to the Internet, renting a cheap VPS is a better solution: cheaper price, stable public IP, no weird script for port forwarding, use of standard ports allowed, reverse DNS, etc...
Proton VPN port forwarding feature is not really practical, at least not as practical as doing a port forwarding with your local router. The NAT is done using NAT-PMP protocol (an alternative to UPnP), you will be given a random port number for 60 seconds. The random port number is the same for TCP and UDP.
Wikipedia page about NAT Port Mapping Protocol
There is a NAT PMPC client named `natpmpc` (available almost everywhere as a package) that need to run in an infinite loop to renew the port lease before it expires.
This is rather not practical for multiple reasons:
Although it has shortcomings, it is a useful feature that was dropped by other VPN providers because of abuses.
Let me share a script I am using on Linux and OpenBSD that does the following:
You can run the script from supervisord (a process manager) to restart it upon failure.
Supervisor official project website
In the example, the Java daemon I2P will be used to demonstrate the configuration update using sed after being assigned the port number.
Install the package `natpmpd` to get the NAT-PMP client.
Create a script with the following content, and make it executable:
#!/bin/sh PORT=$(natpmpc -a 1 0 udp 60 -g 10.2.0.1 | awk '/Mapped public/ { print $4 }') # check if the current port is correct grep "$PORT" /var/i2p/router.config || /etc/rc.d/i2p stop # update the port in I2P config sed -i -E "s,(^i2np.udp.port).*,\1=$PORT, ; s,(^i2np.udp.internalPort).*,\1=$PORT," /var/i2p/router.config # make sure i2p is started (in case it was stopped just before) /etc/rc.d/i2p start while true do date # use for debug only natpmpc -a 1 0 udp 60 -g 10.2.0.1 && natpmpc -a 1 0 tcp 60 -g 10.2.0.1 || { echo "error Failure natpmpc $(date)"; break ; } sleep 45 done
The script will search for the port number in I2P configuration, stop the service if the port is not found. Then the port line is modified with sed (in all cases, it does not matter much). Finally, i2p is started, this will only do something in case i2p was stopped before, otherwise nothing happens.
Then, in an infinite loop with a 45 seconds frequency, there is a renewal of the TCP and UDP port forwarding happening. If something wrong happens, the script exits.
If you want to use supervisord to start the script at boot and maintain it running, install the package `supervisor` and create the file `/etc/supervisord.d/nat.ini` with the following content:
[program:natvpn] command=/etc/supervisord.d/continue_nat.sh ; choose the path of your script autorestart=unexpected ; when to restart if exited after running (def: unexpected)
Enable supervisord at boot, start it and verify it started (a configuration error prevents it from starting):
rcctl enable supervisord rcctl start supervisord rcctl check supervisord
Open a shell as root and execute the script and keep the terminal opened, or run it in a tmux session.
The setup is exactly the same as for OpenBSD, just make sure the package providing `natpmpc` is installed.
Depending on your distribution, if you want to automate the script running / restart, you can run it from a systemd service with auto restart on failure, or use supervisord as explained above.
If you use a different network namespace, just make sure to prefix the commands using the VPN with `ip netns exec vpn`.
Here is the same example as above but using a network namespace named "vpn" to start i2p service and do the NAT query.
#!/bin/sh PORT=$(ip netns exec vpn natpmpc -a 1 0 udp 60 -g 10.2.0.1 | awk '/Mapped public/ { print $4 }') FILE=/var/i2p/.i2p/router.config grep "$PORT" $FILE || sudo -u i2p /var/i2p/i2prouter stop sed -i -E "s,(^i2np.udp.port).*,\1=$PORT, ; s,(^i2np.udp.internalPort).*,\1=$PORT," $FILE ip netns exec vpn sudo -u i2p /var/i2p/i2prouter start while true do date ip netns exec vpn natpmpc -a 1 0 udp 60 -g 10.2.0.1 && ip netns exec vpn natpmpc -a 1 0 tcp 60 -g 10.2.0.1 || { echo "error Failure natpmpc $(date)"; break ; } sleep 45 done
Proton VPN port forwarding feature is useful when need to expose a local network service on a public IP. Automating it is required to make it work efficiently due to the unusual implementation.