Skip to main content

Resilient reverse SSH with systemd

At HKUST every (research) computer science student is equipped with a desktop computer at his office desk. One can even request root-access for the computer / install one's own linux on it.

Unfortunately this comes with the drawback that no incoming network connections are allowed, which makes it quite hard (impossible) to ssh into the computer from outside.

Therefore I will describe a solution which makes sure, that the computer establishes a working reverse ssh connection to some server of your choice as long as the network connection is working.

autossh automatically restarts a ssh connection.
systemd can start autossh at system startup.

Restricted server access

The firewalled computer should for security reasons only access a special and restriced account on the server.

We therefore put the following configuration snippet into /etc/ssh/sshd_config on the server machine.

ClientAliveInterval 30
ClientAliveCountMax 3

Match User limited-reverse_ssh_from_machineX
   #AllowTcpForwarding yes
   #X11Forwarding no
   #PermitTunnel no
   #GatewayPorts no
   AllowAgentForwarding no
   PermitOpen localhost:62222
   ForceCommand echo 'This account can only be used for reverse ssh forwarding of a port'

Then the corresponding user account has to be created:

sudo useradd -m -s /bin/false limited-reverse_ssh_from_machineX

-m creates a homedirectory for the user so we can specify the allowed ssh keys.
-s sets the shell to /bin/false so that the user can actually not issue any commands on the server.

Then add create on the (firewalled) computer a new ssh key which you wish to use to establish the reverse ssh connection:

ssh-keygen -f ~/.ssh/reverse-ssh -t ecdsa

Finally copy ~/.ssh/reverse-ssh.pub to the server /home/limited-reverse_ssh_from_machineX/.ssh/authorized_keys.

Local configuration

First configure the settings for the reverse ssh connection in the ~/.ssh/config as follows:

Host reverse_tunnel
HostName bar
   User    limited-reverse_ssh_from_machineX
   IdentityFile    ~/.ssh/reverse-ssh
   RemoteForward   62222 localhost:22
   ServerAliveInterval     30
   ServerAliveCountMax     3

And then create a systemd service by creating a file /etc/systemd/system/reverse-autossh.service.

[Unit]
 Description=AutoSSH service for a reverse tunnel from foo to bar
 After=network.target

[Service]
 User=leonard
 Environment="AUTOSSH_GATETIME=0"
 ExecStart=/usr/bin/autossh -M 0 -NTq -F /home/leonard/.ssh/config freiburg_reverse_tunnel
 Restart=always
 RestartSec=5min

[Install]
 WantedBy=multi-user.target

You can test if everything works with

sudo systemctl daemon-reload
sudo systemctl start reverse-autossh

Don't forget to enable the systemd service on system start with

sudo systemctl enable reverse-autossh

Usage

To ssh into the (firewalled) computer, you may add the following to your ~/.ssh/config

Host firewalled_computer
    User login_user
    Hostname localhost
    Port 62222
    ProxyCommand ssh -q -W %h:%p yourserver.example.com
    ServerAliveInterval 30
    ServerAliveCountMax 3

Updates

  • 07.11.2016: Add keep alive configuration for ssh, so a broken connection (e.g. due to IP address change of the server) is detected; configure systemd to restart the reverse ssh tunnel if autossh dies unexpectedly.