Lab: Secure Shell Keys
Steven J Zeil
This is a self-assessment activity to give you practice in working with the git
version control system. Feel free to share your problems, experiences, and choices in the Forum.
1 ssh Isn’t Just for Terminal Sessions
You should already be familiar with ssh
even if you are used to invoking it through PuTTY.
In this lab, you will be working with ssh from a command line. You will be working with
-
a server machine, which will be one of the CS Dept Linux servers. I will assume in the rest of this document that you are using
atria.cs.odu.edu
as your server. -
a client machine, at which you can issue
ssh
commands. This will need to be a different machine from the server.-
Ideally, use a PC of your own.
- If your PC runs Linux or OS/X, you should be fine.
- If your PC runs runs Windows 10, good options are Bash on Windows. or the OpenSSH command-line tool in Powershell. (You may need to make some changes to the paths referenced in these commands if you are working in Powershell.)
-
Other good options for Windows 10 or for older versions of Windows are CygWin or setting up a Linux virtual machine.
-
You can use two different CS Linux servers as your client and server (e.g.,
atria.cs.odu.edu
andsirius.cs.odu.edu
) but it’s not ideal. Some mistakes that you might make will be disguised by the fact that you are already logged in to the network via the client machine, so it will be hard to tell if your commands are working because you did the lab correctly or because you are already logged in.
-
Let’s start with just the basics of using ssh
from the command line.
-
Try opening a remote session on your server machine by issuing the following command on your client machine:
ssh -l
yourCSLoginNameatria.cs.odu.edu
- You can omit the “
-l
yourCSLoginName” if your current terminal session is under a user name identical to your CS Dept login name. You can also combine it with the machine name, separated by an “@”:ssh
yourCSLoginName@atria.cs.odu.edu
This opens up what should be a familiar text-mode command session on the remote machine. Issue a few commands to verify that everything is familiar, and then log out of the remote machine.
- You can omit the “
-
Now give the same command, but append a command string to the end:
ssh -l
yourCSLoginNameatria.cs.odu.edu ls -l
ssh
is useful for issuing all sorts of commands to a remote machine. The “default” is to issue the command to open a login shell, but you can issue any command you want.
ssh
has other tricks to offer as well.
-
ssh
servers also, by default, provide file copying services viascp
andsftp
.. -
The
ssh
protocol can act as a “tunnel” for other common network protocols (e.g., email). This includes protocols that normally are limited to local network connections or that, for other reasons, have trouble getting through firewalls and routers. For example, all of the techniques covered in CS252 for connecting via X Windows have actually relied upon anssh
tunnel to carry the X or NX protocol messages between the two machines.
We’ll be making heavy use of both of these features of ssh
in the coming semester. However, these will call for a more sophisticated approach to identifying ourselves than explicitly typing in our login names and passwords for every connection to a network service.
2 Replacing Passwords with ssh Keys
ssh keys provide a way of identifying yourself that is generally more secure than simple passwords. Based on one-way cryptography, an ssh key has two parts: a public key and a private key. You can distribute the public key to a variety of server systems that you like to log in to. You keep the private key on client machines that you log in from. Often these client machines are ones you have a certain amount of physical control over — a home computer or a laptop that you own. That physical security is coupled with a lengthy passphrase needed to activate the private key. Once activated, the private key can be kept active through a work session, allowing you to repeatedly log in to clients that have your public key.
It’s important to keep this straight: * The public key goes onto the remote server that you are connecting to. * The private key stays on your (local) client that you are connecting from.
2.1 Generate a Key Pair
The ssh-keygen
program is most commonly used to generate public/private key pairs.
-
Most Linux systems will have this already installed.
-
On a Windows CygWin system, you can get it as part of the
openssh
package.-
Another possibility is Pageant, part of the PuTTY ssh suite for Windows.
-
Also, you can generate keys from within Eclipse (
Window
$\Rightarrow$Preferences
$\Rightarrow$General
$\Rightarrow$Network Connections
$\Rightarrow$SSH2
$\Rightarrow$Key Management
, but the key length is limited to 1024 bits, which is considered a bit low these days.
-
-
To generate a key pair, give the commands:
mkdir ~/.ssh # if you don't already have this directory chmod 700 ~/.ssh ssh-keygen -b 2048 -t rsa
You can do this step on your client machine or on the remote Linux server.
You can change the name of the generated files if you like. (I keep different key pairs for different client machines and name them accordingly, e.g., “officePC”, “homePC”, etc.). Do keep it in your
~/.ssh
directory, however.You will be prompted for a passphrase. This is used to protect your private key in case someone gains access to the machine/account where you have it stored. Do choose one. Even though the command prompt says it’s optional, you don’t want to have an unprotected private key around. Most people use much longer passphrases than a typical password, but generally place less emphasis on odd character substitutions that make the phrase harder to type.
-
Now look in your
~/.ssh
directory. You should see your new keys. One file has the extension “.pub”. that’s the public part of the key. -
You can do a quick test of your key pair by giving the command
ssh-keygen -y -f path/to/your/private-key
This command will prompt you for your passphrase and, if you are successful in providing it, will then print the corresponding public key.
Compare the output of that to
cat path/to/your/public-key
They should match except for the little “
usr@machine
” comment at the end indicating the machine on which you created the key.Remember, the idea is that you want the public key to be on the remote server and the private key on your local client.
Since you have just created both keys on one machine, one of them is currently out of place.
-
If you created your key pair on your client machine, transfer the public key into your
~/.ssh
directory on the remote server. (If you don’t have a~/.ssh
directory there, create one. Give is the same permissions as shown in step 1, above.)If, on the other hand, you created your key pair on the remote server, transfer the private key to a convenient directory on your local client, and delete the original private key from the remote server.
2.2 Try It Out
At this point, you should have
- A copy of the private key on the local client.
- A copy of the public key on the remote server.
But just having the public key on the remote server isn’t enough. We have to authorize that key before it will do anything for us.
-
Let’s authorize this key as one that you can use to log in to your CS Linux account.
On Linux servers, you do this by adding the public key to
~/.ssh/authorized_keys
.authorized_keys
is simply a text file that contains a list of public keys.There’s at least three ways to do this.
-
You can simply attach it to the end of the
authorized_keys
file:cd ~/.ssh touch authorized_keys cp -a authorized_keys authorized_keys.bak cat path/to/your/publicKeyFile >> authorized_keys
This works the first time you install a key. But if you need to replace or modify a key, it’s not as useful, because you would wind up with multiple copies of the same key in your
authorized_keys
file, leading to unpredictable results. -
Alternatively, log in to the server, open
~/.ssh/authorized_keys
in your favorite text editor and add the public key to the end. (This is also how you can clean up this file later if you want to remove a key, either because the key doesn’t work properly or to clean up after this assignment is done and graded.)-
If you are replacing a key, be sure to delete the old entry for that key. If you have entries in there for keys you aren’t using, remove those as well.
-
-
You might read on the Internet about a command
ssh-copy-id
that combines the file transfer of a public key from a client and the authorization into a single step.Since we are going to be modifying the authorized keys shortly, however, I don’t recommend this. People who rely on this command often wind up with messy
authorized_keys
files that are hard to work with.
-
-
Now, back on your client machine, try connecting to the server:
ssh -i path/to/your/PrivateKey -o "IdentitiesOnly=yes" yourCSLogin@atria.cs.odu.edu
You should be prompted for the passphrase for your new key.
Troubleshooting
If you run into problems with the final step or with the ones that follow, …
Review your steps. Make sure that you have the correct files on the correct machines.
Remember, the public key goes on the remote server inside the
authorized_keys
file.The private key goes on your local client machine.
That means that when you are giving a path to your private key in an
ssh
command, it must be a path on your local machine.Check your permissions on the server very carefully. You should have the equivalent of:
chmod 711 ~ chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys
You may also need to check the permissions on your private key on your local client. Some versions of
ssh
will refuse to use a private key that is readable by anyone other than you (the owner of the file).In particular, if you get a message complaining that your private key permissions are too open, change the permissions on that key!
chmod 600 path-to-your-private-key
- If you are using Bash/Ubuntu on Windows, you may find that
chmod
commands like the one above are ignored. (Do an “ls -l
…” to check.)You may be able to make
chmod
work by using an editor:sudo nano /etc/wsl.conf
and adding the lines
[automount] options="metadata"
Then close all open bash instances, restart bash, and see if your
chmod
commands now work.
2.3 Key Agents
Wait, did we just make your life harder?
Now, you may wonder what good that was. Every time you try to log in to a CS Linux machine, you will be prompted for that passphrase, which is probably much longer than your old password.
But usually, we don’t activate the private key for a one-shot login. Instead, we run a key agent on our client machine. We tell it to activate our private key (giving it the passphrase to prove that we are its owner). It then watches for subsequent ssh
connection attempts and offers up the activated private key.
-
On your client machine:
eval `ssh-agent` ssh-add ~/.ssh/yourPrivateKeyFilename
This launches a new key agent and tells it to watch for incoming requests to validate that private key.
-
Then try giving the following commands from your client
ssh yourCSLogin@atria.cs.odu.edu date ssh yourCSLogin@atria.cs.odu.edu pwd ssh yourCSLogin@atria.cs.odu.edu ls ssh -A yourCSLogin@atria.cs.odu.edu
All of these should work with your being prompted at most once for your passphrase. The last one leaves you logged in to
atria
. From that session onatria
, try logging in to sirius:ssh sirius.cs.odu.edu
Again, you should find that you are able to do this without being prompted for your password or passphrase. The
-A
option in the earlierssh
command caused your agent’s credentials to be forwarded into your session onatria
.
If you like this, you should look into the package keychain
, which is a way to set up agents and activate your keys upon logging in to your client. If you don’t care for it, restore your authorized_keys
file in your CS account to its previous state (the .bak
file). But keep those keys. We’ll use them later.
2.4 Creating Special-Purpose Key Pairs
Suppose that you wanted to allow someone else to try out a program that you had written and that is sitting somewhere in your account area. Let’s also suppose that you don’t want to make this program available to the entire world. For example, perhaps you are working on a programming assignment in one of my courses and you want me to take a look at your running program.
-
You could, of course, tell me your login name and password, but that would be a bad idea unless you really, really trust me. (And why should you?)
-
Based on what we have just seen, you could create an ssh key pair, add the public key to your
authorized_keys
file, give me the private key and its passphrase. Then, after I had tried your program out, you could simply remove that key from~/.ssh/authorized_keys
to lock me back out.But that’s still way too trusting of you. During the time I had access to your program, I would have access to everything in your account. I would, even using the ssh keys, be logged in as you.
But we can actually adapt that second approach by limiting the key pair to running only a specific command or program when anyone uses it to log in.
-
On the remote server, edit the public key that you created in the earlier steps.
The key is typically written as a single long line ending in _yourLoginName@machineName_, reflecting where you created the key. To the front of that line, add
command="/usr/bin/env",no-port-forwarding
and a blank space, right in front of the “
ssh-rsa
”.(If you aren’t familiar with the
env
command in Linux, run it to see what it does.) -
Add that edited public key to your authorized keys list on the server as you did earlier. (Remove the old copy of that key.)
-
You should still have a key agent running on your client. If not, restart it and add your private key.
Now try logging in via that key by giving the following commands on the client:
ssh yourCSLogin@atria.cs.odu.edu ssh yourCSLogin@atria.cs.odu.edu pwd
Notice that, whether you give a specific command for
ssh
to execute on the remote server or omit it, trying for a normal login session, what actually happens is that you are logged in to your account, theenv
command is run, and then you are logged out.
So, to return to our earlier example, if you were working on a programming assignment in one of my courses and you want me to take a look at your running program, you could create a special-purpose key pair to run that program (and do nothing else), and then give me the private key and passphrase, knowing that I would be limited to using your account for that single purpose.
2.5 Playing with Fire: Password-Free Key Pairs
Now we are going to do something a bit dangerous.
-
Shut down the key agent on your client machine with the command
ssh-agent -k
-
Create a new key pair, giving them a different name from the ones you set up earlier.
This time, however, when prompted for a pass phrase, just hit Enter to create a key pair without a pass phrase.
-
Test your keys via the commands
ssh-keygen -y -fpath/to/your/privateKey cat path/to/your/publicKey
Again, the printed public keys should match except for the trailing comment. This time, however, you should not be prompted for a passphrase.
-
If you created these keys on the remote server, transfer the private key to your local client machine and delete the original.
If you created these keys on your local client, transfer the public key to your
~/.ssh/
directory on the remote server. -
Now, adding that key to your authorized key list would be risky, because anyone who got a copy of the private key would be able to log into your account using no passphrase at all.
So, to keep this safe, immediately edit that public key. This time add
command="pwd",no-port-forwarding,no-agent-forwarding
to the beginning of the public key.
-
Add that edited public key to your authorized key list on the server.
-
On the client, give the command
ssh
-i
path/To/Your/New/Private/Key yourCSLoginName@atria.cs.odu.edu
You should see that the command is executed without your being prompted for a password or pass phrase.
If you are still prompted for a password, there may be remnants of your ssh-agent interfering. Try
ssh
-o IdentitiesOnly=yes -F /dev/null -i
path/To/Your/New/Private/Key yourCSLoginName@atria.cs.odu.edu
When you have succeeded in completing these steps, remove the keys you have added to your ~/.ssh/authorized_keys
file on the server.