Manage SSH known_hosts entries

Beginning with the release of OpenSSH version 4.0, a new configuration directive was introduced: 'HashKnownHosts yes'. When you set this option in your ssh_config file, ssh will start recording a one-way cryptographic hash of the hostname and IP address rather than recording them in clear text. Later, when initiating subsequent ssh sessions, your ssh client will hash the hostname you type and look it up in the known_hosts file to find the previously-recorded ssh host key for the remote server. You will effectively still be able to automatically verify ssh host keys but attackers won't be able to harvest hostnames and IP addresses from the known_hosts file.

Today is HashKnownHosts usually set by default to yes. That implies that you can't edit nor view your known_hosts key file. So if the public key of a known host changes (for example because it was reinstalled), you get usually an error message like below if you try to establish a connection to the host, SSH assumes a Man-in-the-middle_attack.

$ ssh example.com

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that the RSA host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
23:00:21:33:d4:0f:95:f1:eb:34:b2:57:cf:3f:2c:e7.
Please contact your system administrator.
Add correct host key in /home/user/.ssh/known_hosts to get rid of this message.
Offending key in /home/user/.ssh/known_hosts:8
RSA host key for example.com has changed and you have requested strict checking.
Host key verification failed.

In such a case you can use the StrictHostKeyChecking option. You can either set it for the current connection with the -o flag, or you can set a default value for it in the ssh_config file.
When set to yes, it will allow only to connect to hosts which's public key is already listed in knwon_hosts, when set to ask, it will ask you to accept the public key of new hosts, appending them afterwards to known_hosts. But if the host is already listed in the file with a different public key, it will refuse to connect with a warning message. When set to no, it will automatically accept and save previously unknown host's public key, and warn when a key changed.

To get a host's base64 encoded key issue the command:

$ ssh-keyscan -t rsa,dsa hostname

Optionally you can specify -H to have the key displayed in the hashed form. -v increases verbosity.

To search for an entry in known_hosts issue:

$ ssh-keygen -H  -F hostname

You can also delete a single entry from known_hosts:

$ ssh-keygen -R hostname

More useful options include:

  • NoHostAuthenticationForLocalhost: Turn off host key checking for the local machine only. Useful if you set up SSH Port Forwards to remote machines, ala ssh -p 9999 localhost, but you need to live with the consequences. Better to use HostKeyAliases as appropriate.
  • HostKeyAlias: This option allows you to specify an 'alias' that will be used, instead of the actual hostname on the command line, when looking for a match in the known_hosts file. Particularly useful for commands that use ProxyCommands to connect, or are based on multiple ports on a machine that forward to different SSH servers behind it, such as a firewall.