If you have read the
ssh whoami.filippo.io post by Filippo Valsorda and the related whoarethey: Determine Who Can Log In to an SSH Server post by Andrew Ayer, you might be wondering if we can do something about it in the OpenSSH client configuration.
In this post I will describe how I use a different key for each server I connect to via SSH and how I make it easy to managed in my OpenSSH client configuration. This mitigates both of the issues mentioned in the posts above. I have been using this configuration without issue for approximately five years now.
A lot of OpenSSH hardening guides focus on configuration recommendations for the OpenSSH server. Since the integration of Wireguard in the Linux kernel and with clients available for all majors platforms, I have been progressively switching all my OpenSSH servers to listening only on a Wireguard interface which thus significantly reduced the pressure for strong sever side OpenSSH hardening. Do not get me wrong: it is still useful and you should still do it but it is no longer a critical priority.
While we generaly do not use OpenSSH to connect to random servers, man in the middle attacks can happen and could redirect the traffic to a malicious host. The general idea is thus to limit the information that the OpenSSH client sends to a remote host by default.
It is also very easy to share the private part of an OpenSSH key pair instead of the public part by mistake, either via the command line with
ssh-copy-id or when adding it to a remote host or service. If you only have one key pair, then if you make one mistake, you have to replace your key on all the hosts and services where you used it.
The idea is thus to create a distinct key pair for each server that we are going to connect to in order to be able to easily revoke or discard them if shared by mistake or when access is no longer needed. Posting a private key by mistake will thus only require immediate action for places where this key was used and as I generally only share the key right after I have generated it for a new host, it is essentially unused and I can directly generate a new one.
I generally create a key pair for each “entity” and not strictly each host as this keeps thing more manageable and easier to track while not reducing the security benefit.
And finally, while the public part of an asymetric OpenSSH should be safe to share by design, it also identifies you and that is the idea behind the two posts mentionned at the beginning. We avoid leaking that information if we use different keys for different hosts.
To enable that setup, we need to disable some options by default for all hosts that we are going to connect to and then explicitely specify for a given host which key we will be using. We will thus use the following layout for the SSH client configuration (usually
ssh_config(5) man page for the full details.
First, we will tell OpenSSH to only use the identity specified for each specific host instead of offering all the keys available to all servers:
Then, instead of generating a single key pair that will be stored in the default location, we will create different keys, one for each entity, and store them in a subfolder:
We can then select the key to use for each server:
There are a lot of additionnal options that you can set to further harden your OpenSSH configuration (client and server). I have found the following articles to be useful and I am using a lot of the mentionned options in my personal configuration:
I have found this setup to be relatively low effort and high peace of mind gain, similarly to how a password manager enables you to not think about password at all anymore.