As the golden standard of secure remote access, the Secure Shell (SSH) protocol has several layers of protection. One of them involves recording and keeping track of the known servers on the client side.
In this tutorial, we check ways to ignore the list of known hosts when connecting to a server via SSH. First, we delve into the file, which holds all known hosts. Next, we look at the mechanism that checks connections against that file. Finally, we show ways to bypass it.
For brevity and security reasons, we only consider the newest iteration of SSH version 2 (SSHv2) as implemented by OpenSSH.
We tested the code in this tutorial on Debian 11 (Bullseye) with GNU Bash 5.1.4 and OpenSSH 8.4p1. It should work in most POSIX-compliant environments.
$ cat $HOME/.ssh/known_hosts |1|b5fsiYN[...]6eTbrpE=|U3VYg[...]6rbGs+l3U= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyN[...]KhcRXB3zj/eIdk+kO7CYQy+u6Kc=
However, we can change its location via the UserKnownHostsFile option in /etc/ssh/ssh_config. In fact, there can be a GlobalKnownHostsFile as well. Its default paths are /etc/ssh/ssh_known_hosts and /etc/ssh/ssh_known_hosts2.
Basically, each such file contains a list with several columns, separated by whitespace:
- Identifying host data
- Host key type
- Host key value
- Optional comment
The first column can be hashed or cleartext, depending on the setting of HashKnownHosts in /etc/ssh/ssh_config. Notably, the default is no, but setting it to yes does not automatically hash current entries. Still, we can do that manually via ssh-keygen.
When hashed, the first field of each line starts with |1|, a HASH_MAGIC marker. After the latter, the field continues with a random 160-bit string, otherwise known as a salt, followed by a 160-bit SHA1 hash. Each of these is encoded in base64.
Of course, the main idea behind hashing is to hide the IP address or hostname data, which would otherwise be directly visible:
$ cat $HOME/.ssh/known_hosts 192.168.6.66 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyN[...]KhcRXB3zj/eIdk+kO7CYQy+u6Kc=
Either way, known_hosts contains a mapping between a server as identified by its characteristics and its key. Yet, what happens when these change?
3. Known Hosts Checking
When connecting to a remote host, SSH checks the known_hosts file of the client to confirm the address or hostname for the server match the key we get from it.
If there is a match, the session setup can continue. Otherwise, we get an error:
$ ssh 192.168.6.66 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ 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 a host key has just been changed. The fingerprint for the ECDSA key sent by the remote host is SHA256:q0liAwJ8kwnc[...]ai7et9iz56+5A. Please contact your system administrator. Add correct host key in /home/baeldung/.ssh/known_hosts to get rid of this message. Offending ECDSA key in /home/baeldung/.ssh/known_hosts:1 remove with: ssh-keygen -f "/home/baeldung/.ssh/known_hosts" -R "192.168.66.6" ECDSA host key for 192.168.6.66 has changed and you have requested strict checking. Host key verification failed.
In essence, the above message tells us that the entry for 192.168.6.66 in the known_hosts file doesn’t match the (Elliptic Curve Digital Signature Algorithm, ECDSA) key we got back from the server at that address. Critically, if we don’t know what caused the error, we should heed the text in capital letters: something nasty can indeed be happening.
On the other hand, the reasons for such an issue can be valid and trivial:
- dynamic IP address
- changed hostname
- reinstalled system
- reinstalled SSH
- Docker container
- misconfigured DHCP
- relocated client
In fact, there can be many more. Under these circumstances and while debugging, we may still want to try and connect to the offending server.
4. Bypass Known Hosts
In addition to the warning about remote host identification issues, the error text when connecting to a misidentified host tells us a few remedies for the situation. Let’s explore each and add some of our own.
4.1. Correct the Row
Since we already know which row of the known_hosts file doesn’t match (the suffix :1 of /home/baeldung/.ssh/known_hosts:1), we can correct the host data, key type, and value. By default, there are several host keys:
4.2. Remove the Row
If we trust the host and don’t want to bother correcting the line by hand, we can simply remove the entry with the supplied command:
$ ssh-keygen -f "/home/baeldung/.ssh/known_hosts" -R "192.168.66.6" # Host 192.168.6.66 found: line 1 /home/baeldung/.ssh/known_hosts updated. Original contents retained as /home/baeldung/.ssh/known_hosts.old
Here, the -R flag to ssh-keygen removes the entry after it from the file supplied to -f. Now, there will be a new confirmation request upon the next connection:
$ ssh 192.168.6.66 The authenticity of host '192.168.6.66 (192.168.6.66)' can't be established. ECDSA key fingerprint is SHA256:i3jbBbq12jnm[...]ytYdefZum0111. Are you sure you want to continue connecting (yes/no/[fingerprint])?
At this point, we can add the new key via the prompt.
4.3. Permanently Ignore
Another way to bypass the host checks is by adding a Host statement for the offending server in our ssh_config:
Host MISIDENTIFIED_HOST StrictHostKeyChecking no UserKnownHostsFile /dev/null GlobalKnownHostsFile /dev/null
Here, we disable several checks for our particular MISIDENTIFIED_HOST:
- StrictHostKeyChecking no means we won’t need a match to connect to a server
- UserKnownHostsFile /dev/null overrides our default $HOME/.ssh/known_hosts path with the empty /dev/null
- GlobalKnownHostsFile /dev/null overrides the default global known hosts file path again with the empty /dev/null
Essentially, this combination of three options strips the security of hosts checking and prevents additions to the known_hosts files for a given machine.
4.4. Temporarily Ignore
In some cases, we may want to ignore the known hosts only temporarily:
$ ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o GlobalKnownHostsFile=/dev/null 192.168.6.66
Here, we directly pass each of the options from before via -o flags when connecting to the misidentified server. Doing so enables easier debugging without global changes to the configuration.
In this article, we looked at the known_hosts file structure and ways to ignore the known hosts from an SSH client.
In conclusion, depending on our aims, we can use one of several options to bypass host checking when establishing an SSH session.