Posted by Steve on Fri 2 Mar 2007 at 11:28
When connecting to a new OpenSSH server for the first time you'll be prompted to accept its host key - but how do you know if it is valid? How do you manage SSH keys for multiple machines?
As part of the package installation the openssh, and openssh-server will generate "host key" which is used when communicating with clients.
The first time you connect to a server you'll see a message similar to this:
steve@steve:~$ ssh localhost The authenticity of host 'localhost (127.0.0.1)' can't be established. RSA key fingerprint is 2d:d3:29:bd:4d:e2:7d:a3:b0:15:96:26:d4:60:13:34. Are you sure you want to continue connecting (yes/no)?
This allows you to test that the key is valid, by showing you the a fingerprint (which is a hash of the full key) and prompting you to confirm its validity.
Once accepted this fingerprint will be stored in the file ~/.ssh/knownhosts either in plain text, or if you're running a recent version of OpenSSH it will be stored in a hashed format. (Set "HashKnownHosts no" if you want to disable this behaviour - either in ~/.ssh/options or /etc/ssh/ssh_config.)
The real question now is how do you know whether the key is valid?
Some organisations store OpenSSH fingerprints online so that you may compare what is presented with what is expected, others assume that 99% of people will merely type "yes" when prompted to accept a key - which is pretty dangerous thing to do.
In the same way that details are stored in ~/.ssh/known_hosts, once accepted, the OpenSSH client program may be configured to read a system-wide list of keys and hostnames.
By default the Debian packages are configured to look at the file /etc/ssh/ssh_known_hosts if it exists.
If you were to build up a list of fingerprints used within your LAN, using the ssh-keyscan command in this file then all your users would avoid prompts connecting to your internal hosts.
As a simple example you could run something like this:
ssh-keyscan -t rsa,dsa cfmaster.my.flat >> /etc/ssh/ssh_known_hosts ssh-keyscan -t rsa,dsa cfmaster >> /etc/ssh/ssh_known_hosts ssh-keyscan -t rsa,dsa mine.my.flat >> /etc/ssh/ssh_known_hosts ssh-keyscan -t rsa,dsa mine >> /etc/ssh/ssh_known_hosts ssh-keyscan -t rsa,dsa yours.my.flat >> /etc/ssh/ssh_known_hosts ssh-keyscan -t rsa,dsa yours >> /etc/ssh/ssh_known_hosts
(Note the use of both "short" and "long" hostnames here; since the machine names must match exactly what the user typed to connect we add both versions. However the users will still be prompted to accept a key if they connect by IP address.)
If you're using a recent version of OpenSSH then it can be configured to check fingerprints against records stored in DNS. This is obviously only an option if you're running your own nameserver, but with the correct options you can see something like this:
steve@steve:~$ ssh localhost -o "VerifyHostKeyDNS=yes" yes authenticity of host 'localhost (127.0.0.1)' can't be established. RSA key fingerprint is 2d:d3:29:bd:4d:e2:7d:a3:b0:15:96:26:d4:60:13:34. Matching host key fingerprint found in DNS. Are you sure you want to continue connecting (yes/no)?
Here you've not been told that the key is valid and trusted, but you've been told that does match what the DNS server-admin has inserted. By contrast a missing key would look like this:
RSA key fingerprint is 2d:d3:29:bd:4d:e2:7d:a3:b0:15:96:26:d4:60:13:34. No matching host key fingerprint found in DNS. Are you sure you want to continue connecting (yes/no)?
Adding the keys to DNS in the first place is a little outside the scope of this introduction/question but you can use software such as sshfp to do the job.
Now that the simple introduction is out of the way here come the questions:
It should have been "yes" - and I've updated the text now.
Either you set it to "no" in which case DNS isn't consulted and you're prompted to accept/reject as normal or you set it to "yes" and you're still prompted - but you get a message such as:
So there is no need for an "ask" setting.
[ Parent ]
[ Parent ]
[ Parent ]
[ Parent ]
[ Parent ]
[ Parent ]
[ Parent ]
[ Parent ]
Then each host would have its own key (e.g. SSH Host Key For host.domain.com <ssh@host.domain.com>
), which would be signed by the relevant administrators (and/or a domain-wide key made specifically for this purpose). If you have an account on that machine, you would presumably already know the operator (because you've arranged with them to get an account), so your ssh client could verify the the signatures on the key using GPG directly.
Other methods of verifying keys programmatically include X509 integration and GSSAPI support (GSSAPI is currently patched and enabled in the etch builds of openssh).
I think the GPG integration provides the best method theoretically for a number of reasons:
One final addition that would be good would be to do GPG verification the other way around: hosts verifying users. That is, provide sshd with its own keyring, and a clean, small set of trusted users (say, the admins on the machine), and then replace ~/.ssh/authorized_keys with ~/.ssh/authorized_gpg_uids. Then each admin wouldn't need to provide a password to the end user at all. Through their pre-existing communication, they would have verified and signed the GPG key of the user. That signature would be presented to the sshd who could use it to verify the uid and match it against a line in ~/.ssh/authorized_gpg_uids
If only i had the time to work on coaxing the patchset into compatibility with modern versions of GPG and OpenSSH, or re-implementing it myself...
[ Parent ]
[ Parent ]
If you're using a recent version of OpenSSH then it can be configured to check fingerprints against TXT records stored in DNS.Is it really TXT records? I've never set this up, but i'd like to, and the only relevant RFC i found seem to claim that this is a separate DNS type, SSHFP, not a TXT record.
Do you have a tool of choice for converting these records into tinydns custom format?
[ Parent ]
Sorry you're correct. It isn't TXT records, I was misremembering SPF.
Unfortunately I don't have a great link handy. I swear I bookmarked an online site for pasting in keys which would generate the magical entries - but I can't find it at the moment.
I'll followup once I stumble upon it again.
[ Parent ]
ssh-keygen -r $(hostname --fqdn) -f /etc/ssh/ssh_host_rsa_key.puband a generic RR just by adding the -g flag.
And I just found this, which relies on gawk, but it doesn't quite work for me. After playing with it a bit more, the following gawk script works OK:
#!/usr/bin/gawk -f # taken from: http://msgs.securepoint.com/cgi-bin/get/djbdns-0702/5.html # modified by Daniel Kahn Gillmor <dkg-debian.org@fifthhorseman.net> # example: ssh_host_key_to_sshfp $(hostname --fqdn) </etc/ssh/ssh_host_rsa_key.pub BEGIN { hostname=ARGV[1] keygen="ssh-keygen -gr " hostname " -f /dev/stdin" while(keygen | getline) { if($8) { rr=sprintf(":%s:44:\\%03.3o\\%03.3o", hostname, $6, $7) for(i=1; i<length($8); i+=2) { rr=sprintf("%s\\%03.3o", rr, strtonum("0x" substr($8, i, 2))) } print "# " $0 print rr ":::" } } }As the comment says, run this script like this:
ssh_host_key_to_sshfp $(hostname --fqdn) </etc/ssh/ssh_host_rsa_key.pub
[ Parent ]
./sshfp -s www.debian-administration.org www.debian-administration.org IN SSHFP 1 1 6fe7cfbc539c2488193dee45ce661126a33d01c www.debian-administration.org IN SSHFP 2 1 e58a8ccd12c06997ed1b68f8f1b0fedcf72375bDirectly usable in Bind if I am right. Cheers, Julien
[ Parent ]
[ Parent ]
[ Parent ]
[ Parent ]
[ Parent ]
[ Parent ]
[ Parent ]
[ Parent ]
[ View Weblogs ]
The? Shouldn't that be ssh localhost -o "VerifyHostKeyDNS ask"
[ Parent ]