Human readable .ssh/known_hosts?

Nico Kadel-Garcia nkadel at
Wed Sep 30 12:54:38 AEST 2020

On Tue, Sep 29, 2020 at 9:56 PM Darren Tucker <dtucker at> wrote:
> On Wed, 30 Sep 2020 at 11:09, Nico Kadel-Garcia <nkadel at> wrote:
> > On Tue, Sep 29, 2020 at 8:22 PM Darren Tucker <dtucker at> wrote:
> > > [...] CheckHostIP [...]
> > As I understand this option, it does not help at all with the nearly
> > inevitable re-use of the same IP address for a different host with a
> > different hostkey in, for example, a modest DHCP based environment.
> I don't follow your reasoning here.  If you set CheckHostIP=no then
> ssh does not store or check IP addresses at all, so how can a host's
> reuse of IP addresses cause an issue, so long as the host's hostkey
> and the client's idea of its name (or hostkeyalias) remain the same?
> Or are your hostnames not stable either?

Sadly, in many environments, SSH keys linked to hostnames change. In
Cloud environments where DNS is not thoroughly under the control of he
client, the primary DNS entry and hostname may be the vendor provided
DNS entry linked to the IP address. These are not necessarily stable,
so SSH connections are made by a variety of means, particularly IP
addresses or the cloud assigned hostnames. Alternatively, and this is
one of my favorites, a service such as an SSH based rsync server or
git server can be upgraded by an engineer who fails to realize that
the hostkeys associated with the exposed service should be preserved
in the upgrade process, especially if it's not the same engineer who
did it *last* time.

I *wish* people would be consistent about associating SSH hostkeys
with services. Sadly, they're not.

> $ ssh -o checkhostip=no -o userknownhostsfile=/tmp/hosts somehost
> $ cat /tmp/hosts
> somehost ecdsa-sha2-nistp256 AAAA [etc]
> $ ssh -o checkhostip=yes -o userknownhostsfile=/tmp/hosts somehost
> Warning: Permanently added the ECDSA host key for IP address
> '' to the list of known hosts.
> $ cat /tmp/hosts
> somehost ecdsa-sha2-nistp256 AAAA [etc]
> ecdsa-sha2-nistp256 AAAA [etc]
> If I then replace the IP address one with the fingerprint from another
> host, i complains with CheckHostIP=yes as expected:

I see your point. Uses vary: Sadly, in many environments, DNS is not
complete or consistent. So IP based SSH connections are commonplace,
and this step effectively provides just the "do not use known_hosts"
results I prescribed.

> $ ssh -o checkhostip=yes -o userknownhostsfile=/tmp/hosts somehost echo it works
> Warning: the ECDSA host key for 'somehost differs from the key for the
> IP address ''
> Offending key for IP in /tmp/hosts:2
> Matching host key in /tmp/hosts:1
> but works fine with CheckHostIP=no:
> $ ssh -o checkhostip=no -o userknownhostsfile=/tmp/hosts gate echo it works
> it works
> The other thing you could do (and this is new in OpenSSH 8.4) is you
> can use %-TOKEN expansion on UserKnownHostsFile to store hostkeys in
> per-host files, eg:

Interesting. These days, I work most frequently with Red Hat based
systems, and updating OpenSSH to a leading edge version rather than
the vendor provided version is.... well, it's work and sometimes it
upsets people, even if I've been doing it successfully for decades.
I'd need to think about that one. On a jumpgate server or ansible
server it could be awkward to clutter a user-owned directory with
thousands of such files, What this looks most like is a hack to work
around the hashing of entries in known_hosts, to male key management
more visible. without having to parse or edit .ssh/known_hosts more
dynamically, and to get filesystem timestamps on the recorded public
hostkeys. I need to think about that one. I don't think it solves some
of my use cases, for which I have a longstanding published solution,
but it's a potentially useful feature.

The more I think about this, the more I think "that could actually be
useful for locking down a deployable known_hosts configuration".

> UserKnownHostsFile ~/.ssh/known_hosts.d/% Bk
> which will cause the host keys, including per-IP keys if enabled, to
> be stored in separate files per host.

RHEL 8 is at openssh-8.0p1: I've not bothered to update my published
git repo for building backported RPMs to 8.4p1 yet. I'll post if I
find cycles to do that. Sadly, some of the repositories that were
willing to publish such updates for vendor provided software are no
longer supported, so it can be awkward to find reliable packaging for
such updated tools.

Nico Kadel-Garcia

> --
> Darren Tucker (dtucker at
> GPG key 11EAA6FA / A86E 3E07 5B19 5880 E860  37F4 9357 ECEF 11EA A6FA (new)
>     Good judgement comes with experience. Unfortunately, the experience
> usually comes from bad judgement.

More information about the openssh-unix-dev mailing list