Doing It All with OpenSSH, Part 2

by Marcel Gagné

Welcome back to the Sysadmin's Corner and the continuing saga of secure communications, SSH-style. Logging in to an SSH server is easy enough and provides you with secure communications, while still opening you up to the whole world. You could set up a firewall that allows in certain IP addresses only to port 22, but that presents another problem. If you are on the road and you need access to your own system, you might be connecting from an untrusted system with a dynamic IP. A nice iptables rule isn't going to help here, unless you've got somebody permanently standing by who can answer your phone call and enter the commands for you--somebody with root access, no less. No matter how you look at it, it can get messy.

Another option is to leave port 22 wide open and set your server to allow only public key authentication. This option requires a little more work than merely running sshd and forgetting about it. But as an added bonus, you can securely log in without a password. Did he just say "without a password"? Yes, he did, and you can do so securely. In fact, public key authentication can be safer than the classic password system because knowing the password isn't enough.

Here's how it works. Using a key generation program, you create a key pair consisting of a public key, which is copied to the server, and a private key, which you keep on your PC and guard with your life. No authentication can take place without both keys.

To generate your own public key, use the ssh-keygen command, specifying the encryption type. In the following example, I used RSA encryption, the one most people should use. Other encryption types include rsa and dsa. There's also an rsa1 for the old protocol 1 ssh, but odds are that you won't need this--at least not for now.

If you type ssh-keygen -t rsa, the output of the command looks like this:

                 Generating public/private rsa key pair.
                 Enter file in which to save the key (/home/mgagne/.ssh/id_rsa):
                 Enter passphrase (empty for no passphrase):
                 Enter same passphrase again:
                 Your identification has been saved in /home/mgagne/.ssh/id_rsa.
                 Your public key has been saved in /home/mgagne/.ssh/
                 The key fingerprint is:
                 0b:76:f2:a3:54:20:86:74:fe:9d:64:56:c4:85:a9:7f mgagne@ultraman

You can pretty much accept the question regarding the location for storing the key. Pay attention, however, to the second question, the demand for a passphrase. If you wanted to, you could enter nothing here, upload your key to the server and have no passwords whatsoever when you connect. After all, it sounds like you simply are exchanging one password for another. There is a catch, however, with this idea. If someone was to get a copy of your private key, that person would have no trouble getting into all your other systems. Given that danger, you definitely want to protect yourself with a passphrase--so what have you gained?

Well, as it turns out, there is a way around this roadblock, and I'll tell you about it shortly. But first, I would like to tell you what you do with your public key. The ssh-keygen command creates a file named for your public key, and you need to get its contents to the remote system. That key is a text file, and its contents look something like what is shown below. Although the contents below span a few lines, in reality, this is one unbroken line of text.

                 WhWaPd+YE1fmqzU2nBRxQ1Ud2xqjFCcwdSWesE= mgagne@ultraman

Your next step it to connect to the remote server where the sshd process is running. You might want to open another window to do this, because we'll be doing a little copying and pasting. That should put you in the user's home directory. From there, cd to the .ssh directory in the home directory and look for a file called authorized_keys. If it isn't there, create it. Now, copy and paste the key into the authorized_keys file, keeping in mind the key must be copied exactly. You also could transfer it to the remote system and append it to the authorized_keys file, like this:

                 cat >> $HOME/.ssh/authorized_keys

A word of caution before we continue: the permissions on this file cannot be group or world writable or this procedure will not work. You have to do a chmod 644 authorized_keys to make sure the file can be written only by the owner.

When you next connect to the remote system with ssh -l user_name remote_sys, you'll connect without being asked for a password. As I mentioned, however, creating your public/private key pair without a password probably is a bad idea. If someone gets his or her hands on your keys, all is lost; any security you might have gained by running with the secure shell is pretty much gone. Your only option is to use a passphrase when you generate your key-pair with ssh-keygen, but then you are back to using a password--the thing I promised you freedom from at the beginning of the article. Is there no way out?

This conundrum is exactly where a fine little program called ssh-agent comes to the rescue. If you already have created your passphrase-free key-pair, start again and provide a passphrase this time. Move the public key over to your server (remember to get rid of the old pubkey from the .ssh/auhorized_keys file), and test your connection. You should be asked for your passphrase, but not the user's password. So far, so good?

Before you start ssh-agent, you may want to look for its process because your window manager may start it for you. For instance, on my Mandrake 9.1 system, this little bit of code exists in the system wide /etc/X11/Xsession file.

                  AGENT=$(type -p ssh-agent)
                  if [ -x "$AGENT" -a -z "$SSH_AUTH_SOCK" ]; then
                      if [ -r $HOME/.ssh/identity -o -r $HOME/.ssh2/identificati
                           SSH_AGENT="$AGENT --"

In fact, if I do a ps ax | grep ssh-agent on my notebook, I see the following:

                3209 ?        S      0:00 ssh-agent
                3475 ?        S      0:00 /usr//bin/ssh-agent -- /bin/sh -c #!/b

So, ssh-agent clearly is running, and yet I still am asked for a passphrase when I connect to my remote system. Obviously, simply having ssh-agent running isn't enough. That's because while ssh-agent might be running, it doesn't know your passphrase yet. You enlighten the process with the ssh-add command.

                 $ ssh-add
                 Enter passphrase for /home/mgagne/.ssh/id_rsa:
                 Identity added: /home/mgagne/.ssh/id_rsa (/home/mgagne/.ssh/id_

As you can see, I'm asked for a passphrase for my private key. After I've entered it, I then am able to connect to the remote system without a passphrase--simple and secure. Luckily, ssh-agent doesn't remember the information after you logout. Otherwise, once a passphrase was entered with ssh-add, the security of a protected passphrase would be pointless if somebody broke into your system.

You can use ssh-agent even if you aren't running an X window graphical environment, by the way. Let's pretend you are logged in to a text-only session. From the command line, you could type ssh-agent /bin/bash, at which point you then would have a bash shell wrapped by ssh-agent. From there, you can execute the ssh-add command, enter your passphrase and work with your various systems accordingly.

We've come full circle now. Everything works as it should, and you are ready to switch your sshd server over to an authentication that doesn't allow passwords at all. That way you can leave the port 22 connection open to the world, knowing that only fully authenticated public key clients can connect to your system. Here's what you do. Open the /etc/ssh/sshd_config file and look for the following line:

                 # PasswordAuthentication yes

The line is likely to be commented out because allowing password authentication is the the default. Uncomment the line, and change the yes to no. Then, restart your sshd server daemon. If you are feeling a bit worried about locking yourself out, you could leave the current process running and start a second server on another port, such as 2222, as I covered in my previous column.

                 /usr/sbin/sshd -p 2222

Now, if you try to log in to the server on port 2222 without the appropriate public key on the server, you won't get any further.

                 $ ssh -p 2222 -l marcel remotesys
                 Permission denied (publickey,keyboard-interactive).

Well, I think I've definitely used up my quota of words for today. Next time around, I'll tell you how to do this with your (gasp!) Windows PCs. I also will talk about remote program execution, secure transfers and many other exciting things. Until next time, I hope you are feeling a little bit more secure.

Marcel Gagné is Linux Journal's Chef Français and a Linux true believer. His new book Moving to Linux: Kiss the Blue Screen of Death Goodbye! will be out in August 2003. You can find out more from his web site at

Load Disqus comments

Firstwave Cloud