65

I run an Ubuntu desktop with a bunch of virtual servers in Virtual Box to test stuff out, etc. In the past I have also been connecting to other kinds of remote VPS Linux boxes. Currently my .ssh/known_hosts file has a whole bunch of keys in it, most of which are not being used any more.

I want to clean up my .ssh/known_hosts file, but how do I know which key belongs to what host? I.e. how do I know which keys I can safely remove and which ones I should leave alone?

1
  • What I found helpful is to sort the file by the fingerprint: cat ~/.ssh/known_hosts | sort -k3 . This is because ssh in many cases (and it is very unclear to me in which situations exactly) makes multiple entries for the same host, and some may have a claertext host name while others will not. When sorted, it will be obvious which host an obscure entry is for, as long as there is also a clear entry for it.
    – q.undertow
    Apr 3, 2023 at 19:47

4 Answers 4

85

To find out which entry is for a known hostname in known_hosts:

 # ssh-keygen -H  -F <hostname or IP address>

To delete a single entry from known_hosts:

 # ssh-keygen -R <hostname or IP address>
1
  • 2
    It is good to remember that the format can also be [ip address]:port for the argument
    – Vargas
    Jun 26, 2020 at 15:17
30

With difficulty...

Ubuntu by default hashes hostnames the known_hosts file (this is not the default openssh behaviour), to make it difficult for anyone reading the file to know what systems you access.

If you really wanted to clean out the file, simplest option is probably just delete it and check the keys for servers you know as they arise, but really I'd just leave known_hosts alone.

You can stop new hosts entries from being hashed by commenting out the option in /etc/ssh/ssh_config

#HashKnownHosts yes
4
  • Cleaning up ~/.ssh/known_hosts also helps when the configuration of the remote host changes and ssh shows a warning. However one should be careful with that and ignore the warnnig only for trusted hosts.
    – Alex
    Aug 28, 2009 at 8:28
  • 8
    A better option might be to explain how to generate the hash for a specific hostname, allowing him to search for that hash in known_hosts so he can update it.
    – Cerin
    Feb 6, 2012 at 15:58
  • 1
    After above change just add a new entry e.g. by connecting to new server with ssh root@something-new-or-new-dns-alias. This will refresh the original known_hosts file and de-crypt the host names/IPs.
    – Nux
    Feb 23, 2016 at 14:27
  • 1
    @Cerin, at least by now (2021), the following commands are available: ... ssh-keygen -F example.com: shows the known_hosts entry for example.com if it exists, even in hashed form ... ssh-keygen -R example.com: removes the known_hosts entry for example.com if it exists, even in hashed form.
    – Abdull
    Dec 21, 2021 at 14:15
28

If you've got a list of all your hosts, you can do something like

ssh-keyscan -t rsa,dsa -f list_of_hosts > ~/.ssh/known_hosts

That will overwrite your .ssh/known_hosts file with a newly generated one based on scanning the hosts.

And also do what theotherreceive suggests; HashKnownHosts is more annoyance than help here.

1
  • ssh-keyscan has a very strict formatting rules of the list_of_hosts file. It needs to be be just the addres and no other whitespace then LF after each address. That includes LF after last address. Otherwise you get a lot of trash in the generated file.
    – Nux
    Feb 23, 2016 at 14:25
3

I had over 300 stale old entries in my known_hosts file. Not sure that it will work for all systems (or even most systems), but here is my Q&D script. You may have to adjust the matching strings or location.

#!/bin/sh

list=`cat ~/.ssh/known_hosts | awk '{print $1}' |sed -e 's/,/ /g' | sort -u `

listsorted=$(printf "%s\n" ${list[@]} | sort -u)
echo $listsorted
#listsorted="10.2.10.1"
echo > /tmp/sshstat.txt
for host in $listsorted ;
do
echo $host 
ssh -oBatchMode=yes -oConnectTimeout=2  root@${host} "exit" >/tmp/sshstat.txt 2>&1 
ret=$?
if [ $ret -ne 0 ]; then
     echo "Failed: $host"
     echo sed -i.bak \"/$host/d\" "~/.ssh/known_hosts" | sh
else
    grep "Offending RSA" /tmp/sshstat.txt |  sed -e 's/:/ /g' | awk '{printf "sed -i.bak -e \"%dd\" %s  \n", $6, "~/.ssh/known_hosts" }' | sh
   fi
done
#echo $list
1
  • 3
    This doesn't work on a hashed known_hosts file, and since the questioner asks, "how do I know which key belongs to what host" I think it's very likely that his file is hashed. He says he's on Ubuntu, and as theotherreceive says, Ubuntu hashes by default. Aug 8, 2019 at 18:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .