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:
- https://www.ssh.com/ssh/tunneling/example
- https://dev.to/k4ml/poor-man-ngrok-with-tcp-proxy-and-ssh-reverse-tunnel-1fm
- https://superuser.com/questions/588591/how-to-make-ssh-tunnel-open-to-public
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