Find us on GitHub

Teaching basic lab skills
for research computing

The Unix Shell: Secure Shell

The Unix Shell/Secure Shell at YouTube

In modern operating systems, the command line allows the user a powerful way to accomplish a diverse set of tasks on the user's computer. In this episode, we'll see how remote logins can be used to connect to other computers and perform command line tasks on the other computers, all without distance being an issue.

First, let's start by looking at what happens when we use our desktop computer. When we type information to our computer (for example, a shell command), the text—the 1's and 0's that represent each character—is sent from the keyboard to the shell. The shell then displays characters on the screen to represent what we type.

If what we type represents a command, the shell will execute the command and additionally display characters representing the output.

When we login to our desktop computer, we type our username and password at the keyboard which sends it to the shell.

The shell passes the login information to the OS, and if the OS authenticates our login information, the shell will give us a command line prompt to interact with the OS. The shell will send the 1's and 0's to the screen to represent the characters that make up that prompt.

Let's say we want to login to another computer from our desktop. Let's call this a remote login, and the other computer is a remote computer. A remote login appears nearly the same to the user. However, the username and password information is being passed on to a shell on the remote computer's OS, so it has a longer distance to travel.

The shell on the remote computer interacts with its OS and responds back with output, and the output travels back to us. The interaction with the remote computer will be the same as if we had traveled that distance and were typing at the keyboard of the remote computer.

In order to invoke a remote login, all we need to know is the secure shell command 'ssh' and the simple syntax "ssh username@computer" and we get prompted for our username and password on the remote computer. Voila!

Wrong password?—no access. Just as we expect.

After we login to the remote computer, we can use the remote shell to use the remote computer's files and directories.

When we type "exit", we terminate the remote shell and return to our previous shell.

Suppose there is a file that we want to transfer from the remote computer to our computer.

Now that you know how to run secure shell, you can understand what secure copy might do. Secure copy allows you to copy files to or from a remote computer, and it takes advantage of the remote connection setup used by secure shell. The syntax is simple and is similar to that of "cp" and "ssh". To copy a file, we first specify the source location of the file that we are copying…

…followed by the destination directory to where we are copying the file.

When specifying the source and destination, we write the user name, at-sign, the name of the computer, colon, then the path of the file or directory

If either the source or destination is on a remote computer, then we have to type the password for the user accounts that are being used to make the connection. Secure copy may also give us feedback on the progress of our transfer.

Copying a folder is similar to using copy command "cp" in that the -r option indicates we are copying a directory and its contents

If either the source or destination is the current computer, we can omit the "user-at-sign-computer-colon" part.

Sometimes, we only want to login to a remote computer to find out (or create) a piece of information, and then return. If this is quick or repetitive, this can get tedious. For example, I need to know how much free disk space there is, and I need to collect this information every hour, and keep this information on my personal computer. I could login, run "df -h", save the output as a file, logout, and then "scp" the file from the remote computer to my computer.

But the ssh command allows us to pass data streams to a remote command and receive input streams from a remote command. When we provide the command that ssh needs to run remotely, any output that the command generates is sent back to our shell.The remote command is specified as an argument to the ssh command that follows the username and remote computer information.

Now we can save the remote command's output to a file. This simplifies the task considerably and still achieves the same result. We have the remote computer's disk usage statistics saved on our computer.

Remember that ssh can accept streams of data and pass those to the remote command, too. This command sends a stream of characters to a remote shell session.

As mentioned before, the remote shell will execute any command on the remote computer that was provided as an argument to ssh. The remote shell session also passes any input it receives to the provided command. In this example's remote command, 'cat' is a command that will receive the input and repeat it entirely as output, and then the rest of the remote command will redirect that output to a file.

The command has created a file on the remote computer in the user's home directory that contains the original stream of characters.

…And we can copy the file from the remote computer to our computer, if we like.

Why do we call the command used to login to a shell on a remote computer "secure shell"?

Until a few years ago, we used to create remote logins by passing our information straight through to the remote computer.

However, if a person could intercept our messages to the remote computer and were devious, that person could read our username and password and use them to impersonate us. Not secure, and we don't expect to be impersonated. What we needed was a way to do this without the risk of our passwords and information being stolen.

Imagine the information we send as messages that can be protected by locking them. One way to arrange a locking scheme is to have all users connecting to a remote computer use the same lock and key when sending their messages.

As we might imagine, this is not safe with many users.

If multiple users have copies of the same key, the potential for a single key to get stolen or fall into the hands of a thief is higher.

What we really needed, then, was a way to create a lock and key design with two keys, where the message can be locked by one key and only unlocked by the other key. Imagine the remote computer having a set of two keys, and handing out the first and keeping the second. The user locks all of his/her messages with the first key, but only the second key can open it, which only the remote computer has.

Anyone pretending to be the remote computer does not have the second key, and cannot break the lock. All subsequent messages from the user to that particular remote computer will be done with the remote computer's first key that the user received, and the remote computer continues to use the second key it kept to unlock the messages.

This key-lock mechanism is called public-key encryption, and public-key encryption is a standard feature of secure shell. In public-key encryption, the first key, which is sent out to the user, is the public key. It's okay to send this out to every user, since no one has the second key in the set, called the private key. The locking mechanism is an encryption algorithm, and the public key is used to encrypt our messages to the remote computer. Due to the way these encryption algorithms are designed, the remote computer can use its private key to decrypt the messages, but no other key will work. In order for the remote computer to send messages to us, the same process happens in reverse—we generate a public and private key pair, give the remote computer our public key, the remote computer encrypts messages to us using our public key, and we decrypt the remote computer's messages using our private key.

Anyone trying to pose as us will not have the remote computer's private key, and will not be able to understand our message encrypted with the remote computer's public key. This makes it safe to put our username and password, and any other sensitive information, in our messages. Similarly, in the reverse direction from the remote computer to our computer, anyone posing as us will not have our private key, and cannot decrypt the messages sent from the remote computer using our public key.

Also note: users who login to a remote computer for the first time need to first receive the remote computer's public key and agree to its authenticity. The public key is sometimes represented in a "fingerprint" format for easier verification purposes.

Let's return to the example of saving a log of free disk space every hour. We can imagine putting this inside a loop that repeats every hour.

But there's one thing that's still tedious—we have to type our password every single time, every single hour. And the remote computer will probably only wait for a short while for the password before assuming you're not there and giving up. We need to make this process fully automatic. The equivalent of this in the GUI world is the "save password" option, but our way will be more secure. What we want is a way to do silent authentication—we want the remote computer to recognize our username and password in some form without having to type our password interactively.

In order to silently authenticate into a remote computer, we need to take advantage of ssh allowing user keys. User keys are user-specific, user-generated public-private keys. Each user has his/her own user key pair, and it is separate from the host key pair belonging to the user's computer. The host key pair is shared by all users of the computer, and it is used by default when the user key pair is not used. The user keys allow us to "embed" our password into our user key pair when generating them, making it much harder to fake than the host key pair we use by default, and thus more secure.

We use ssh-keygen to generate the user key pair. We then have to manually send our user public key to all the remote computers that we want to use it. If we don't send our user public key to a remote computer, then when we login to that computer, by default, we will have to use our host public-private key pair for encryption, and we also have to authenticate with our username and password on the remote computer.

When using ssh to log into a remote computer that has our user public key, we type in our password so that it matches the password we embedded in our user key pair.

The trick to silent logins is to generate a new user key pair and provide an empty password as the key pair password, when prompted, by pressing Enter. We copy this particular public key to every remote computer for which we want silent login.

Here are 3 different ways to copy the user public key to the remote computer so that it can be found

We can now start writing scripts that run commands, send input to remote computers, or receive output from remote computers in a secure way. All of this can happen silently without us typing our password.

Thank you for listening.