29

I'm running some non-critical Ubuntu servers in my dorm room in college. Turned them off before break, come back, SSH in, and get a warning that the ECDSA keys have changed.

It looked pretty much like this

Warning: the ECDSA host key for '<snip>' differs from the key for the IP address '<snip>'
Offending key for IP in /home/<snip>/.ssh/known_hosts:14
Matching host key in /home/<snip>/.ssh/known_hosts:12
Are you sure you want to continue connecting (yes/no)?

This looks a lot less scary than the server identity changed error so I'm not worrying too much but still, what would cause this to change? Is this something I should be worrying about?

3 Answers 3

41

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".

10

Assuming I am guessing the <snip> parts correctly, looks like the hostname (example.com) is now resolving to a different IP than it was before.

Whether or not you need to worry about that is difficult to tell without more information. What form is the hostname? Is it an FQDN? Is it resolved using DNS? Did you make any DNS changes? That kind of information.

It's probably better if you replace your hostnames and IPs with examples (example.com, example.net, example.org and anything-you-want.test are good for hostnames, private IPs like 192.168.foo.bar or 10.foo.bar.baz are good for IPs), that way the command output is easier to interpret. You can also use this to indicate whether two domains are in the same TLD, whether two IPs are in the same subnet, etc. so it's very useful.

5

If the IP wasn't moved and the openssh-server package wasn't upgraded and a new host key generated, then what happened?

While you can disable the host key check, this isn't a practice I would start.

What seems to have happened is that ssh is now using a different host key system (ECDSA vs DSA or RSA) and the warning is making us aware of that.

1
  • 1
    This change could have occurred in a recent upgrade of openssh-server. Aug 7, 2012 at 16:37

You must log in to answer this question.

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