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.