Chapter 16 ■ telnet and SSh
305
So, SSH has the idea that each server, when installed, creates its own random public-private key pair that is not
signed by anybody. Instead, one of two approaches is taken to key distribution.
• A system administrator writes a script that gathers up all the host public keys in an
organization, creates an ssh_known_hosts listing them all, and places this file in the
/etc/sshd directory on every system in the organization. They might also make it available
to any desktop clients, like the PuTTY command under Windows. Now every SSH client will
know about every SSH host key before they even connect for the first time.
• Alternatively, the administrator can simply abandon the idea of knowing host keys ahead of
time and instead have each SSH client memorize them at the moment of first connection.
Users of the SSH command line will be familiar with this: the client says it does not recognize
the host to which you are connecting, you reflexively answer “yes,” and its key gets stored in
your ~/.ssh/known_hosts file. You actually have no guarantee on this first encounter that you
are really talking to the host you think it is. Nevertheless, at least you will be guaranteed
that every subsequent connection you ever make to that machine is going to the right place
and not to other servers that someone is swapping into place at the same IP address
(unless, of course, someone has stolen that host’s keys).
The familiar prompt from the SSH command line when it sees an unfamiliar host looks like this:
$ ssh asaph.rhodesmill.org
The authenticity of host 'asaph.rhodesmill.org (74.207.234.78)' can't be established.
RSA key fingerprint is 85:8f:32:4e:ac:1f:e9:bc:35:58:c1:d4:25:e3:c7:8c.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'asaph.rhodesmill.org,74.207.234.78' (RSA) to the list of known hosts.
That yes answer buried deep on the next-to-last full line is the answer that I typed giving SSH the go-ahead to
make the connection and remember the key for next time. If SSH ever connects to a host and sees a different key, its
reaction is quite severe.
$ ssh asaph.rhodesmill.org
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
This message will be familiar to anyone who has ever had to rebuild a server from scratch and forgets to save its
old SSH keys. Without them, the newly rebuilt host will now use new keys generated by the reinstall. It can be painful
to go around to all of your SSH clients and remove the offending old key so that they will quietly learn the new one
upon reconnection.
The paramiko library has full support for all of the normal SSH tactics surrounding host keys. However, its default
behavior is rather spare. It loads no host key files by default, and it must therefore raise an exception for the first host
to which you connect because it will not be able to verify its key.
import paramiko
client = paramiko.SSHClient()
client.connect('example.com', username='test')
Traceback (most recent call last):
...
paramiko.ssh_exception.SSHException: Server 'example.com' not found in known_hosts