1

Let's imagine the following scenario.

I have an host key ABCDEF1234 for a given hostname, so my known_hosts file looks like this (unhashed version):

example.com ssh-rsa ABCDEF1234 

Now I connect to it, and hostnames resolve to 10.11.12.13 I have a message like this

Warning: Permanently added the ECDSA host key for IP address '10.11.12.13' to the list of known hosts.

And my known_hosts looks like this

example.com ssh-rsa ABCDEF1234 192.0.2.1 ssh-rsa ABCDEF1234 

Now a few month later, example.com admin tells me the RSA key is removed and changed in favour of 1234ABCDEF key. So I remove the offending key using ssh-keygen -R example.com, then I connect for the first time, accepts the key, and know my known_host looks like this:

192.0.2.1 ssh-rsa ABCDEF1234 example.com ssh-rsa 1234ABCDEF 

And every time I connect I have this nice warning message:

Warning: the ECDSA host key for 'example.com' differs from the key for the IP address '192.0.2.1' Offending key for IP in /home/jenkins/.ssh/known_hosts:162 Matching host key in /home/jenkins/.ssh/known_hosts:182 

Now imagine there are tens or hundreds of IP for that particular hostname, that is quite a lot of lines to clean. One solution is to use sed to remove matching lines, but isn't the goal of ssh-keygen -R to avoid messing with sed?

sed -i '/ABCDEF1234/d' known_hosts

Is there another solution, that would remove all entries from a known_host file that are associated with a given key, instead of an hostname or IP address ?

6
  • I think this post has your answer askubuntu.com/questions/123072/ssh-automatically-accept-keys Commented Aug 29, 2023 at 7:48
  • 2
    Why do you use: ssh-keygen -R myhost.com to remove the entry for myhost.com,, and do you not use: ssh-keygen -R 10.11.12.13 to remove the entry for 10.11.12.13 ? Commented Aug 29, 2023 at 8:15
  • @Luuk Let's say github.com changes its rsa key, do you know all IP of github.com ? Of course if I have single ip, I can do waht you suggest. Commented Aug 29, 2023 at 8:47
  • That's why, when you connect to github.com, you will not use an ip-address, but use a hostname. Commented Aug 29, 2023 at 8:56
  • 2
    shodanex: which Ubuntu? Adding both hostname and IP to known_hosts was long the default behavior in OpenSSH, but you could disable it by setting option CheckHostIP = no on the commandline with -o or in your config file(s). OpenSSH 8.5 changed the default to no, and Ubuntu 22.04 up should have OpenSSH 8.9 up. Commented Aug 30, 2023 at 1:38

2 Answers 2

4

The purpose of ssh-keygen -R is not to avoid using sed, but to remove hashed hosts that, e.g., sed could not find. From ssh-keygen(1):

-R hostname

Removes all keys belonging to hostname from a known_hosts file. This option is useful to delete hashed hosts (see the -H option above).

-H

Hash a known_hosts file. This replaces all hostnames and addresses with hashed representations within the specified file; the original content is moved to a file with a .old suffix. These hashes may be used normally by ssh and sshd, but they do not reveal identifying information should the file's contents be disclosed. This option will not modify existing hashed hostnames and is therefore safe to use on files that mix hashed and non-hashed names.

Considerations

Avoid collisions

Notice that it is best to use the full public key encoded in Base64 to avoid removing other keys. E.g., if you use just parts of the header your would end up removing all the keys of the same type:

 Base64 ASCII Ref.
AAAAE2VjZHNhLXNoYTItbmlzdHAyNTY
AAAAIbmlzdHAyNTYAAABBB
....ecdsa-sha2-nistp256
....nistp256...A
RFC 5656, 3.1
AAAAC3NzaC1lZDI1NTE5AAAAIFKy ....ssh-ed25519... R² RFC 8709, 4
AAAAB3NzaC1yc2EAAAADAQABAAABAQ ...ssh-rsa........... RFC 4253, 6.6

Adjust your sed for Base64

The Base64 encoded public key contains characters A-Za-z0-9+/=. As it can contain the / used in your sed example, you would like to use another character like :.

Working examples

In the examples:

  • The AAAA+OLD/KEY= is a placeholder for the full old public key.
  • The AAAA+NEW/KEY= is a placeholder for the full new public key.

Remove all hosts having the same key

Use the full old key to remove all lines containing it:

sed -i ':AAAA+OLD/KEY=:d' ~/.ssh/known_hosts

Replace the old key with a new one

Use the full keys (old & new) to replace it on all lines containing the old key:

sed -i 's:AAAA+OLD/KEY=:AAAA+NEW/KEY=:g' ~/.ssh/known_hosts

If the key type also changes, you would have to include it, e.g.,

sed -i 's:ssh-rsa AAAA+OLD/KEY=:ecdsa-sha2-nistp256 AAAA+NEW/KEY=:g' ~/.ssh/known_hosts

Remove keys for the hostname or IP

This is the only use case where you would use ssh-keygen.

ssh-keygen -R example.com

ssh-keygen -R 192.0.2.1

2

Avoiding the issue in the first place is a good solution. If known_hosts wasn't filled with entry for each and every IP for a given hostname, there would be no need to mess with sed. ssh_keygen -R hostname would be sufficient to perform key rotation.

So my solution to this is to set CheckHostIP to no in the ssh config.

How does the SSH option CheckHostIP=yes really help me?

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.