Using autossh with systemd to keep a tunnel open

Sometimes it’s desirable to have a back door into a system that is behind a firewall. ssh is a security person’s best friend, and worst nightmare. This is more in the latter category, but as an admin, incredibly useful. I have a server that I can get outbound connections to anywhere, but do not have any inbound connections without using VPN. The VPN isn’t always reliable, and it’s nice to have an alternate way.

autossh to the rescue.

In a nutshell, autossh is just a wrapper that establishes an ssh connection, then in the event that the connection drops, reconnects automatically. ssh takes care of the actual tunnels.

Having autossh is nice and all, but you really need a way to have it execute automatically for you as well, especially across reboots. That’s where systemd comes in to the picture. You can create a service file to define how and when the service runs:

[Unit]
Description=Keeps a tunnel to Home
After=network-online.target

[Service]
# Here we set what user the process will run as; change to your username
User=autossh

# The options here are well documented in the autossh and the ssh manuals
# Make sure you specify the correct path to the key you wish to use

ExecStart=/usr/bin/autossh -M 0 -N -a -q -C -o "ServerAliveInterval 60" -o "ServerAliveCountMax 3" -o "ExitOnForwardFailure=yes" -o PasswordAuthentication=no -D 1080 -p 22 -l sgarrett -R 2222:127.0.0.1:22 -T -i /home/autossh/.ssh/id_rsa server.technomancer.com

# If we stop the service, tell it how to kill it.
ExecStop=/usr/bin/killall -s KILL autossh

# Set a delay, in seconds, between attempts.  This prevents a process storm if something is
# wrong.
RestartSec=15

[Install]
WantedBy=multi-user.target 

To enable this (for Ubuntu/Debian, at least), save a copy of the above to “/etc/systemd/system/autossh.service“.

Then just run the command:

systemctl enable autossh 

At this point, I recommend that you copy the autossh line, and run it once by hand to make sure that you are able to log in without any prompts and that your key works.

Once you have verified your connection, just:

systemctl start autossh 

You can verify that it worked with:

systemctl status autossh 

In this example, it is set to run the service as the user “autossh”. Change it to suit your needs.

I have several ports forwarded. If I have a shell on server.technomancer.com, I could run:

ssh -p 2222 localhost 

This would connect me back to the server at work that is running autossh to its ssh client.

The real trick here is combining this with the “jump host” option in ssh, -J. So instead of having a ton of -R port forwards, and trying to remember them all, instead, on the client side (i.e. where autossh has connected to), you could get to any host that the server (where autossh is running) with a command in the form of:

ssh -J localhost:2222 server2.work.com 

This would “directly” log you in to server2.work.com, via the host that autossh is running on (maybe called server1?).

A useful trick with this is to put a function in your bashrc file:

function viawork()
{
	ssh -J localhost:2222 $*
} 

Then all you need to do to ssh to server3.work.com would be:

viawork server3.work.com 

If you need to get to other ports, or other ports on other machines other than ssh, you can define as many -R <local port>:<remote host>:<remote port> blocks as you need.

Leave a Comment