Författare:
Per Stenebo
Skapad:
2014-10-19 17:19:13
Ändrad:
2018-12-19 12:53:30
sv

Reverse SSH tunnel

reversessh

Task

You want to connect safely to a target machine that sits behind a firewall you don't control.

Solution

We will create a reverse SSH tunnel between the target machine and the relay machine. The source machine can then connect to the target machine from anywhere. It's like you have put a virtual network cable straight between two specific ports on the target machine and the relay machine. Anything you do on the the relay machine port 11022 actually happens on the target machine (including login credentials). To maintain the availability between your sessions we will be using AutoSSH to keep the tunnel alive at all times.

Assumptions

The target firewall allow traffic from the inside to internet, at least on one port (usually port 80 to allow web surfing). This machine have a SSH service daemon running. You have direct access to this machine during setup and testing. You can put it on the target network when this is done.

You have access to a relay machine on another network that sits behind a firewall that you can do port forward/port mapping on. It can also be on your own network (the same as the source computer). This machine also have a SSH service daemon running.

The source computer have access to the internet and a SSH client program.

Security

The security in this setup relies heavily on the security built into SSH, proper configuration of the relay and target machine SSH daemons and strong passwords of the users allowed SSH login on the relay and target machines. There's plenty information about this elsewhere.

Please note that this method make the port on target machine public available, if that is not needed you should have a look att this guide instead.

Process

Tip: Proceed only when each previous step was successful.

Please observe that you should adapt FQDN like firewall.relay.org and ports like 11022 and 33022 to suit your situation.

  1. Configure the relay firewall to allow and remap (redirect) TCP traffic from port 33022 to the SSH daemon listening port on the relay machine, usually port 22.
     
  2. Configure the relay firewall to forward TCP traffic on port 11022 to the same port number on the relay machine.
  3. From the source machine terminal, test login on the relay machine:

    ssh -p 33022 relay_user@firewall.relay.org

    Supply credentials for a admin user on the relay machine.

    Configure SSH daemon on the relay server:

    sudo nano /etc/ssh/sshd_config

    Make sure those lines exist and are uncommented (no leading #):

    AllowTcpForwarding yes
    GatewayPorts yes

    Restart the SSH service if changed:

    sudo service ssh restart

  4. From the target machine terminal, test login on the relay machine:

    ssh -p 33022 relay_user@firewall.relay.org

    Supply credentials for the relay machine user.

  5. From the target machine terminal, try to establish reverse SSH tunnel to the relay machine:

    ssh -R 11022:localhost:22 -N target_user@firewall.relay.org -p 33022

  6. From the source machine terminal, test connection to the target machine thru the relay machine:

    ssh target_user@firewall.relay.org -p 11022

    Supply credentials for the target machine user (not the relay machine user).

    This is all you need if it is a one-shot mission and you can skip the rest.

  7. From the target machine terminal, generate RSA keys for automatic login on the relay machine:

    ssh-keygen -t ed25519

  8. Transfer the keys from the target machine to the relay machine:

    ssh-copy-id -i ~/.ssh/id_ed25519.pub "relay_user@firewall.relay.org -p 33022" 

  9. From the target machine terminal, test automatic login on the relay machine:

    ssh -p 33022 relay_user@firewall.relay.org

    No credentials or other confirmations should be needed.

  10. From remote machine terminal: Install AutoSSH to maintain SSH tunnel between sessions:

    sudo apt-get install autossh

  11. From the target machine terminal, establish SSH tunnel to relay machine with AutoSSH:

    autossh -M 0 -f -R 11022:localhost:22 -N relay_user@firewall.relay.org -p 33022
    
  12. From the source machine terminal, test connection to the target machine thru the relay machine:

    ssh target_user@firewall.relay.org -p 11022

  13. From the target machine terminal, autostart the tunnel with cron:

    Check path to AutoSSH:

    which autossh Its usually in /usr/bin

    Edit your crontab:

    crontab -e

    Add the line:

    @reboot sleep 30 && /usr/bin/autossh -M 0 -N -f -R 11022:localhost:22 -o "ServerAliveInterval 45" -o "ServerAliveCountMax 2" -o "ExitOnForwardFailure yes" firewall.relay.org -p 33022

    I added the "sleep 30 &&" to allow extra time for network to be established before autossh try to connect.

  14. Reboot the target machine (to test that the cron command work).

  15. From the source machine terminal, test connection to the target machine thru the relay:

    ssh target_user@firewall.relay.org -p 11022

We are done! Now you can (relocate and) start the target machine on it's final destination.

 

Other uses

In this example we wanted SSH access to the target machine since we defined "localhost:22". To access the SSH daemon on another machine on the same LAN as the target machine we could use "192.168.0.45:22" instead, where 192.168.0.45 is the ip of the final destination machine. To access a web service on that machine we alter the port to "192.168.0.45:80". The complete autossh line would then become:

autossh -M 0 -f -R 11022:192.168.0.45:80 -N -o "ServerAliveInterval 45" -o "ServerAliveCountMax 2" -o "ExitOnForwardFailure yes" firewall.relay.org -p 33022

Notes

The domain name firewall.relay.org must be replaced with your domain name. The domain name can be exchanged with IP address.

The port numbers (11022 and 33022) can independently be exchanged with any other available port number between 1 and 65535. Ports between 1 and 1024 usually requires root privileges. SSH standard port is 22. We use high numbers to obscure that we provide SSH.

This is tested on machines with Debian based operating systems like Ubuntu and Raspbian but the process should be similar on most unix/linux/bsd flavors. The source machine can run Windows using Putty SSH client. Windows can probably also be used as relay and target too using cygwin. I've heard of some kind of SSH programs for Apple OSX but that's well outside my expertise.

SSH monitor the tunnel by sending some packets every now end then (configurable), this will of course generate traffic and perhaps data transfer costs. It is not much traffic but in some situations this can be important.

It should be noted that this solution might circumvent the intent of the target firewall and should only be used when appropriate. One appropriate example would be if you need access to services that have their internet connection over common 2g/3g/4g mobile networks, where the internet provider usually deploy a firewall that deny access from the outside. You obviously don't have control over that firewall and thus would need something like this solution to make it work.

Links

Source site (in Swedish): http://wallmander.net/1873-reverse-ssh-tunnel-kringgar-nat-brandvaggar/

Ubuntu man pages: | ssh | autossh |

| Ubuntu documentation - SSH | Raspberry Pi - remote access |

Troubleshooting

Check log:

grep 'sshd' /var/log/auth.log

Add the -y switch to ssh to send more info to syslog, like: .....-p 33022 -y

Check current SSH connections on this host:

sudo netstat -tupn | grep sshd

 

 

Kommentarer till sidan reverseSSH