[kwlug-disc] Remote access to machine behind CG-NAT

John Van Ostrand john at vanostrand.com
Tue May 20 13:42:53 EDT 2025


On Tue, May 20, 2025 at 12:00 PM Khalid Baheyeldin <kb at 2bits.com> wrote:

> Thanks John for the details.
> It seems OpenVPN is quite doable then ...
>
> Regarding split tunnels, it is not something I have experience with.
> Rather it is something that needs to be set up, in order to prevent
> ALL data from going through the VPS. Say you are traveling, and
> only want the data to your home server to go through the VPN,
> but your streaming from Youtube (or whatever streaming service)
> should go to your local provider, and NOT to the VPN, to reduce data
> usage and improve performance.
>
> That is what I understand it to be. How to do it depends on the
> specific tunnel or VPN used.
>

This is the confusion people must have with VPNs. All the ones you see
advertised are for anonymising or changing one's geolocation. The original
use of a VPN was to allow secure remote access through a firewall. This is
what OpenVPN does.

In the old days (maybe still now) some corporate VPN administrators chose
to force all data through the VPN. I suppose it helped to secure the
corporate data and prevent someone from hopping through the client to
access the corporate network. Someone could use the SSH method below to do
just that.

It is the default behaviour of OpenVPN to only route traffic to the VPN
host. You have to add additional routes in the OpenVPN configuration to
allow access to the network behind a client. You would have to do
additional work to route all Internet data through the VPN. So by default
your Internet traffic will go around the VPN.

As for SSH tunneling, it turned out to be quite simple for certain
> use cases, and for a single or a couple of ports.
>

We used SSH tunnelling a lot to access hosts behind our clients' networks.
We didn't want a full VPN to all our clients, but when we needed to access
a server behind a firewall or access a web interface on a device remotely
we'd use SSH tunnelling.

The main drawback with SSH tunneling is that you need an SSH login on a
firewall that has a routable IP address. More ISPs are putting clients
behind a NAT and handing their firewall a non-routable address (e.g.
10.x.x.x or 172.16-31.x.x, 192.168.x.x.) So if you don't have SSH on your
firewall, or it doesn't have a routable IP address you can't use this.

If you can SSH, it's pretty handy and less complex to do manually than the
example below. I think the example below is clever and useful for some
cases. To do that with 100 clients you'd have to have 100 ports and
remember the ports for each. But if you just wanted to access a web server
at home while remote you could do it. We used dynamic DNS at our clients
and if that failed, we'd have our clients send us an email which had their
IP in the header. What could be a problem is if you have VirtualHosting on
the server you want to access. Since you'll be webbing to
HTTP://localhost:8080 the "localhost" name will be passed to the web server
which may not lead to any VirtualHost name. You'd have to compensate by
using a static /etc/hosts entry for that name on your laptop that points to
127.0.0.1 so that you can still use the correct host name.

For example, we used to do this to access a printer control panel at a
client:

ssh -R 8080:printer_ip:80 user at clientname.dyndns.org

Then web to localhost:8080 to access the printer web admin interface.
That's not very complicated, but it does require that the client have
an SSH-capable firewall with a routable IP address.

What the VPN does is make you a full participant in the network, at least
at the IP layer (things using physical layer discovery or broadcasting
won't work without special configuration.) So you can connect to NFS
servers, browse using your network's DNS server names, print, etc. There
are things you may want to do that aren't tied to a specific port, use UDP,
ICMP, or multiple ports. OpenVPN allows all that, SSH does not.

A VPN uses separate network addresses for clients than the network you want
to access. So if you have a 192.168.0.x network at home, a 1.2.3.4 VPS you
might configure a 192.168.1.x network for VPN client addresses. Because
this is a new address you may have to make changes to your home firewall to
allow that, presuming your home firewall is also your VPN client, it
doesn't have to be, but since it's the default gateway it makes it easier
to access network hosts. Otherwise all your network hosts would need a
route to 192.168.1.x to the VPN host.

If you only need access to one host, then you can configure OpenVPN on that
host and have complete access pretty easily, without firewall or routing
issues.

Here's the addressing example (The client and home firewall will also have
routable IP addresses, but it doesn't matter in this example.)

(Client          ) --->  ( VPS VPN Server    ) ---> (Home Firewal/VPN
client ) ---> ( Home Network)
(192.168.1.2 )        (1.2.3.4, 192.168.1.1)       (192.168.0.1,
192.168.1.3  )       (1982.168.0.x    )

I'm not sure how well versed you are on IP routing or firewall rules, but
you'll have to know at least a little.

Assume you have a VPS with the domain name of YOUR-VPS.com
> (if you have a fixed IP address, then you can use that too, or a Dynamic
> DNS service). Also assume your shell user name on it is REMOTE_USERNAME.
> And on the machine that is behind a firewall where you can't open external
> ports,
> nor can you have a stable external facing IP address, the internal IP
> address is
> 192.168.0.50, and the service you want to run is on port 8080.
>
> You create a systemd unit file, you do:
> User=USERNAME
> ExecStart=/usr/bin/autossh -N \
>   -o StrictHostKeyChecking=no \
>   -o UserKnownHostsFile=/dev/null \
>   -o PubkeyAuthentication=yes \
>   -o PasswordAuthentication=no \
>   -o ServerAliveInterval=30 \
>   -o ServerAliveCountMax=3 \
>   -i /home/USERNAME/.ssh/id_ed25519 \
>   -R YOUR-VPS.com:18080:192.168.0.50:8080 \
>   -p 22 REMOTE_USERNAME at YOUR-VPS.com
>
> The -R line is where the magic is. It starts with the name of the external
> VPS
>
> Then because this specific service is HTTP, you need an extra step, to
> proxy it in Nginx or Caddy.
>
> Since my VPS already has Nginx, I chose that route, with this file called
> my.conf, in the directory /etc/nginx/sites-enabled:
>
> server {
>   server_name subdomain1.YOUR-VPS.com;
>   listen 80;
>   access_log /var/log/nginx/access-$host.log;
>   location / {
>     proxy_pass                         http://127.0.0.1:18080; # This is
> the tunnel port
>     proxy_http_version                 1.1;
>     proxy_set_header Host              $host;
>     proxy_set_header                   Upgrade $http_upgrade;
>     proxy_set_header                   Connection 'upgrade';
>     proxy_set_header                   Host $host;
>     proxy_cache_bypass                 $http_upgrade;
>     proxy_read_timeout                 90;
>     proxy_connect_timeout              90;
>     proxy_buffers                      8 24k;
>     proxy_buffer_size                  2k;
>   }
> }
>
> If you browse to http://subdomain1.YOUR-VPS.com, the request will go to
> Nginx
> which will send it to the tunnel on the VPS, which then sends it to your
> machine
> behind the firewall, then back.
>
> You can go a step further and setup SSL on Nginx, and the service will be
> https,
> and not plain text http.
>
> It is all transparent, and your application never knows it is behind a
> tunnel.
>
> It gets complicated if you have more services, since you need to have one
> port (18080 in the above case) assigned to each tunnel.
>
>
>

-- 
John Van Ostrand
At large on sabbatical
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.kwlug.org/pipermail/kwlug-disc_kwlug.org/attachments/20250520/d6c2fe9c/attachment-0001.htm>


More information about the kwlug-disc mailing list