Categories
SysOps

How to create persistent reverse SSH tunnel

Sometimes I want to access a private server at home from a different network while being on the go.
The easiest way to do this is to use autossh utility to create a secure and persistent reverse SSH tunnel to the publicly available server.

First step

Connect to the remote server and create sshtunnel user.

$ sudo useradd -s /usr/sbin/nologin -m sshtunnel

It is crucial to disable shell access, but create a home directory to store SSH configuration (known hosts and authorized keys).

Second step

Create sshtunnel user on the local machine.

$ sudo useradd -s /usr/sbin/nologin -m sshtunnel

Switch to the sshtunnel user and create SSH key pair.

$ sudo su sshtunnel -s /bin/bash
sshtunnel$ ssh-keygen -t rsa -b 2048 -q -N "" -f ~/.ssh/tunnel_key_a

Third step

Upload ~/.ssh/tunnel_key_a.pub file to the remote server and perform the following operations while still being connected to it.

Create a missing .ssh directory.

$ sudo su -s /bin/sh sshtunnel -c "mkdir ~/.ssh"

Add uploaded public key to the pool of keys authorized for authentication.

$ echo 'no-agent-forwarding,no-user-rc,no-X11-forwarding,no-pty' $(cat tunnel_key_a.pub) | sudo su -s /bin/bash sshtunnel -c "tee >> ~/.ssh/authorized_keys"

Now you can remove the uploaded public key.

Fourth step

Add remote server to the known servers pool on the local machine.

$ ssh-keyscan -H -t rsa remote-server | sudo su -s /bin/sh sshtunnel -c "tee >> ~/.ssh/known_hosts"

Fifth step

Use the following command on the local machine to test the reverse SSH tunnel to the remote server.

$ sudo su -s /bin/sh sshtunnel -c "autossh -v -i ~/.ssh/tunnel_a remote-server -N -R 9000:localhost:22"
OpenSSH_6.7p1 Debian-3, OpenSSL 1.0.1j 15 Oct 2014
debug1: Reading configuration data /etc/ssh/ssh_config
[..]
Authenticated to remote-server ([111.222.333.444]:22).
[..]
debug1: remote forward success for: listen 60654, connect 127.0.0.1:60655
debug1: remote forward success for: listen 9000, connect localhost:22
debug1: All remote forwarding requests processed

Sixth step

Add autossh command to the /etc/rc.local script to start a ssh tunnel at boot.

$ sudo sed -i -e '$i # create sshtunnel\nsu -s /bin/sh sshtunnel -c "autossh -f -i ~/.ssh/tunnel_key_a remote-server -N -R 9000:localhost:22"\n' /etc/rc.local
$ cat /etc/rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# create sshtunnel
su -s /bin/sh sshtunnel -c "autossh -f -i ~/.ssh/tunnel_key_a remote-server -N -R 9000:localhost:22"

exit 0

Now you should be able to connect to the SSH service on the local machine from the remote server using port 9000, while autossh is managing the SSH tunnel.

remote-server$ ssh -l milosz -p 9000 localhost