8

There are many discussions about this option and most people argue that "it improves security", "it protects you from MiTM attacks/DNS spoofing", etc, but I fail to see how that is true. ssh_config(5) says that the option

"allows ssh to detect if a host key changed due to DNS spoofing"

but it still seems vague or even misleading, because 1) the option doesn't detect if a "host key has changed" but only if a host's IP has changed, and 2) It doesn't elaborate on what it does when it detects such a thing (for example, does it stop the connection from happening?).

Because of the vagueness of the documentation, other people even seem to believe that CheckHostIP=yes will not let you connect to a host that has changed its IP (i.e. it has a different IP than the one that is already recorded in known_hosts) which is totally untrue, at least as far as I can understand through my own tests.

  • When I connect with CheckHostIP=yes (the default) to a remote server whose host key is already stored in known_hosts, but has changed its IP, the connection proceeds normally but I get a warning:

"Permanently added the ECDSA host key for IP address [......]"

Also a new line is appended into known_hosts, containing the server's host key (which has not changed) and the new IP address (which is different). If the host later changes its IP again and I connect to it with CheckHostIP=yes, a new line will be appended in known_hosts, and so on.

  • If I connect with CheckHostIP=no to a server that has changed its IP address, the connection proceeds (which is what also happens with CheckHostIP=yes) but this time without a warning, and without appending a new line in known_hosts.

So the only difference between yes and no seems to be only a simple one-line warning upon connecting, plus the recording of new addresses in known_hosts every time the host changes its IP (effectively keeping a history record of a server's different IP's through time).

If that's the case then I'm not even sure that CheckHostIP=yes is better than CheckHostIP=no, because if the client machine was compromised the attacker would be able to deduce from known_hosts that 1) The server with the host key X has a dynamic IP, and 2) It has changed its IP address Y times. Obviously it's not much and I doubt the attacker could actually do something with that bit of information, but it is leakage of information that would not happen with CheckHostIP=no.

I have tried the above with two separate ssh servers that have dynamic IP's (I use a free DDNS service to connect to them).

Can an SSH guru confirm to me that this is all the protection CheckHostIP=yes offers (a warning that doesn't even ask for user interaction), or correct me if I am terribly wrong about something? Should I just always keep CheckHostIP=no for connections to servers that I know will be changing their IP's through time?

5
  • I'm not sure what's different in your config file, but when I connect to a known host on a different ip address it asks me if I'm sure I want to connect and makes me type yes before continuing.
    – Will
    Oct 29, 2020 at 14:24
  • I've used 2 different clients to connect to the server(s). One client is a raspberry pi (OpenSSH_7.9p1) and the other is my Android cellphone through Termux app (OpenSSH_8.3p1). In both cases the config file is untouched...
    – AndroidX
    Oct 29, 2020 at 14:37
  • Perhaps it's a setting on the server itself? Recently I've been migrating my home server to a vm host. Ips have been changing during setup and any time ips changed I got warned the next time I connected to the host through either Manjaro (my workstation), Proxmox sshing into the VMs/containers, my migrated server running Ubuntu (14.04>20.04) a Debian LXC, a fresh Ubuntu 20.04 I was going to use as the server before migrating my existing install into a VM, and even using Connectbot /Termbot from my android phone. In every case I have to accept the warning to connect if the ip has changed.
    – Will
    Oct 29, 2020 at 15:20
  • That's strange because what you're saying is that CheckHostIP=yes actually triggers an interactive prompt if the known host's IP has changed. The problem is that I tried the above with 2 different remote servers, same result. I just checked right now connecting to one server with an untouched sshd_config file (OpenSSH_7.9p1 Debian-10+deb10u2) that has just changed its IP, same result (as outlined in my post). I don't get it. I will try to ssh into both servers via another client later but I doubt I'll get different results...
    – AndroidX
    Oct 29, 2020 at 15:36
  • I've experienced similar issues as the OP @AndroidX , my initial guess was something related to having AddKeysToAgent yes for the Host * in the file ~/.ssh/config. But after tinkering with it for a bit didn't seem to take effect. Any ideas? Apr 28, 2022 at 11:22

1 Answer 1

4

Summary

In my view, CheckHostIP just reassures you that an attacker who has already compromised your remote server's private key hasn't also poisoned your local DNS.

If you got here because of the GitHub RSA key leak, cycle the host key in known_hosts like they tell you to in the blog post.

Expert opinion

An "SSH guru," specifically an OpenSSH maintainer, has affirmed your position.

I think we're more likely to turn off CheckHostIP (the thing that spams addresses into known_hosts) in the short term, as nobody has satisfactorily explained what problem it solves to me.

@DamienMiller (Twitter, 2020-12-11)

Three months later, Damien followed through in the release of OpenSSH v8.5 on 2021-03-03, where CheckHostIP was turned off with this changelog message:

  • ssh(1): disable CheckHostIP by default. It provides insignificant benefits while making key rotation significantly more difficult, especially for hosts behind IP-based load-balancers.

Bringing back CheckHostIP

If you really want to keep CheckHostIP, you can turn it back on and disable it only for hosts with dynamic IPs to skip the warning and known_hosts pollution. Don't do this, though. It's not that helpful.

It is so improbable that CheckHostIP is a meaningful measure for dealing with a threat actor who can both…

  • Steal the private key of the remote SSH server, and
  • Manipulate your client's DNS resolution.

In the face of such a foe, it seems ludicrous that somehow you'll be saved by the "Warning: Permanently added host key" message when connecting to a host, especially when it shows you the warning1 every single time.

The known_hosts trick

Some people proactively dump all the known IPs for a service into a known_hosts line. I think they're doing this just to avoid the warning message. It front-loads all the nonsense into known_hosts that you'd gradually accumulate otherwise. But frankly, the important part of known_hosts is not the IP, it's the host key.

In order to cut down on the super-long known_hosts entries, other people simulate IP ranges with wildcards, which may appear clever, but it's actually finicky and it only works because CheckHostIP works against IPs and ignores hostnames.2

1 That is to say: "when it cries 'Wolf!'"
2 For example, if you try to allow 127.0.0.* for your dynamic-IP SSH server, you technically also match 127.0.0.evilsite.example because IPs and hostnames are not distinguished. You can limit wildcards to single characters with ?, but be careful: 127.0.0.?? will match 127.0.0.cz. Maybe it seems unlikely that .cz would allow 0 as a second-level domain, but we're talking about an adversary who is poisoning your DNS!

1
  • 2
    Thank you for citing a credible source. The spamming in known_hosts was getting really annoying
    – AndroidX
    Aug 26, 2022 at 16:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.