In the last article, you learned that a cryptosystem is used to protect the privacy, integrity, and authenticity of data as it traverses a network. In today's article, we'll see how the SSH cryptosystem provides these features.
If you're using at least FreeBSD version 4.0, your FreeBSD system uses OpensSSH and it is installed and ready to go. As the name implies, this is an open source implementation of the SSH cryptosystem. You can read more about it at the OpenSSH website.
In a previous article (see IP Packets Revealed), I demonstrated that the telnet utility can be used to login to a remote computer from another system. Once logged in, a user can do anything on that remote system as if he were physically sitting in front of it. That is, every keystroke is sent to the remote system and interpreted as if it had come from the keyboard attached to that remote system (even though that keyboard input first had to travel over a network). We also saw in that article that every single keystroke and response was sent in clear text, meaning that a sniffer could watch the entire session.
Any SSH cryptosystem will allow a user to login to a remote system and work just as if he were physically there. However, before the user is given a login prompt, a key will be generated to encrypt and decrypt all of the data that will be passed between the two computers. That is, more is happening behind the scenes.
Since SSH is used to access another computer, a user account must exist on the computer to be accessed. Additionally, the computer being accessed is known as the SSH server and must be running the SSH daemon; by default, this daemon listens on TCP port 22. The machine you are sitting at is known as the SSH client; it will contact the daemon on the other machine.
Your FreeBSD system has default configurations that allow you to use SSH as is. I'll demonstrate the default configuration first, then move on to some changes you may wish to make to increase the security of SSH.
I'll be using two computers. 10.0.0.1 will be the SSH daemon, the computer
I wish to access, and 10.0.0.2 will be the SSH client, the computer I'm sitting
at. On both systems, I have created a user account called "genisis". You'll
note that the cryptosystem is called OpenSSH. It uses a protocol usually
written as uppercase SSH, and the commands you type,
sshd, are written in lowercase. Also, you can use the
ssh command to access either an IP address or a hostname. In
this week's article, I'll purposefully use IP addresses. In the next
article I'll take a closer look at name resolution issues when using SSH.
First, I need to check if the host keys have been created on the system that will be the server. At 10.0.0.1, I'll run this command:
If I get this output:
moduli ssh_host_dsa_key.pub ssh_host_rsa_key ssh_config ssh_host_key ssh_host_rsa_key.pub ssh_host_dsa_key ssh_host_key.pub sshd_config
I have the necessary keys. However, if I instead get this output:
moduli ssh_config sshd_config
there aren't any host keys and I will need to generate them before I can start the SSH daemon. If I'm impatient and try to start the SSH daemon before creating the keys, it will refuse to start and I'll instead receive this error message:
sshd Could not load host key: /etc/ssh/ssh_host_key Could not load host key: /etc/ssh/ssh_host_dsa_key Disabling protocol version 1. Could not load host key Disabling protocol version 2. Could not load host key sshd: no hostkeys available -- exiting.
There are several ways to generate those missing keys. If you are an
advanced user who is comfortable with reading startup scripts, search for
/etc/rc.network to see which commands your
FreeBSD system uses to generate the host keys. I'll instead demonstrate the
results of running that script. The easiest way to ensure the necessary keys
are generated and that SSH starts whenever the system reboots is to add the
following line to
Once I've saved my changes, I'll type:
When I get a prompt back, I'll press enter and then type the word exit. As my startup scripts are reinitialized, I see the following message:
Starting final network daemons: creating ssh1 RSA host key Generating public/private rsa1 key pair. Your identification has been saved in /etc/ssh/ssh_host_key. Your public key has been saved in /etc/ ssh/ssh_host_key.pub. The key fingerprint is: 12:d9:3d:f3:95:92:0e:e7:6b:54:09:80:77:a0:3e:cf root@hostname creating ssh2 RSA host key Generating public/private rsa key pair. Your identification has been saved in /etc/ssh/ssh_host_rsa_key. Your public key has been saved in /etc/ssh/ssh_host_rsa_key.pub. The key fingerprint is: 4b:cf:7e:af:f1:a8:01:08:64:1b:c0:79:e3:a2:58:78 root@hostname creating ssh2 DSA host key Generating public/private dsa key pair. Your identification has been saved in /etc/ssh/ssh_host_dsa_key. Your public key has been saved in /etc/ssh/ssh_host_dsa_key.pub. The key fingerprint is: 22:69:d7:05:23:c6:db:d9:55:2a:20:a3:34:bd:f4:ef root@hostname
Let's take a look at that output. You'll note that three separate key pairs were generated: one for rsa1, one for rsa, and one for dsa. You should recognize the RSA and DSA acronyms from the last article on cryptographic terms. But why so many key pairs? There are two versions of the SSH protocol, and OpenSSH supports them both. Not surprisingly, the rsa1 keypair is used by SSH version 1. You can see from the output that ssh2 (version 2) supports both RSA and DSA.
Each key in a key pair is stored in a separate file. You can identify the
public key files, as they have a
.pub extension. Additionally,
each public key has an associated fingerprint which is unique to that key.
We'll see that fingerprint again.
Not only were the necessary keys generated, the SSH daemon was also
started. This can be verified with the
sockstat |grep ssh root sshd 69820 3 tcp4 *:22 *:* root sshd 69820 3 tcp46 *:22 *:*
Okay, now that 10.0.0.1 is listening on port 22, let's see what happens
when I use the
ssh command from 10.0.0.2 as the user genisis:
ssh 10.0.0.1 The authenticity of host '10.0.0.1 (10.0.0.1)' can't be established. DSA key fingerprint is 22:69:d7:05:23:c6:db:d9:55:2a:20:a3:34:bd:f4:ef. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '10.0.0.1' (DSA) to the list of known hosts. Password:
Once I type the correct password for the user genisis, I'll receive my motd and customized prompt. I'll then type "exit" to leave the session:
exit logout Connection to 10.0.0.1 closed.
I'll now repeat a second time:
ssh 10.0.0.1 Password:
Let's pick apart what happened here. The very first time I used SSH, I was asked to verify the fingerprint of the server's DSA public key. Once I doublechecked that it was correct and typed yes, a copy of the server's public key was placed on the client or 10.0.0.2:
more ~genisis/.ssh/known_hosts 10.0.0.1 ssh-dss AAAAB3NzaC1kc3MAAACBAPiOFgV4PpsbXfkaxGD+hCr02Cv9P3OJDKfaXge059 cSohLN/n/kd2Nz/E1mDvT4Y8nSAQL7M667iMeqJ0WTpcdI59ktuPtvOsYBc7SNoJ6aPqqoKo682mAfC NpUFZ3jirbWGFnaF3WpJsWFyeOY6vyD4hVT6CkunL2ovoYSJND7AAAAFQDjZ2TNBixZByXB+h00wxCN tHZ8zQAAAIEAl4lePs+e5v9f1H93l2GLXtxXhXyasr+X42HnKgKQTMR+iLgxhtD0Eb/ftTMK+n2ECn9 3MwCNTgx5tdGX06dyBdK5xEfjV4tJnmnP42UweBwOHKpRkNLiMBN4onh7KKXjhXWmH0MpO5fhaHy6k0 f+yTTLckCKd2IO/TgGJitjlo4AAACBAM+3JMr8M+MQoa6D7BU0pNJVGoTmGdxrLotMNLmUdqM0xIFKr 3dBrgqY+gsDciQEG1CSqDDhusrkz3LRBmnuG68tE7WPPjzGZrT46ZYCmMeZume67xVN0dDd57BuxmhK B7iKvmlM0v+EkvJ0XTlNCwBTWuU3cdTdhkWT7swxGhvf
The next time I used SSH, the server's public key was compared to the copy of that key on the client; since they were the same, SSH knew I was connecting to the correct server so I wasn't asked to re-verify a fingerprint. Instead, I simply received the login prompt on the server.
Let's recap what happens behind the scenes:
OpenSSH supports other authentication methods, but this is what happens in the default configuration on your FreeBSD system. You may have noticed that the server sent its DSA public key, meaning that it was using SSH version 2. This is a good default, as version 2 is much more secure than version 1.
You may have also noticed that the user doesn't require a key pair in the
default configuration, only their password. Let's change that. First, I'll
have to generate a key pair for the user genisis by using the
ssh-keygen command at 10.0.0.2:
ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/home/genisis/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/genisis/.ssh/id_rsa. Your public key has been saved in /home/genisis/.ssh/id_rsa.pub. The key fingerprint is: fd:5a:cc:cf:a9:f0:ea:9c:93:ea:1a:04:48:b1:47:14 genisis@hostname
ssh-keygen, you need to use the
t switch to specify
which type of key pair to create. Since SSH version 2 is more secure than
version 1, and since RSA is more secure than DSA, I chose to create a SSH
version 2 RSA keypair. I was also prompted for a passphrase which will be used
in the future to prove that I am the owner of the key pair, or, more
importantly, the private key. A passphrase is similar to a password, but should
be longer yet memorable. Whenever I wish to use the private key, I will be
prompted for the passphrase. If I ever forget the passphrase, I will need to
generate a new key pair.
Remember that the public key in a key pair is meant to be public and it is up to you to ensure the private key is kept private. Let's take a look at the default permissions on those keys:
ls ~genisis/.ssh total 4 -rw------- 1 genisis genisis 951 Nov 9 15:00 id_rsa -rw-r--r-- 1 genisis genisis 247 Nov 9 15:00 id_rsa.pub
The private key,
id_rsa, is only accessible by the user
genisis. The public key,
id_rsa.pub, is readable by anyone. If I
file utility, I'll see that both files are ASCII text,
meaning they can be viewed with a pager:
file ~genisis/.ssh/* id_rsa: ASCII text id_rsa.pub: ASCII text more id_rsa.pub ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEA1gfc4NRnq9K17TLqhhKT3L6feKUttHTJvM054k+WhjI vsdt4YoeNa3m6lplnOxwOh2w6o+xu+xuiHa/CQkvkAdxFU1ZGtnxtQWV06QJdodUEk55U/0y417TaDF H1aYjsgPPSpjulKCLQv263C9KOSpjDrjZ74ZLOlQHtsJINY2c= genisis@hostname
Note that I only showed you my public key, not my private key.
Creating the key pair is not enough. I still need to copy my public key into my home directory on the SSH server. Once the server has a copy of my public key, whenever I use SSH it will ask for my public key so it can compare it to its copy. If they match, I will be authenticated.
I'll use the
scp or secure copy command to copy the key to the
server. This utility comes with OpenSSH and allows you to transfer files over
an encrypted session. Its syntax is similar to the regular old
command; the only difference is that the destination file starts with the IP
address of the machine you want to copy the file to, followed by a full colon,
followed by the name you want the file to have once it is copied over.
So, at 10.0.0.2, I'll issue this command to copy my public key to the server:
scp ~/.ssh/id_rsa.pub 10.0.0.1:~/.ssh/authorized_keys Password: id_rsa.pub: 100% |***************************| 247 00:00
Note that I was careful to copy over the public key, not
the private key; that is, I chose the file with the
.pub extension. I also had
to change the name of the destination file to
~/.ssh/authorized_keys. I was prompted for my password on the
destination system before the actual copy occurred.
Now that my public key is copied over, I'll try another SSH:
This time, I wasn't prompted for a password. Instead, since my public key was correct, I immediately received my shell prompt on the server machine. While it may seem less secure to not be prompted for anything, being authenticated by a public key is more secure than being authenticated by a password. However, the security of the system still depends upon you. Just like you don't give other users your password, don't give other users your private key or your passphrase. If you ever suspect that your private key has been compromised, generate a new key pair using a different passphrase and copy over the new public key to the SSH server.
ssh, you don't have to be logged in to the same account on the
client machine as you want to access on the server machine. For example, if I'm
currently logged in as biko but want to access genisis on the server
machine, I can use the
l switch or login switch at the client:
ssh -l genisis 10.0.0.1
I could also use this equivalent command:
Since there isn't a copy of genisis' public key in biko's home directory, I'll be prompted for a password. I need to input the password for genisis, not for biko. While it's a little bit harder to remember who I am on each system, it does mean that I don't have to create a user account called genisis on both machines.
Let's see what happens if I try to use SSH from the superuser account:
ssh 10.0.0.1 Password: Password: Password: email@example.com's password: Permission denied. Please try again. firstname.lastname@example.org's password: ^c
Even though I gave the correct password for the superuser account, access
was denied. This is a very good default. Just like you should never login
directly as root, you should never
ssh into another system from the root
account. If you need superuser access on the remote system,
ssh using a regular
user account which has permission to become the superuser once logged in to the
In order to change the other defaults, we'll have to take a close look at
the parameters in the SSH configuration files. Let's save that for next time.
In the meantime, you can get a sneak peek by reading the manpages for
sshd_config. You might also find the
ssh FAQ interesting.
Dru Lavigne is a network and systems administrator, IT instructor, author and international speaker. She has over a decade of experience administering and teaching Netware, Microsoft, Cisco, Checkpoint, SCO, Solaris, Linux, and BSD systems. A prolific author, she pens the popular FreeBSD Basics column for O'Reilly and is author of BSD Hacks and The Best of FreeBSD Basics.
Read more FreeBSD Basics columns.
Return to the BSD DevCenter.
Copyright © 2009 O'Reilly Media, Inc.