NGINX-logo

Port forwarding behind NAT or CGNAT

There several ways to port forward to expose your local port to the internet. These instructions are working for normal NAT routers and also for Carrier Grade NAT (CGNAT). CGNAT is often used by LTE/4G internet connections. Described port forward methods are:

  • Via SSH on your own webserver/VPS
  • Via ngrok
  • Via Serveo
  • Via OpenVPN server on your webserver/VPS
    • VPN Method 1: Proxy on Apache 2 webserver
    • VPN Method 2: Port forward on the VPS

In the described examples are we going to forward local port 8080 and expose it on internet with port 18080.

Info:

Port forward via OpenSSH on your VPS

To enable port tunneling via SSH on your webserver/VPS, the option GatewayPorts needs to be set on yes. Check this with the following command:

$ sshd -T|grep -i gatewayports
gatewayports yes

If there is a no, change the /etc/ssh/sshd_config:

$ vi /etc/ssh/sshd_config
GatewayPorts yes

Then restart the SSH service on your VPS:

$ systemctl restart ssh

Now it’s possible to port forward from every Linux machine, with for example this command. Run this on the local machine.

$ ssh -l root -R :18080:localhost:8080 my-vps.com

Serveo

Info: https://serveo.net/

In case you don’t have or don’t want to use your own webserver/VPS, it’s possible to use Serveo. It works a bit like on your own VPS. You don’t have to install or configure anything. You also don’t need any account. Clever!

$ ssh -R 18080:localhost:8080 serveo.net
Hi there
Forwarding TCP connections from serveo.net:18080
Press g to start a GUI session and ctrl-c to quit.
TCP connection from 37.188.243.191 on port 18080
TCP connection from 37.188.243.191 on port 18080

ngrok

Login on the dashboard and download the binary here: https://dashboard.ngrok.com/get-started

Unzip the zipfile on your local machine:

$ unzip /path/to/ngrok.zip

Authenticate ngrok once, you can get the command here https://dashboard.ngrok.com/auth. This will look like this:

$ ./ngrok authtoken 3e5iY2KftJ2844aWA6jDY_9fJFZAc1Hhq5bJ4eD1myV
Authtoken saved to configuration file: /home/arjan/.ngrok2/ngrok.yml

Now it’s possible to start the port forward:

$ ./ngrok http 8080
ngrok by @inconshreveable                                                                           (Ctrl+C to quit)

Session Status                online
Account                       Arjan Wooning (Plan: Free)
Version                       2.3.25
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://e9d4ff45.ngrok.io -> http://localhost:8080
Forwarding                    https://e9d4ff45.ngrok.io -> http://localhost:8080

Connections                   ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00

And in this case you can reach your local server on this URL: https: //e9d4ff45.ngrok.io

Configuration instructions for the OpenVPN server

Activate packet forwarding

On Linux you need to activate IP forward:

$ echo 1 > /proc/sys/net/ipv4/ip_forward

$ vi /etc/sysctl.conf
net.ipv4.ip_forward=1

Add/replace the following VPN settings in server.conf:

# Allow client to client communication
client-to-client
# Send pings to keep connection alive
keepalive 15 60
ping-timer-rem
# Persistent ip addresses
ifconfig-pool-persist /etc/openvpn/ipp

# Enable ip forward on the running system (temporary)
sysctl -w net.ipv4.ip_forward=1

Restart the OpenVPN server:

$ service openvpn start

VPN Method 1: Proxy on Apache 2 webserver

Advantage of this method is that you can use the Let’s Encrypt certificate of you webserver. On your lokal network you don’t need to have encryption, http is in most cases secure enough. When the Let’s Encrypt certificates are updated on your webserver, they also are updated for this proxy.

$ vi /etc/apache2/sites-available/application_example.conf
<IfModule mod_ssl.c>
        Listen 18080
        <VirtualHost *:18080>
                ProxyPreserveHost On
                ProxyRequests Off
                ServerName myserver.com
                SSLProxyEngine On

                ProxyPass "/" "http://192.168.1.5:8080/"
                ProxyPassReverse "/" "http://192.168.1.5:8080/"
                RewriteEngine on
                RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
                RewriteCond %{HTTP:CONNECTION} ^Upgrade$ [NC]
                RewriteRule .* ws://192.168.1.5:8080%{REQUEST_URI} [P]
                SSLEngine on

                SSLCertificateFile /etc/letsencrypt/live/myserver.com/fullchain.pem
                SSLCertificateKeyFile /etc/letsencrypt/live/myserver.com/privkey.pem
                SSLCertificateChainFile /etc/letsencrypt/live/myserver.com/chain.pem

                ErrorLog ${APACHE_LOG_DIR}/error_home_assistant.log
                CustomLog ${APACHE_LOG_DIR}/access_home_assistant.log combined
        </VirtualHost>
</IfModule>

And activate the configuration:

$ cd /etc/apache2/sites-enabled/
$ ln -s ../sites-available/application_example.conf
$ systemctl restart apache2.service

VPN Method 2: Port forward on the VPS

In this example the local machine has IP nr: 192.168.1.5

$ vi /etc/rc.local
## Port forward: 18080 <-> 8080
iptables -t nat -A PREROUTING -p tcp -m tcp --dport 18080 -j DNAT --to-destination 192.168.1.5:8080
iptables -t nat -A POSTROUTING -d 192.168.1.5/32 -p tcp -m tcp --dport 8080 -j MASQUERADE