Ssh – Why does SSH add a known_host entry for an IP address

ssh

I have a host named nms.example.org. In my /etc/ssh/ssh_known_hosts I have an entry for the host with the RSA key. This entry, and all the other entries are managed by my configuration management system.

nms.example.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDZqfmVPs/XqTS...

Also I have an entry in my /etc/ssh/ssh_config for the specific host setting the host key alias. Which if I understand everything properly, this means that only the nms.example.org should matter.

Host nms.example.org nms.example nms
    HostKeyAlias nms.example.org
    HostName nms.example.org

Why then, when I connect from a client does ssh still seem to think it needs to add an key to my per-user known_hosts with the IP of the host?

$ ssh nms -v
OpenSSH_6.0p1 Debian-4+deb7u4, OpenSSL 1.0.1e 11 Feb 2013
debug1: Reading configuration data /home/zoredache/.ssh/config
debug1: /home/zoredache/.ssh/config line 61: Applying options for *
debug1: /home/zoredache/.ssh/config line 71: Applying options for *
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 84: Applying options for nms
debug1: /etc/ssh/ssh_config line 363: Applying options for *
debug1: Connecting to nms.example.org [104.236.190.144] port 22.
debug1: Connection established.
debug1: identity file /home/zoredache/.ssh/zoredache-20140204.id_rsa type 1
...
debug1: Server host key: RSA 6b:5f:b6:e9:13:c3:b7:39:1e:ec:74:05:33:64:4d:5e
debug1: using hostkeyalias: nms.example.org
debug1: Host 'nms.example.org' is known and matches the RSA host key.
debug1: Found key in /etc/ssh/ssh_known_hosts:104
Warning: Permanently added the RSA host key for IP address '192.0.2.144' to the list of known hosts.
debug1: ssh_rsa_verify: signature correct
...

SSH knows my host is valid (See: Host 'nms.example.org' is known and matches the RSA host key) so why does it add the key for the IP to a user profile?

This is extremely irritating, because when I reinstall a machine, my configuration management system handles collecting and distributing the host keys to all system just fine. But there will be these left over conflicting keys associated with IPs in per-use known_host files that cause warnings on a connection attempt that prevent scripts from connecting.

$ ssh nms -v
OpenSSH_6.0p1 Debian-4+deb7u4, OpenSSL 1.0.1e 11 Feb 2013
...
debug1: Local version string SSH-2.0-OpenSSH_6.0p1 Debian-4+deb7u4
debug1: using hostkeyalias: nms.example.org
...
debug1: Server host key: RSA 6b:5f:b6:e9:13:c3:b7:39:1e:ec:74:05:33:64:4d:5e
debug1: using hostkeyalias: nms.example.org
debug1: Host 'nms.example.org' is known and matches the RSA host key.
debug1: Found key in /etc/ssh/ssh_known_hosts:104
Warning: the RSA host key for 'nms.example.org' differs from the key for the IP address '192.0.2.144'
Offending key for IP in /home/zoredache/.ssh/known_hosts:25
Matching host key in /etc/ssh/ssh_known_hosts:104
Are you sure you want to continue connecting (yes/no)?

How can I prevent ssh from caching this per-IP value in each users known_hosts? Or is there some security reason why I just have to live with this annoying behavior? This is also frustrates me because a couple servers have somewhat dynamic IP addresses. My configuration management handles the DNS updates. But I get these left over per-IP host keys filling up my per-user known_host files.

Best Answer

I think it's to make the CheckHostIP work.

If this flag is set to “yes”, ssh(1) will additionally check the host IP address in the known_hosts file. This allows ssh to detect if a host key changed due to DNS spoofing. If the option is set to “no”, the check will not be executed. The default is “yes”.

You get slightly better diagnostics in case of a misconfiguration or attack with this option, but it doesn't actually improve security in any way that I can think of.

If you turn off CheckHostIP then SSH (as of OpenSSH 6.7p1) does not record the IP address when you connect to a new host by name. So add this to your .ssh/config:

CheckHostIP no

You can add it to a Host section if you only want to turn it off for a specific host (especially one with a dynamic IP address).

Related Question