ssh port forwarding

2024-05-23

to connect to a device behind a private unreachable router you can use remote ssh port forwarding or remote ssh tunneling (notice that remote ssh tunneling is different from local ssh tunneling).
example:

ssh -i path/to/key -R '*:5000:*:22' user@remote -N -g

so say you have 3 machines, "local1", "local2" and "remote1". when this command is run from local2, it binds to the port 5000 on the machine remote1 and forwards the traffic to that port to port 22 of local2. this allows you to ssh into local2 through the remote machine from local1, now if you take local1 into any other network, not necessarily the network local2 is on, you can still connect to local2 from local1 through remote1.
basically, this can be used as an alternative to other port forwarding methods when you want to gain access to a machine behind a private network like a home or office network.
a connection to the tunnel can be opened using the command

ssh -i path/to/key localuser@remote1 -p 5000

note that localuser would be the user of local2 (not the remote machine) that you want ssh to use.

connection refused

by default tunnel endpoints only listen on 127.0.0.1, so they can't be accessed from other machines. to change this you may need to add this to /etc/ssh/sshd_config on the server:

GatewayPorts clientspecified

this is also the reason we use the address *:5000:*:22, the star is used to listen on all interfaces, like 0.0.0.0.

using ipv6

if you're using ipv6 you need to make sure its enabled on all machines. vim /etc/sysctl.conf and make sure you have the following:

net.ipv6.conf.default.disable_ipv6 = 0
net.ipv6.conf.all.disable_ipv6 = 0

the ipv6 equivalent for localhost is ::1. so, for example, the reverse tunnel ssh command becomes:

ssh -i yourkey -R '*:5000:*:22' -6 user@remote1:etc:etc::1 -N -g

systemd service

an example systemd service that i use to automatically open an ssh tunnel for a linux server:

[Unit]
After=network.target network-online.target
Description=ssh tunnel
Wants=network-online.target

[Service]
ExecStart=ssh -i my/key/path -R '*:5000:*:22' -6 root@my:server:ipv6::1 -NTg -o ServerAliveInterval=60
Restart=on-failure
RestartSec=5s
User=mahmooz

[Install]
WantedBy=multi-user.target