SSH Port Forwarding

There’s heaps on this on the internet and a good book. Here is my usage, which is useful for IoT connections.

Remote Server Access

I want to connect remotely to a web server on machine.com. But it’s behind a firewall which refuses incoming connections and/or has no public IP address.:

# machine.com>
ssh -N -R 8080:localhost:80 ssh-user@your.public.server

-N: using no shell/command…
-R : listen on the remote machine…
8080: at remote port 8080…
localhost:80: and forward connection that back here…
ec2-user@your.public.server: do this by sshing to this remote machine

image 13
image 13

Finally, there’s a configuration setting on public.com required. See details here.

And now, from Admin’s computer, we can connect to public.com:8080 which is really connecting to machine.com:80, its webserver. From the public.com machine, we can see it’s listening on :8080 to forward to machine.com:80

public.com>ss -t -l -n
 State      Recv-Q      Send-Q            Local Address:Port           Peer Address:Port     
 LISTEN     0           128                     0.0.0.0:8080                0.0.0.0:*               

Unmanned Tunnel

Extending this concept, we can create a ssh tunnel from the remote machine.com to a public server:

# machine.com:
ssh -N -R 2345:localhost:22 ec2-user@public.com

And then from an admin machine connect to sshd on machine.com by:

# admin machine
ssh -p 2222 ec2-user@machine.com
# and we get:
machine.com>

Keep Alive and AutoSSH

We’ve got a remote machine without a public ip. It’s headless. We can run a process automatically to ‘phone home’. Use autossh, available via apt, to nicely monitor the connection:

/usr/bin/autossh -N -R 2020:localhost:22 user@public.com -o ForwardX11=no -o ExitOnForwardFailure=yes -o StrictHostKeyChecking=no -o ServerAliveInterval=20

Those options are for reliability. Check the man page. Then run it on boot as a systemd service as suggested here:

[Unit]
Description=Auto Reverse SSH
After=systemd-networkd-wait-online.service
# Try to restart forever!
StartLimitIntervalSec=0

[Service]
Type=simple
Restart=always
RestartSec=60       # Wait a bit before restart

[Service]
ExecStart=/usr/bin/autossh -N -R 0:localhost:22 user@public.com -o ForwardX11=no -o ExitOnForwardFailure=yes -o StrictHostKeyChecking=no -o ServerAliveInterval=20

[Install]
WantedBy=multi-user.target

Multiple Connections

Right, so we’ve got a tunnel from our remote (maybe IoT) machine to a publicly accessible, but secure, server. We can use ‘0’ as the remote port (0:localhost:22) to let it choose one. If we have a few remote computers, how do we know what is what? Use github.com/brettbeeson/tunnel/ to interrogate the clients periodically.

Forward a Connection from Remote Server to Public Server

So, we’ve ssh’d onto a remote machine. On that remote machine’s network is a device (“device.local”) with a web server we need to access.

First let’s find available web servers on the local network:

nmap -q --open -oG a -p 80 10.1.1.* && cat a

We can forward one IP or host to our public machine. Have to config sshd on the remote machine too (see details here.) Then:

ssh -N -R 8080:device.local:80 user@public.com

Just kill when finished add -f to fork to background. Now we can access device’s web server from outside. (Don’t forgot about security considerations as it’s now a ‘public’ site.) Port 8080 needs to be unfirewalled on public.com.

One thought on “SSH Port Forwarding

Leave a Reply

Your email address will not be published. Required fields are marked *