Tag Archives: autossh

Set up Autossh with systemd

Autossh is a great tool that is useful in establishing a persistent encrypted reverse tunnel between two computers.

A case for autossh

Let us say that you have a static IP on the internet and your friend (or relative) that always needs help fixing his computer has a dynamic IP address (constatly changes).  Whenever your friend (or relative) needs their computer fixed you could run to their house and fix it… or you could figure out a way to connect to their computer to fix it.  Now your friend (or relative) probably doesn’t know how to open ports on their router or may not be able to, so how could you make a connection between their computer and yours?…  Enter SSH tunneling…  With ssh you could have your friend (or relative) connect to your computer and establish a reverse tunnel back to them (even on Windows with PUTTY), but again this is the person who is not that good with computers.

We need to make something that is bulletproof, something that you could drop at your friend’s (or relative’s) house and that it does everything by itself.  This is where autossh comes into play.

With autossh running on a simple Linux box (maybe a Raspberry Pi) you can accomplish what is required to establish a persistent tunnel between your friend’s (or relative’s) network and yours.

Another scenario would be that you want to set up an off-site backup of you important data at a friend’s house, but you don’t want to mess about in their router configuration.  You want to give them something they can just plug into their network and turn on.  Autossh can establish a reverse tunnel from their network to your network and you can just use any of the myriad of network sync tools to accomplish your off-site backup.

How to install and configure autossh with systemd

Before we begin we need to make the following assumptions.

  1. Autossh will be running in a computer named “autossh_server” on a different network.
  2. The computer we want to use as our gateway to the other network via the autossh tunnel is named “otherserver”.
  3. We have at least one account (user1) on all computers and root privileges in order to change system configurations files.
  4. We are using Debian Stretch (or a similar distro like Raspbian)
  5. We will run autossh as a service under a user named “autossh”.

We begin by installing autossh in “autossh_server”.

# apt-get install autossh

In this example I’ve chosen “autossh” as the user that the autossh service will run as. We can create the user by executing the following command:

# adduser autossh

Even though the adduser command made a home directory when we created the “autossh” user,  this is a service and we don’t want it to use a home directory in the “/home” folder.  So lets create a folder named “autossh” in the “/var/run/” directory. Create the directory with the following command:

# mkdir /var/run/autossh

Now we make sure that the “autossh” user and the “autossh” group have ownership of the “/var/run/autossh” directory.

# chown autossh:autossh /var/run/autossh

Since “/var/run” is a directory usually mounted as tmpfs anything that is written to “/var/run/autossh” will be effectively destroyed on reboot. Because of this, we need a place to store keys for autossh and since we are running it as a service we might as well use a directory in “/etc”. Create the “/etc/tunnel” directory.

# mkdir /etc/tunnel
# chown autossh:autossh /etc/tunnel
# chmod 700 /etc/tunnel

For the initial setup we are going to use the “/home/autossh” directory.  Logout of the root account and login as the autossh user.  Make sure that you are in the autossh user directory (run “pwd”; it should return “/home/autossh”) and run the following as the “autossh” user:

$ ssh-keygen -t rsa -b 4096

This create an 4096 bit key.  Once it finishes do the following while still the user “autossh” and where “user1” is a user in the server “otherserver”, running the ssh daemon:

cat .ssh/id_rsa.pub | ssh user1@otherserver 'cat >> .ssh/authorized_keys'

This command basically logs into the remote server (“otherserver”) from the “autossh” user account using the “user1” account on the remote server and transfers the authorizing key to that account.  This allows for future logins to be accomplished without having to enter a password.  It also takes care of the initial registration of the remote server’s key (answer “yes” when prompted).

If you get an error like “bash: .ssh/authorized_keys: No such file or directory” ensure that the “.ssh” directory exists in the home directory of the user in “otherserver” and re-run the previous command.

Now we need to move the contents of the “.ssh” directory to its new home in /etc/tunnel:

$ cp -Rp .ssh /etc/tunnel
$ chmod -R 700 /etc/tunnel

The two above commands copy the newly created cryptographic keys to “/etc/tunnel” and lock down the directory so that it is only readable/writable/executable by the owner, in this case the “autossh” user.

Setting up the configuration in systemd

Now return to being root and create “/etc/default/autossh” with the following content:
##############################################
#Specifies how long ssh must be up before we
#consider it a successful connection
AUTOSSH_GATETIME=0
#Sets the connection monitoring port.
#A value of 0 turns the monitoring function off.
AUTOSSH_PORT=0
AUTOSSH_LOGLEVEL=7
AUTOSSH_LOGFILE=/var/run/autossh/user_ssh_error.out
SSH_OPTIONS="-N -o 'ServerAliveInterval 60' -o 'ServerAliveCountMax 3' -p 22 -R 20022:localhost:22 user@otherserver -i /etc/tunnel/.ssh/id_rsa"
###########################################

On the above configuration, notice the line that says:

SSH_OPTIONS="-N -o 'ServerAliveInterval 60' -o 'ServerAliveCountMax 3' -p 22 -R 20022:localhost:22 user@otherserver -i /etc/tunnel/.ssh/id_rsa"

This are the options you are passing to ssh.  The “ServerAliveInterval 60” ensures that every 60 seconds a null packet is sent to keep the connection alive.  The “ServerAliveCountMax 3” set to three the number of server alive messages that may be sent without getting a reply.  The “-p 22” is the port that the remote ssh server is listening on (ssh usually is at port 22).  The “-R 20022:localhost:22” is how we set up the reverse tunnel; in this instance  port 20022 on “otherserver” system connects you to port 22 on “autossh_server”.  You can add any other ports or even forward connections from “autossh_server” to other systems on its network.

For example:

Adding “-R 20080:httpserver:80” would take anything coming into port 20080 of “otherserver” and forward it to port 80 on a system called “httpserver” in the same network as “autossh_server”.

Also, “-R 20089:Windows_box_X:3389” would take anything coming into port 20089 of “otherserver” and forward it to port 3389 on “Windows_box_X”.  Port 3389 is the Windows Remote Desktop Protocol port, so by adding that little line now you can RDP into a windows box on another network over an encrypted tunnel from a system in your local network.

Now to continue with configuration, create “/lib/systemd/system/autossh.service” with the following content:

#############################################
[Unit]
Description=autossh
Wants=network-online.target
After=network-online.target

[Service]
#Type=simple
User=autossh
EnvironmentFile=/etc/default/autossh
ExecStart=/usr/bin/autossh $SSH_OPTIONS
Restart=always
RestartSec=60

[Install]
WantedBy=multi-user.target
#################################################

Now, we can create a soft link in /etc/systemd/system:

# ln -s /lib/systemd/system/autossh.service /etc/systemd/system/autossh.service

Try out the connection as the autossh user:

$ ssh user1@otherserver

If you can ssh in without a password then everything is working as it should.

To further lock down the autossh user, in /etc/passwd change:

autossh:x:1001:1001:autossh,,,:/home/autossh:/bin/bash

to:

autossh:x:1001:1001:autossh,,,:/var/run/autossh:/bin/false

What we are doing here is changing the value for the home directory of the “autossh” user from ” /home/autossh” to “/var/run/autossh” and changing the default shell from “/bin/bash” to “/bin/false”.   As stated before, using “/var/run/autossh” as home ensures its contents is always reset to nothing on reboot.  By changing the default shell value from “/bin/bash” to “/bin/false” we make sure that the “autossh” user is not able to log into the box in any manner.

As started before the contents of “/var/run” doesn’t survive reboot, we need to ensure that the “/var/run/autossh” is created on boot every time.  To do this we need to create a file called autossh.conf in /usr/lib/tmpfiles.d with the following content:

#########################################
d /var/run/autossh 0700 autossh autossh
L /var/run/autossh/.ssh - - - - /etc/tunnel/.ssh
##############################################

What follows the “d” basically mean create the directory “/var/run/autossh” with the permisions set at 0700 and owned by user “autossh” and group “autossh”.  All that follows the “L” means to link the /etc/tunnel/.ssh directory to /var/run/autossh/.ssh.  All this ensures that everything is where it needs to be after a reboot.

Before we can start our service, we have to ask systemd to reload all unit files:

$ sudo systemctl daemon-reload

Now we enable the autossh service:

$ sudo systemctl enable autossh

Before we reboot and test everything out we need to also make some changes to “otherserver” that will allow anyone to connect to the forwarded ports.

Assuming that you are using OpenSSH as you ssh daemon, log into your “otherserver” and edit /etc/ssh/sshd_config.  Change:

#GatewayPorts no

To:

GatewayPorts yes

Also ensure that the parameter is not commented.  Daemons other than OpenSSH should have similar settings.  Restart the OpenSSH daemon or reboot.  Also reboot the computer running autossh.

Once the reboot is complete, we can check the status on the computer running autossh with:

$ sudo systemctl status autossh

If there are any problems, check /var/run/autossh/user_ssh_error.out

Now to test it out…  if you ssh from any machine into “otherserver” using port 20022 you will actually be connected to port 22 on “autossh_server”.

In essence the following command on your local network:

$ ssh -p20022 user1@otherserver

connects you to a computer on a remote network without the need to know the actual IP address of that computer.