What is inconvenient is seldom secure. SSH is mostly very convenient and is quite secure, but there’s one common pain point: verifying host identities.

Traditionally, in the world of SSH, servers have host keys that rarely change, but are generated separately for each host. When a user accesses a host for the first time, they are presented with the host’s key, and need to manually, laboriously, and usually insecurely, check that it’s the right key for that host. Or they can just say “OK, whatever”.

This situation is annoying to the user. They’re asked to do something tedious, something may have no idea of how to do right, in order to do the thing they originally set to do. The result is almost invariably that they answer “yes”.

The user is in effect trained to automatically accept any host key for any host.

The SSH client saves the host key so the correct answer is known and the user need not be annoyed again. This avoids the question unless the host key changes, such as when it’s a VM that gets re-created with the same name. In that case there is much more scary warning about main-in-the-middle attacks. It’s not even an annoying question, it’s a fatal error.

The host key verification question is a somewhat risky situation: if an attacker manages to trick the user’s SSH client to show a key the attacker has generated, and the user accepts it as the real one, the attacker can potentially see – and change – all the traffic going over the SSH connection. This mostly nullifies the security benefit SSH is meant to provide. (Not entirely: the connection is still protected against other attackers.)

This is not a particularly easy attack, so I would not be terribly worried about it happening. However, annoying users is never a good idea. Do not annoy users, lest they hold a grudge and not trust you.

The risky situation can be avoided by having the host keys be communicated to all users ahead of time, but doing this in a secure and convenient way is difficult. It doesn’t help when host keys change or new hosts are created often. It is also unnecessary.

There are at least three ways to avoid the annoying question entirely without compromising on security:

  • Use an SSH Certificate Authority to certify host identities.
    • this means a little extra work for system administrators, and getting users to configure their SSH client to accept certificates made by one or more CA keys
  • Use the SSHFP DNS record type to distribute host key fingerprints.
    • this requires DNSSEC working for the user, which can’t yet be taken for granted, and requires SSH server administrators to be able to update DNS, and for DNS updates to propagate sufficiently quickly to the user
  • Use Monkeysphere.
    • this builds on OpenPGP web of trust, which not everyone is part of
    • this also seems to no longer be developed, and the website has vanished

My preference here is SSH CA, but it’s good for you to consider your options.

Using an SSH CA to certify SSH host keys means the user’s SSH client can trust it without asking the user to verify it. The client is configured to trust any host certificate that can be verified using the SSH CA public key. The CA public key still needs to be communicated to the user in a secure way, but the CA key is only one key and rarely changes, so the tiresome risky situation happens very rarely. After the user has the CA key, an attacker can’t trick the user into accepting a false host key.

With host certificates, the SSH client never needs to ask its user if the host key of a new host is valid, and the user never needs to try to verify it. If the host’s host key changes, the client doesn’t need to bother the user about it, as long as the new host key gets a new certificate.

Overall, this leads to a much smoother and more secure experience for people using SSH.

I’ve written a little guide on SSH CA, at https://liw.fi/sshca/, and am preparing to offer commercial training on managing SSH CA. Ping me if you’re interested.

If you have any comments on this blog post, please respond on the fediverse thread.