Configuring an SSH Key Between a Client and Server

January 11, 2022

Overview

The SSH protocol uses public key cryptography to authenticate clients and servers. ssh-keygen is a tool for creating new authentication key pairs for SSH. Such key pairs allow for automated logins, single-sign on and the authentication between client and server.

Create SSH Key Pair on the Client

To create an SSH key:

ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa
  • -t specifies the algorithm
  • -b specifies the key size (in bits)
  • -f specifies the filename

Running this command will generate a public key (id_rsa.pub) and private key (id_rsa) in the specified directory of the client (which defaults to ~/.ssh). You will also be asked for an optional passphrase, which is used for encrypting the private key.

The server itself will have it's own corresponding public key. For SSH, the server's public key will match the format used by the client, and is usually located on the server at:

/etc/ssh/ssh_host_rsa_key.pub

Add Public Key on the Server

To use an SSH key for authentication, the public key must be copied to the server and added to an ~/.ssh/authorised_keys file. This file may have multiple public keys registered, as multiple clients may want to connect to the same server. Once this has been added, the server will allow any connecting client that has the private key to log in.

To add the public key to the server:

ssh-copy-id user@host

You will need to confirm your connection to the server (enter yes) and provide the relevant password for the user you are connecting as. Subsequently, this command will create the following files:

  • a known_hosts file on the client (ie: client:~/.ssh/known_hosts) - this file stores the public key of any server that it has authenticated with (for a given client, which servers can it connect to)
  • an authorised_keys file on the server (ie: server:~/.ssh/authorised_keys) - this file stores the public key of any client that it has authenticated with (for a given server, which clients can connect to it)

Host Validation

Host validation occurs every time you try to connect to a server. The SSH protocol will attempt to make sure that the server you are connecting to is the server that you think you are connecting to.

If this is the first time making a connection you will receive a warning indicating that the authenticity of the server cannot be established and whether you want to continue. If you continue, the SSH fingerprint derived from the public key of the server will be used for future validation.

SSH Fingerprint

An SSH fingerprint is derived from a public key. Each time a connection is attempted, the client will look at the server's public key stored in ~/.ssh/known_hosts and the derived SSH fingerprint of that key. If the fingerprint has changed then you will be warned that it has changed and asked whether you want to continue.

Reasons for a change may include:

  • the key changed on the server
  • the IP address you are connecting to used to belong to a different server
  • a man-in-the-middle attack is happening (this is a security problem)

Validating SSH Fingerprints

To extract the SSH fingerprint of the client's public key:

ssh-keygen -lf ~/.ssh/id_rsa.pub -E sha256

This should match one of the SSH fingerprint's derived from the server's authorised_keys file:

ssh-keygen -lf ~/.ssh/authorized_keys -E sha256

To extract the SSH fingerprint of the server's public key (stored on the server):

ssh-keygen -lf /etc/ssh/ssh_host_ecdsa_key.pub -E sha256

This should match one of the SSH fingerprint's derived from the client's known_hosts file:

ssh-keygen -lf ~/.ssh/known_hosts -E sha256

SSH Configuration

The ~/.ssh/config file on the client is used for system-wide configuration during SSH. The configuration variables set here will be used when connecting to various servers and may be useful for setting up relevant aliases and shortcuts.

Host simple-server-name
HostName complicated-server-name.complicated-domain-name
User username@complicated-domain-name

You can now SSH into the server using:

ssh simple-server-name