Publishing SSH Fingerprints in DNS

So here’s the thing about SSH: The first time you connect to a server, you have no real idea of if that’s legitimate or not, right? Well, you could compare the key fingerprint to the fingerprint that the server admin gave you and make sure they match, but nobody does that.

Well… there is a way. Using everyone’s favorite always-broken service, DNS.

DNS does have support for this in the form of what’s called an SSHFP record (type 44), which has three fields: the algorithm, the fingerprint type, and the fingerprint data.

The algorithm can be either RSA, DSA, ECDSA, or Ed25519, and the fingerprint type can be either SHA-1 or SHA-256. Doing the multiplication, to have one host with public SSH fingerprints, you need eight DNS records.

Anyways, to get to why this is a thing, we need to talk about… tofu?


SSH uses a principle called Trust On First Use, or TOFU. The thought here is that the first time you connect, you assume it’s valid, if things change around at a later time, then it’s suspect.

You know this, because the first time you try to SSH into a host,1 you get this nice little warning:

The authenticity of host ' (' can't be established.
ECDSA key fingerprint is SHA256:l+QTA4Gxw7mX4L24FBnmvUx/5atQM8Wdvby47/l1Bh0.
Are you sure you want to continue connecting (yes/no/[fingerprint])? y
Warning: Permanently added ',' (ECDSA) to the list of known hosts.

What this is saying is that SSH has never seen this server before and is asking if the displayed fingerprint is, well, acceptable. if you press yes, it’ll warn you that it permanently added the host to the list of known hosts.

Now, if the SSH key changes the next time you connect, you get this thing:

Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
Please contact your system administrator.
Add correct host key in /jack/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /jack/.ssh/known_hosts:2
  remove with:
  ssh-keygen -f "/jack/.ssh/known_hosts" -R ""
ECDSA host key for has changed and you have requested strict checking.
Host key verification failed.

Even better if the DNS address changes, you get another:

The ECDSA host key for has changed,
and the key for the corresponding IP address
is unknown. This could either mean that
DNS SPOOFING is happening or the IP address for the host
and its host key have changed at the same time.

Authenticating On First Use with SSHFP

The traditional solution has been sharing the fingerprints of your hosts to anyone that’s going to connect, so they can manually verify. But this is 2021, and of course, SSH can do this itself.

Add the VerifyHostKeyDNS yes2 option to your SSH config (usually ~/.ssh/config for your user, or /etc/ssh/ssh_config3 for system-wide, if you want to enable for everyone), and suddenly, if the domain you’re connecting to has SSHFP records deployed, you’ll either connect with no warning, or see an additional line in that TOFU question:

Matching host key fingerprint found in DNS.

If the domain is question is properly signed with DNSSEC, SSH will accept the fingerprints and connect, since that data is cryptographically validated, you can definitely trust the unknown key. If the domain doesn’t have DNSSEC, you’ll see that line. It’s telling you that the fingerprint matches what’s publicly advertised, but since it’s not signed with DNSSEC, it’s possible that someone spoofed both the host and the SSHFP records.


  1. The actual known_hosts file tracks the hostname, IP address, and SSH port, which is how I can get away with having one server on port 22 and another on port 2222 without any issues. ↩︎

  2. If this is not desired behavior, and you still want to be asked, even when a DNSSEC-sighed SSHFP record was found, then use VerifyHostKeyDNS ask instead ↩︎

  3. Note that I said ssh_config not sshd_config. The former is system-wide SSH client options. The latter is the SSH server configuration file, if one exists. ↩︎