This article demonstrates how to make a local port available on a remote server. Ideal for dynamic IP-addresses or devices not accessible from outside a local network.
Quick reverse tunnel
Further below is a more standardized method using a dedicated tunnel-user. But this following command should already work out of the box (if no root access to the remote server):
ssh -o 'ExitOnForwardFailure yes' -N -R 0.0.0.0:[remote-port]:127.0.0.1:[local-port] [remote-user]@[remote-host] -p [remote-ssh-listen-port]
-o 'ExitOnForwardFailure yes'ensures the command will terminate upon any error in forwarding.
-Nmeans no command line (shell) will be opened.
-R 0.0.0.0:[remote-port]:127.0.0.1:[local-port]makes the local port publicly (at
0.0.0.0, or privately using
127.0.0.1) available at the given remote port. Be sure the port is allowed through the firewall if it must be publicly available.
[remote-user]@[remote-host] -p [remote-ssh-listen-port]define the ssh login details of a user on the remote server. By default, the port is 22, and may be left out if that is the port sshd is running on.
Remote server configuration
It is good to stick to the following standardized setup. First add a new dummy-user that will only be used for authentication purposes (will have no home-directory).
useradd --no-create-home -s /bin/false tunnel
Add the following to /etc/ssh/sshd_config:
Port 22000 Match User tunnel PasswordAuthentication no AuthorizedKeysFile /etc/ssh/tunnel_keys GatewayPorts clientspecified AllowTcpForwarding yes PermitOpen 0.0.0.0:22001 0.0.0.0:22002 0.0.0.0:22003 0.0.0.0:22004 0.0.0.0:22005 0.0.0.0:22006 0.0.0.0:22007 0.0.0.0:22008 0.0.0.0:22009 127.0.0.1:22001 127.0.0.1:22002 127.0.0.1:22003 127.0.0.1:22004 127.0.0.1:22005 127.0.0.1:22006 127.0.0.1:22007 127.0.0.1:22008 127.0.0.1:22009 X11Forwarding no AllowAgentForwarding no ForceCommand /bin/false PermitTTY no
Ensure a file exists (which only root may write to), with on each line the public key of the user who is allowed to create a tunnel.
That is, to allow a user, add the contents of the user's
~/.ssh/id_rsa.pub file to /etc/ssh/tunnel_keys:
ssh-rsa ... user@device-name
Open the tunnel-ports in the firewall:
firewall-cmd --add-port=22000-22009/tcp --permanent firewall-cmd --reload firewall-cmd --list-all
Note: Don't forget to forward these ports to the remote machine if it's behind a proxy (in TCP-mode).
Creating the reverse SSH-tunnel (actual usage)
ssh -o 'ExitOnForwardFailure yes' -N -R 127.0.0.1:22001:127.0.0.1:[local-port] tunnel@[remote-host] -p 22000
The above command will keep running until interrupted, an error occurred, or it is killed.
To stop the command gracefully, use
This command does not terminate if a connection between the remote and local port was disconnected or stopped listening.
That is, it will keep the tunnel intact, and survives a restart of a program listening on the local-port.
You may make the tunnel available on another machine, using the following command on that other machine:
ssh -o 'ExitOnForwardFailure yes' -N -L 127.0.0.1:[local-port]:127.0.0.1:22001 tunnel@[remote-host] -p 22000
These tunnels are only (privately) available for the given tunnel user and all in the allocated port range as per the configuration. But by default, anyone with shell-access to the server typically has access to the tunnels.
If you wish to make the tunnel public, use
0.0.0.0:22001 instead of
127.0.0.1:22001 in the remote address.
This means that anyone who can access the remote machine port, has access to the endpoint of that tunnel.