Everybody using SSH knows the problem: You connect to a server for the
first time and your client asks you to confirm the fingerprint of the
key. How often have you just accepted what is presented to you without
verifying it?
This is not to say that this is entirely useless. But the
problem in asking the user for his approval of a hashed crypto key is
pretty clear: The user just cannot remember it and will most likely
ignore it. At the moment, I see the major benefit in these fingerprints
in detecting a possibly compromised system.
SSL solves this problem by making use of certificate authorities (like VeriSign, Thawte, etc.). These authorities have their certificate shipped with your browser. When you try to access an SSL enabled website, your browser will implicitly trust your certificate, because it was signed by one of these CAs.
At the moment there is no such facility for SSH. However in day-to-day use we do not want to and quite often even cannot verify these fingerprints. How many of you have a list of the SSH fingerprints of their systems? We actually do! But it is still a pain to manually check against it.
DNS to the rescue
DNS offers a so called SSHFP resource record with which we can publish exactly these fingerprints inside of the already existing DNS infrastructure. This enables the SSH client to do this verification for us.
But wait, is DNS secure?
By using DNSSEC we can verify the authenticity of the information we retrieve from DNS. OpenSSH already implements a configuration option called VerifyHostKeyDNS. From the ssh_config manpage:
How to use it
On your servers:
To make use of this feature you first have to publish the SSH fingerprints of the system you want to secure in the respective DNS zone.
First you log into the system that you want to secure.
Once you are logged into the system you retrieve the SSHFP records by executing this:
On your clients:
To enable OpenSSH to actually verify the SSH fingerprints in DNS you need to add the following to your ~/.ssh/config file (or your global /etc/ssh/ssh_config):
The Good, the Bad and the Ugly
The Good: Using existing infrastructure
This is just a matter of enabling a SSH feature and providing SSHFP records inside your existing DNS infrastructure. No additional complex systems (like your own CA) needed.
The Bad: No reverse DNS support
A minor problem with the current OpenSSH implementation is, that it refuses to query for SSHFP records in reverse DNS zones. However it is very plausible to have SSH fingerprints provided for a particular IP address. This however is a minor bug that can be solved by a few lines of code in a future release.
The Ugly: DNSSEC support in libresolv
Unfortunately we do not yet live in a perfect DNSSEC world. Most UNIX based systems use libresolv to query DNS from applications. However on most systems I have tested (Debian, Ubuntu, CentOS and MacOS) you cannot configure libresolv to send the DO bit in the requests. This means that the local resolver is not able to ask specifically for DNSSEC validation. That in turn also means that no AD bit is sent in the response and the local system cannot see if the query is DNSSEC validated.
At the moment OpenBSD was the only system that I found to have support for this. You can enable EDNS0 via an option in /etc/resolv.conf. An example would look like this:
Support in other SSH clients
The main dependency for this feature to be widely available for clients on various systems is a DNSSEC enabled local resolver.
As noted above this is already available for most UNIX based systems but it still lacks configurability. Please make sure you request this for your operating system(s).
Microsoft has planned DNSSEC support for Windows 7. Once this is available this would enable the developers of PuTTY to implement this and get it off their wishlist.
Further reading
SSL solves this problem by making use of certificate authorities (like VeriSign, Thawte, etc.). These authorities have their certificate shipped with your browser. When you try to access an SSL enabled website, your browser will implicitly trust your certificate, because it was signed by one of these CAs.
At the moment there is no such facility for SSH. However in day-to-day use we do not want to and quite often even cannot verify these fingerprints. How many of you have a list of the SSH fingerprints of their systems? We actually do! But it is still a pain to manually check against it.
DNS to the rescue
DNS offers a so called SSHFP resource record with which we can publish exactly these fingerprints inside of the already existing DNS infrastructure. This enables the SSH client to do this verification for us.
But wait, is DNS secure?
By using DNSSEC we can verify the authenticity of the information we retrieve from DNS. OpenSSH already implements a configuration option called VerifyHostKeyDNS. From the ssh_config manpage:
Specifies whether to verify the remote key using DNS and SSHFP resource records. If this option is set to ``yes'',the client will implicitly trust keys that match a secure fingerprint from DNS. Insecure fingerprints will be handled as if this option was set to ``ask''. If this option is set to ``ask'', information on fingerprint match will be displayed, but the user will still need to confirm new host keys according to the StrictHostKeyChecking option. The argument must be ``yes'', ``no'', or ``ask''. The default is ``no''. Note that this option applies to protocol version 2 only.
How to use it
On your servers:
To make use of this feature you first have to publish the SSH fingerprints of the system you want to secure in the respective DNS zone.
First you log into the system that you want to secure.
Once you are logged into the system you retrieve the SSHFP records by executing this:
This gives you the DNS resource records that reflect the public key of this system (RSA and DSA). Example:$ ssh-keygen -r `hostname`. -f /etc/ssh/ssh_host_rsa_key; \
ssh-keygen -r `hostname`. -f /etc/ssh/ssh_host_dsa_key
Now the only thing you need is transfer these into your DNS zone (in this example yourcompany.invalid).hostname.yourcompany.invalid. IN SSHFP 1 1 d3b07384d113edec49eaa6238ad5ff0049eaa623
hostname.yourcompany.invalid. IN SSHFP 2 1 40f85931c157a79031e1c40f85931829bc5fc552
On your clients:
To enable OpenSSH to actually verify the SSH fingerprints in DNS you need to add the following to your ~/.ssh/config file (or your global /etc/ssh/ssh_config):
Now, once we connect to the system we get the following (I enabled verbose output to make the magic visible):Host *
VerifyHostKeyDNS yes
In case of an unsigned zone the information from DNS is only used as a support for the user. OpenSSH will still ask the user to confirm that he trusts this key.ssh -v hostname.yourcompany.invalid
[Unimportant output removed]
debug1: found 2 secure fingerprints in DNS
debug1: matching host key fingerprint found in DNS
debug1: ssh_rsa_verify: signature correct
[Unimportant output removed]
$
ssh -v hostname.yourcompany.invalid
[Unimportant output removed]
debug1: found 2 insecure fingerprints in DNS
debug1: matching host key fingerprint found in DNS
The authenticity of host 'router.as112.ripe.net (193.0.0.216)' can't be established.
RSA key fingerprint is 77:a2:72:0b:f1:9c:43:f2:c4:90:e7:3d:17:97:b4:18.
Matching host key fingerprint found in DNS.
Are you sure you want to continue connecting (yes/no)? yes
[Unimportant output removed]
$
The Good, the Bad and the Ugly
The Good: Using existing infrastructure
This is just a matter of enabling a SSH feature and providing SSHFP records inside your existing DNS infrastructure. No additional complex systems (like your own CA) needed.
The Bad: No reverse DNS support
A minor problem with the current OpenSSH implementation is, that it refuses to query for SSHFP records in reverse DNS zones. However it is very plausible to have SSH fingerprints provided for a particular IP address. This however is a minor bug that can be solved by a few lines of code in a future release.
The Ugly: DNSSEC support in libresolv
Unfortunately we do not yet live in a perfect DNSSEC world. Most UNIX based systems use libresolv to query DNS from applications. However on most systems I have tested (Debian, Ubuntu, CentOS and MacOS) you cannot configure libresolv to send the DO bit in the requests. This means that the local resolver is not able to ask specifically for DNSSEC validation. That in turn also means that no AD bit is sent in the response and the local system cannot see if the query is DNSSEC validated.
At the moment OpenBSD was the only system that I found to have support for this. You can enable EDNS0 via an option in /etc/resolv.conf. An example would look like this:
I have found the following bug listings dealing with this issue. Please go ahead and comment on them to give them a higher priority:nameserver your.resolver.ip.address
lookup file bind
options edns0
- https://bugzilla.redhat.com/show_bug.cgi?id=205842
- https://bugs.launchpad.net/ubuntu/+source/openssh/+bug/242956
Support in other SSH clients
The main dependency for this feature to be widely available for clients on various systems is a DNSSEC enabled local resolver.
As noted above this is already available for most UNIX based systems but it still lacks configurability. Please make sure you request this for your operating system(s).
Microsoft has planned DNSSEC support for Windows 7. Once this is available this would enable the developers of PuTTY to implement this and get it off their wishlist.
Further reading

Migrated from old blog system - original post date: August 10, 2009 11:04 AM
Good news! The bug for RedHat had quite some progress over the course of the last weeks. The next release should support for the 'edns0' option in resolv.conf. I would prefer if it would also seperate EDNS from DNSSEC, but it is a good first step.
Posted by: wnagele | March 4, 2010 at 21:07
Migrated from old blog system - original post date: August 10, 2009 1:48 PM
Apparently i misread the code for this. The current implementation is already separating this properly. If you enable 'edns0' in resolv.conf it will be able to use the DO bit. It is still up to the application (OpenSSH in the example above) to set the DO bit accordingly.
Posted by: wnagele | March 4, 2010 at 21:07
Now you can use OpenSSH with ldns to make this work: http://jpmens.net/2012/07/27/verifyhostkeydns-yessssss/
Posted by: wnagele | July 27, 2012 at 14:19