Run autossh as a systemd service on CentOS

If you install with yum, the systemd configuration file will also be placed, so it's easy.

(In the first place) About SSH Port forwarding

This is a general technology for transferring communication between the connection source host and connection destination host of SSH.

For example, consider the following environment. Suppose you can't connect to devices in the verification network from the Internet and you need to SSH into the platform once.

image.png Here, if you want to access the Web server in the verification network by HTTP from the operation terminal, you can use SSH Port forwarding.

SSH


ssh -L 127.0.0.1:10080:<Web server address>:80 <Stepping stone server address>

Add the -L option when SSH login from the operating terminal to the platform. Then, while SSH is connected, the communication to 127.0.0.1:10080 of the operating terminal is transferred to <Web server address>: 80 (as seen from the SSH connection destination).

At this time, you can access the web server by entering http://127.0.0.1:10080 in your web browser.

Also, since communication is transferred through SSH channels, communication is encrypted on the Internet.

What is autossh

As you can see, SSH Port transfer is so convenient that you may want to use it permanently.

Autossh is convenient in such a case.

AUTOSSH(1)More excerpt


     autossh is a program to start a copy of ssh and monitor it, restarting it as necessary should it die or
     stop passing traffic.

autossh monitors ssh and restarts ssh if there are any problems. Start as follows.

autossh


AUTOSSH_GATETIME=0 autossh -M 0 -N -L <Transfer options> <SSH connection destination>

Here, -M is the setting of the monitoring port, but since it is not used, it is set to 0. After -N, it is an SSH option. -N is an option that does not execute the command after SSH connection, without which it will fail to start the shell.

After that, it is the same as normal SSH Port transfer.

If the environment variable AUTOSSH_GATETIME is not set to 0, autossh seems to end when SSH is disconnected.

While autossh is running, it will try to reconnect if the SSH is disconnected.

Sep 02 14:24:14 localhost.localdomain autossh[9968]: Connection to 192.168.122.61 closed by remote host.
Sep 02 14:24:14 localhost.localdomain autossh[9968]: ssh exited with error status 255; restarting ssh
Sep 02 14:24:14 localhost.localdomain autossh[9968]: starting ssh (count 2)
Sep 02 14:24:14 localhost.localdomain autossh[9968]: ssh child pid is 10189
Sep 02 14:24:14 localhost.localdomain autossh[9968]: ssh: connect to host 192.168.122.61 port 22: Connection refused
Sep 02 14:24:14 localhost.localdomain autossh[9968]: ssh exited with error status 255; restarting ssh
Sep 02 14:24:14 localhost.localdomain autossh[9968]: starting ssh (count 3)
Sep 02 14:24:14 localhost.localdomain autossh[9968]: ssh child pid is 10190
Sep 02 14:24:14 localhost.localdomain autossh[9968]: ssh: connect to host 192.168.122.61 port 22: Connection refused
Sep 02 14:24:14 localhost.localdomain autossh[9968]: ssh exited with error status 255; restarting ssh
Sep 02 14:24:14 localhost.localdomain autossh[9968]: starting ssh (count 4)
Sep 02 14:24:14 localhost.localdomain autossh[9968]: ssh child pid is 10191
Sep 02 14:24:14 localhost.localdomain autossh[9968]: ssh: connect to host 192.168.122.61 port 22: Connection refused
Sep 02 14:24:14 localhost.localdomain autossh[9968]: ssh exited with error status 255; restarting ssh
Sep 02 14:24:14 localhost.localdomain autossh[9968]: starting ssh (count 5)
Sep 02 14:24:14 localhost.localdomain autossh[9968]: ssh child pid is 10192
Sep 02 14:24:14 localhost.localdomain autossh[9968]: ssh: connect to host 192.168.122.61 port 22: Connection refused
Sep 02 14:24:14 localhost.localdomain autossh[9968]: ssh exited with error status 255; restarting ssh
Sep 02 14:24:14 localhost.localdomain autossh[9968]: starting ssh (count 6)
Sep 02 14:24:14 localhost.localdomain autossh[9968]: ssh child pid is 10193
Sep 02 14:24:14 localhost.localdomain autossh[9968]: ssh: connect to host 192.168.122.61 port 22: Connection refused
Sep 02 14:24:14 localhost.localdomain autossh[9968]: ssh exited with error status 255; restarting ssh
Sep 02 14:24:14 localhost.localdomain autossh[9968]: starting ssh (count 7)
Sep 02 14:24:14 localhost.localdomain autossh[9968]: ssh child pid is 10194
Sep 02 14:24:14 localhost.localdomain autossh[9968]: ssh: connect to host 192.168.122.61 port 22: Connection refused
Sep 02 14:24:14 localhost.localdomain autossh[9968]: ssh exited with error status 255; restarting ssh
Sep 02 14:24:16 localhost.localdomain autossh[9968]: starting ssh (count 8)
Sep 02 14:24:16 localhost.localdomain autossh[9968]: ssh child pid is 10195
Sep 02 14:24:26 localhost.localdomain autossh[9968]: ssh: connect to host 192.168.122.61 port 22: No route to host
Sep 02 14:24:26 localhost.localdomain autossh[9968]: ssh exited with error status 255; restarting ssh
Sep 02 14:24:34 localhost.localdomain autossh[9968]: starting ssh (count 9)
Sep 02 14:24:34 localhost.localdomain autossh[9968]: ssh child pid is 10196

Install and run with systemd

This time I will install it on CentOS 7. The following environment

Enable and install the epel repository.

sudo yum install epel-release
sudo yum install autossh

The systemd config file is added here.

$ rpm -ql autossh
/etc/autossh
/usr/bin/autossh
/usr/lib/systemd/system/[email protected] # <-this
/usr/share/doc/autossh-1.4g
/usr/share/doc/autossh-1.4g/CHANGES
/usr/share/doc/autossh-1.4g/README
/usr/share/doc/autossh-1.4g/README.service
/usr/share/doc/autossh-1.4g/examples
/usr/share/doc/autossh-1.4g/examples/autossh.host
/usr/share/doc/autossh-1.4g/examples/rscreen
/usr/share/man/man1/autossh.1.gz

$ cat /usr/lib/systemd/system/[email protected]
[Unit]
Description=autossh: %I
Documentation=file:///usr/share/doc/autossh/README.service man:autossh(1)
After=network.target

[Service]
User=autossh
Environment="AUTOSSH_GATETIME=0"
EnvironmentFile=/etc/autossh/%i.conf
ExecStart=/usr/bin/autossh $OPTIONS

[Install]
WantedBy=multi-user.target

There is an explanation in /usr/share/doc/autossh-1.4g/README.service, so let's create a configuration file according to that.

/etc/autossh/web.conf


OPTIONS=-M 0 -N -L 127.0.0.1:10080:192.168.0.2:80 -i /etc/autossh/keys/testing.rsa -l testing 192.168.122.61

What is specified in the OPTIONS variable is passed to autossh and executed.

When booting from systemd, autossh is run by user autossh. Therefore, this time, the user for login is explicitly specified with the -l option of SSH, and the private key for authentication is explicitly specified with the -i option.

Keep the private key somewhere accessible to the autossh user.

#The testing user on this machine can log in to the destination with public key authentication.
sudo -u autossh mkdir -m 700 /etc/autossh/keys
sudo cp /home/testing/.ssh/id_rsa /etc/autossh/keys/testing.rsa
sudo chown autossh:autossh /etc/autossh/keys/testing.rsa

When you log in to SSH for the first time, you need to confirm the connection destination, so log in once with the SSH command.

python


$ sudo -u autossh ssh -i /etc/autossh/keys/testing.rsa [email protected]
The authenticity of host '192.168.122.61 (192.168.122.61)' can't be established.
ECDSA key fingerprint is SHA256:gYYyvZ9++CwtcU3zlpfEJHgo509G7KaqSDpaqBDte8o.
ECDSA key fingerprint is MD5:de:c9:1c:80:0d:60:8c:33:9f:c8:22:48:8f:dc:6b:b1.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.122.61' (ECDSA) to the list of known hosts.
Last login: Wed Sep  2 12:18:35 2020 from 192.168.122.1
[testing@localhost ~]$

At this point, the preparation is complete.

Start the service. The service name will be autossh @ <before .conf in the configuration file>.

sudo systemctl start autossh@web

You can check the status and restart / stop like other services. You can also set it to start when the machine boots.

#Status check
$ sudo systemctl status autossh@web
● [email protected] - autossh: web
   Loaded: loaded (/usr/lib/systemd/system/[email protected]; disabled; vendor preset: disabled)
   Active: active (running) since Wed 2020-09-02 13:58:32 EDT; 6s ago
     Docs: file:///usr/share/doc/autossh/README.service
           man:autossh(1)
 Main PID: 9954 (autossh)
   CGroup: /system.slice/system-autossh.slice/[email protected]
           ├─9954 /usr/bin/autossh -M 0 -N -L 127.0.0.1:10080:192.168.1.2:80 -i /etc/autossh/keys/testing.rsa t...
           └─9955 /usr/bin/ssh -N -L 127.0.0.1:10080:192.168.1.2:80 -i /etc/autossh/keys/testing.rsa testing@19...

Sep 02 13:58:32 localhost.localdomain systemd[1]: Started autossh: web.
Sep 02 13:58:32 localhost.localdomain autossh[9954]: port set to 0, monitoring disabled
Sep 02 13:58:32 localhost.localdomain autossh[9954]: starting ssh (count 1)
Sep 02 13:58:32 localhost.localdomain autossh[9954]: ssh child pid is 9955

#restart
$ sudo systemctl restart autossh@web

#Starts when the machine starts
$ sudo systemctl enable autossh@web

Example of use

Here are some possible cases.

web It is good to use Nginx etc. for TLS, but depending on the application, it may not be necessary to do so.

A little different from the example at the beginning, Consider the case where the web server (192.168.122.61) does not allow HTTP access from other hosts in the firewall. Suppose this server can be SSH connected from the operating terminal for management.

[testing@localhost ~]$ curl 192.168.122.61:80
curl: (7) Failed connect to 192.168.122.61:80; No route to host
#can not connect.

[testing@localhost ~]$ ssh 192.168.122.61
Last login: Thu Sep  3 03:48:08 2020 from 192.168.122.1
#SSH can connect.
 
[testing@web ~]$ curl -i 127.0.0.1:80
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/2.7.5
Date: Thu, 03 Sep 2020 07:59:31 GMT
Content-type: text/html; charset=UTF-8
Content-Length: 414

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>
<title>Directory listing for /</title>
<body>
<h2>Directory listing for /</h2>
#The following is omitted. Accessable from localhost.

I will try to make HTTP connection from the operation terminal by port forwarding. The settings for autossh are as follows.

/etc/autossh/web.conf


OPTIONS=-M 0 -N -L 127.0.0.1:10080:127.0.0.1:80 -i /etc/autossh/keys/testing.rsa [email protected]

I will try using it.

#to start.
[testing@localhost ~]$ sudo systemctl start autossh@web

[testing@localhost ~]$ curl 127.0.0.1:10080
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>
<title>Directory listing for /</title>
<body>
<h2>Directory listing for /</h2>
#The following is omitted.

VNC

This is the one that allows you to check the Linux GUI over the network. It may also be used to access the virtual machine's display from the hypervisor.

This time,

--For a server that accepts VNC from the local --Log in with SSH from the web server and --Host noVNC on your web server --Try to operate with a browser.

image.png

This is the autossh configuration file. Suppose VNC is waiting at 127.0.0.1:5903 on 192.168.122.1.

/etc/autossh/vnc.conf


OPTIONS=-M 0 -N -L 127.0.0.1:15903:127.0.0.1:5903 -l testing -i /etc/autossh/keys/testing.rsa 192.168.122.1

Forwarded the port to localhost 15903. Convert this port to Websocket with Websockify for use with noVNC.

websocketify


#Start it with this.
websockify 25903 localhost:15903

We accept WebSocket in 25903. This time I will host noVNC with Nginx. (Reference https://github.com/novnc/noVNC/wiki/Proxying-with-nginx)

bash:/etc/nginx/conf.d/novnc.conf


server {
    listen 80;
    server_name 192.168.122.80;
    location /websockify {
        proxy_pass http://127.0.0.1:25903/;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
    location / {
        index index.html;
        alias /usr/share/novnc;
    }
}

When you start the service and access it, it looks like this. (After opening the web page, entering the parameters and connecting.) image.png

Here, if you start Nginx with systemd, you can set the dependency.

$ sudo systemctl edit nginx
#Described below.
[Unit]
[email protected]

If you do this, autossh will also be started when you start Nginx. Isn't it good that it is easy to handle?

Summary

I think convenience is convenient.

By the way, Ubuntu doesn't have a systemd configuration file, so it seems that you have to write it yourself.

Recommended Posts

Run autossh as a systemd service on CentOS
How to run the SpringBoot app as a service
How to install GNOME as a desktop environment on CentOS 7
Run React on a Docker container
Run PureScript on a Docker container
Run JVM-Math-Language as a Gradle project at hand
OpenVPN on CentOS 8
Install BookStack Documentation Wiki on Elastic Compute Service on CentOS 7
Let's create a gcloud development environment on a centos8 container
Create a user with an empty password on CentOS7
Steps to set up a VNC server on CentOS 8.3
Java11: Run Java code in a single file as is
Apparently the environment variables are different when running sidekiq as a service on the production server