SSH (Secure shell)#

SSH, or Secure Shell, is a remote communication protocol that allows users to interact with remote servers over the Internet.

It provides a mechanism to authenticate a remote user, transfer input from the client to the host, and relay output back to the client in a secure manner.

../_images/symmetric-encryption-ssh-tutorial.jpg

Fig. 20 Schematic of an SSH transaction. Credit: Hostinger#

SSH client#

If you are using GNU/Linux or macOS, then using SSH is straightforward and a terminal will natively support it.

If you are using Windows, you will need to use an SSH client to open SSH connections.

A SSH client comes with a few command-line tools, among which the most useful are

ssh

to interactively connect via the SSH protocol and send commands

ssh-keygen

to generate a pair of asymmetric keys

ssh-copy-id

to register a public key on a remote server

SSH basics#

A basic connection on a remote server with SSH is achieved with

ssh <username>@<hostname>

<username> represents the username of the account you wish to access and
<hostname> refers to the remote server, which can be an IP address (e.g. 244.235.23.19) or a domain name (e.g. www.xyzdomain.com)

User authentication methods on remote servers#

Password

Although passwords are encrypted, it is not recommended to use passwords for secure connections. This is because many bots can brute force easy passwords or default passwords, and access your account and having to remember a complex password for each server is very difficult.

Asymmetric keys (recommended method)

This is a set of asymmetric keys used to authenticate the user without having to enter a password. It improves the security and simplifies workflows at the same time. Each user has a private key and a public key that can be shared with the remote servers. The private key must remain private. We will see below how to generate such pair of keys and register them on to the remote servers.

Note

Keys are also used to authenticate git commits.
One should always associate a key with their account on GitHub, GitLab, etc.

Generation of a SSH key pair#

There are several algorithms used to generate SSH keys. Some are outdated and some are not yet supported on all servers

  • RSA – Default and most popular algorithm. It is based on the difficulty of factoring large numbers. A key size of at least 4096 bits is recommended for RSA. RSA is getting old and significant advances are being made in factoring. Choosing a different algorithm is advisable where possible.

  • DSA – An old US government Digital Signature Algorithm. It is based on the difficulty of computing discrete logarithms. A key size of 1024 would normally be used with it. DSA in its original form is no longer recommended.

  • ECDSA 👈 – A new Digital Signature Algorithm standardized by the US government, using elliptic curves. This is the recommended algorithm for current applications/service if supported. Only three key sizes are supported: 256, 384, and 521 (sic!) bits. Most SSH clients now support this algorithm.

  • ED25519 – This is one of the new algorithms added in OpenSSH. Support for it in clients is not yet universal. You need to check the documentation of the SSH clients and servers, if they support this algorithm.

source

Example#

We will generate a pair of keys with the elliptic curve algorithm and a size of 521 bits

ssh-keygen -t ecdsa -b 521 -C "daenerys@castlerock"

This should output something like

Generating public/private ecdsa key pair.
Enter file in which to save the key (/home/daenerys/.ssh/id_ecdsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/daenerys/.ssh/id_ecdsa
Your public key has been saved in /home/daenerys/.ssh/id_ecdsa.pub
The key fingerprint is:
SHA256:Go5oxc3cEjdrG4ZYDDl4TlFQ6WyBeIC6gMvmXIcXPHs daenerys@castlerock
The key's randomart image is:
+---[ECDSA 521]---+
| ..++Bo.         |
|. o Boo          |
|o  =.++.o        |
|+  ..X+= o       |
|oo  =.@ S        |
|oo = * E o       |
|+ + + + .        |
| +               |
|                 |
+----[SHA256]-----+

Exposing the public key#

The next step is to provide the remote server with the newly created public key to be able to authenticate through the SSH handshake. For this use ssh-copy-id on the terminal such as

ssh-copy-id -i ~/.ssh/id_ecdsa daenerys@castlerock

and enter your password this one time.

Use the -i option to provide the desired key for the server.

Hint

Even though it seems we are copying the private key (which does not have the .pub extension, ssh-copy-id will make sure only the public key is copied over.

SSH config#

To manage multiple SSH servers, it is possible to create a config file on your machine to easily connect.

touch ~/.ssh/config
chmod 600 ~/.ssh/config

Example#

Host targaryen
    User dany
    HostName targaryen.in2p3.fr
    IdentityFile ~/.ssh/id_ecdsa

Host tyrell
    HostName 192.168.10.20

Host martell
    HostName 192.168.10.50

Host *ell
    User dragonqueen

Host * !martell
    LogLevel INFO

Host *
    User root
    Compression yes

Usage#

In the terminal, use the host alias to connect

ssh targaryen

All the options specified in the ssh config file will be taken into account.

Advanced usage#

Connecting through a proxy#

Sometimes a remote server is only accessible from a local network and thus not exposed on the internet. This is the case for the APC computing clusters for instance.

In such case, one has first to connect to a bastion, a remote server that serves as a bridge between internet and the local network, before being able to connect to the desired server.

Listing 1 Connecting to a remote server accessible through a bastion#
ssh -J daenerys@got-bastion.in2p3.fr targaryen

To avoid having to do the two connections in a row, one can specify in the config that the connexion should go through that bastion

Listing 2 SSH config example for tunneling#
Host got-bastion
    User daenerys
    HostName got-bastion.in2p3.fr
    IdentityFile ~/.ssh/id_ecdsa_bastion

Host targaryen
    User dany
    HostName targaryen.in2p3.fr
    IdentityFile ~/.ssh/id_ecdsa
    ProxyJump got-bastion

Then connecting to targaryen will just be as simple as

Listing 3 Same as above with a proper config file#
ssh targaryen

Port forwarding#

For security reasons or specific needs, one sometimes needs to redirect the local ports of your machine to those of a remote web server (e.g. for VNC, or access to a specific website).

The way to do that is to connect to the host while providing the desired ports to forward to, e.g. here with the port 8080 (used for instance for a Jupyter webserver)

Listing 4 Local port forwarding for port 8080#
ssh -L 8080:targaryen:8080 got-bastion

If this is something regular, one might want to add that to the SSH config so each connection will also add the local port forwarding. In this case, since the server is behind a proxy, one needs to do the port forwarding at the proxy level.

Listing 5 SSH config example for local port forwarding on targaryen web server#
Host got-bastion
    User daenerys
    HostName got-bastion.in2p3.fr
    IdentityFile ~/.ssh/id_ecdsa_bastion
    LocalForward 8080 targaryen:8080

Host targaryen
    User dany
    HostName targaryen.in2p3.fr
    IdentityFile ~/.ssh/id_ecdsa
    ProxyJump got-bastion

Then for the port forwarding to be enabled one must execute in a terminal

Listing 6 Silent port forwarding to targaryen:8080#
ssh -fN got-bastion

The -f option will run the SSH session in the background and -N will disable remote command execution for security.