When you connect first time to a given SSH server, you get the usual question with the key fingerprint; afterwards, the SSH client stores a copy of the server public key in the .ssh/known_hosts
file. But the SSH client actually stores two keys: one for the server name, and one for the server IP.
For instance, assume that server foo.example.com
has IP 10.0.0.8
. Upon your first connection (ssh foo.example.com
), the SSH client will get the server public key, display the fingerprint (a hash of the public key), ask for confirmation, and then store in the known_hosts
file two mappings, one for foo.example.com
, the other for 10.0.0.8
, both pointing to the same public key.
When you connect back to the same server, SSH verifies the two mappings. If the first mapping (the one for the name) yields a public key that is distinct from the one recorded in known_hosts
, you get the scary error message with UPPERCASE LETTERS (that's how it manages to be scary), and the client refuses to connect any further (so the message is not only scary, it is quite inconvenient as well).
Another situation is when the first mapping matches:
- The user types:
ssh foo.example.com
.
- The DNS system resolves that name to IP
10.0.0.8
.
- The SSH client connects to that machine, and obtains the SSH server public key.
- The obtained public key matches the one found in
.ssh/known_hosts
under the entry foo.example.com
.
- BUT the obtained public key does NOT match the one found in
.ssh/known_hosts
under the entry 10.0.0.8
.
In that case, you get the exact message that you display in your question. The SSH client has some assurance that you are talking to the intended server -- the public key matches the one recorded for the same server name -- but something is still amiss, hence the warning, and the confirmation prompt.
This can happen when the server IP has changed. With the example above, suppose that, last week, foo.example.com
had IP 10.0.0.7
, but bar.example.com
had IP 10.0.0.8
. At that time, you connected to both. But last week-end, a sysadmin with slight obsessional compulsive disorder decided that some IP had to be changed, so that he could setup more efficient, regular and mathematically elegant networking rules. So he "moved servers around", and set bar.example.com
to IP 10.0.0.16
and foo.example.com
to 10.0.0.8
. Our friend the sysadmin dutifully configured the DNS to report the new IP. Now, we are on Monday, and you want to connect again. Your SSH client talks to the DNS, gets the new IP for foo.example.com
, and all is fine, except that the recorded key for 10.0.0.8
does not match the public key of foo.example.com
: indeed, your known_hosts
file contains a copy of the public key of bar.example.com
, listed under the IP 10.0.0.8
, which, up to last week, was bar
's IP, not foo
's.
A sysadmin with OCD is not strictly necessary for this scenario; it can also happen with dynamic IP setups, or with some cases of load-balancing.
Solution: use a text editor and remove the offending entry from your known_hosts
(line 14, in your case). You can also use the command ssh-keygen -R <host>
to remove the particular entry. Next time you will connect, the client will display yet another warning (this time complaining about the absence of any recorded public key for the target IP), but this one will fly by almost unnoticed, because there will be no prompt at all. The SSH client will then record the public key again in known_hosts
, and set things right, at least until the sysadmin hear voices again.
Alternatively, disable host IP checking in the SSH client, by setting the option CheckHostIP
to no
(in the system-wide /etc/ssh/ssh_config
, or your .ssh/config
, or directly on the command-line: ssh -o CheckHostIP=no foo.example.com
). Host-IP checks are useful to detect abnormal situations of wandering server names, but for some sysadmins, server IP jugglery is perfectly "normal".