URI: 
       Title: How to use Proton VPN port forwarding
       Author: Solène
       Date: 31 August 2024
       Tags: network privacy security openbsd linux
       Description: In this blog post, you will learn how to automate Proton
       VPN port forwarding
       
       # Introduction
       
       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.
       
  HTML 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...
       
       # Feature explanation
       
       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.
       
  HTML 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:
       
       * you get a random port assigned, so you must configure your daemon
       every time
       * the lease renewal script must run continuously
       * if something wrong happens (script failing, short network failure)
       that prevent renewing the lease, you will get a new random port
       
       Although it has shortcomings, it is a useful feature that was dropped
       by other VPN providers because of abuses.
       
       # Setup
       
       Let me share a script I am using on Linux and OpenBSD that does the
       following:
       
       * get the port number
       * reconfigure the daemon using the port forwarding feature
       * infinite loop renewing the lease
       
       You can run the script from supervisord (a process manager) to restart
       it upon failure.
       
  HTML 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.
       
       ## OpenBSD
       
       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.
       
       ### Using supervisord
       
       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
       ```
       
       ### Without supervisord
       
       Open a shell as root and execute the script and keep the terminal
       opened, or run it in a tmux session.
       
       ## Linux
       
       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.
       
       
       ```shell
       #!/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
       ```
       
       # Conclusion
       
       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.