Unix: The shell

by Gisle Hannemyr

This chapter introduces the Unix shell. Beside the various standard shells, it also introduces the secure shell and privilege elevation using sudo, and how to capture a CLI session with script.

Table of contents

Introduction

The UNIX shell is a command line interpreter (CLI). It interprets the commands the user types in and arranges for them to be carried out.

The user types in commands consisting of a single line of text, ending with pressing the [Enter] key. (Sometimes referred to as the [Return] key by those that grew up using typewriters.) When the user press the [Enter] key, the entire command line is sent to the shell and interpreted.

After receiving the command, the shell may execute it itself, or call upon the kernel and/or some other program to execute the command. When execution has completed, the shell displays the default prompt again to tell the user it is ready to accept a new command.

tipThe default prompt is a dollar sign ($) if your shell is the classic Bourne shell sh, the Bourne Again Shell bash or the Korn shell ksh. The default prompt is a percentage sign (%) if your shell is the C shell csh or tcsh. In the examples in this ebook, a dollar sign will be placed in front of each shell command. Do not type the dollar sign when you try out the examples, it only there to indicate that you should try out the example out from the command line. When a user is running with superuser privileges, it is customary to remind the user of that power by having an alternate prompt. This alternative prompt is usually the hash sign (#).

It is possible for users to toggle between different shells on the same machine. As is evident from the previous paragraph, several different shells exist. However, one of the best and easiest to come to grips with (in this author's opinion) is the Bourne Again Shell (bash). In this ebook, bash will be used in all the examples.

If you're already using a Unix or Gnu/Linux system, you get access to the shell by means of the terminal, as discussed in the previous section.

Note that working with a command line interpreter is different from working in a GUI. In a GUI, there is no “prompt” and you initiate commands by clicking with the mouse or stroking a multi-touch screen. A GUI is always ready to accept another command, while a command line interpreter by default becomes unavailable when a task is carried out. To be fair, there are several ways around this, as will be shown later.

Remote login: ssh

An essential tool for logging in and working on a remote computer over the Internet is the secure shell (ssh).

The ssh is actually a lot more than a remote terminal. It has built-in encryption, so that everything you send and receive during a session is encrypted. It also supports various authentication facilities, secure file transfer, X session forwarding, and port forwarding.

To log in on a remote host, you type the command ssh username@hostname in your local shell, where “username” is your user name on the remote host, and hostname is the DNS-address of the remote host.

Key-based authentication

To use SSH key pairs for passwordless remote login (strongly recommended), you need to add a public SSH-key to the remote server, and have a matching private key on the local server.

To add a key for yourself, first make sure you have a valid key pair.

If you do not have a key pair, you first must generate one. See below for a description of how to do this on various platforms. After generating the pair, you may need to create a directory named “.ssh” in your home directory, and place your private (“id_rsa”) and public “id_rsa.pub”) key pair there. However, this may already be done for you by the key generator.

If you already have the keys you need, skip ahead to Installing the public key.

Generating keys: Ubuntu and RHEL7/8

Both these platforms use ssh-keygen from the OpenSSH package to generate a private/public key pair for key-based authentication.

If you set a passphrase, this will be requested every time you try to login using key-based authentication. If the private key is on a secure computer, I think it is safe to leave the passphrase empty. The pair of key files will be saved in a subdirectory named .ssh in your home directory.

$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save key (/home/username/.ssh/id_rsa):
Created directory '/home/username/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again: 
Your identification has been saved in /home/username/.ssh/id_rsa.
Your public key has been saved in /home/username/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:FF6vRvatZy/+/Hh1q1DlUej3ni8nZvbhHYWJqw/QQUI username@example.com
The key's randomart image is:
+---[RSA 2048]----+
|       .E o    ..|
|       . = .  . .|
|        o + .. o |
|       . + + o+oo|
|        S + o.+oo|
|         o  .o  =|
|          ..o o+=|
|           o.oO*B|
|          ...*+X@|
+----[SHA256]-----+
$

tipThe randomart is meant to be an easier way for humans to validate keys. Instead of comparing the key's hexadecimal fingerprint, look at the randomart. To see the randomart of an existing private key, use:
$ ssh-keygen -lv -f ~/.ssh/id_rsa.

If this is not working after copying the files, and the target server is running SELinux, you may need to change the “the security context” to grant access to the key:

For background, see this page on DigitalOcean.

$  cd ~/.ssh
$  sudo chcon -t ssh_home_t . authorized_keys

Amazon EC2

The Amazon EC2 cloud service generates a .pem file that contain the required keys. This file is generated when you set up an account with Amazon Web Services, and you need to save it and use it for logging in on your server instances. This method of authentication makes the password redundant.

As soon as you've downloaded an identity file, make sure it is not readable by others. If the file is named mykey.pem, you do this with the the chmod command like this:

$ chmod 600 mykey.pem

(The exact meaning of the above command will be explained in the chapter about access rights.)

Here is an example of me using ssh to connect to an Amazon EC2 server instance, using the identity file mykey.pem to authenticate.

$ ssh -i mykey.pem ec2-user@ec2-107-22-130-254.compute-1.amazonaws.com
Last login: Mon Jan 28 05:38:37 2013 from diamant.ifi.uio.no

       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2012.09-release-notes/
[ec2-user@domU-12-31-39-07-5C-FE ~]$

The configuration for ssh is kept in a directory named .ssh in your home directory.

PuTTY

[TBA]

Installing the public key

If you only need one identity, you only need one key pair. You can reuse this pair across all computers you need to access remotely. To reuse an existing key pair, use the following command to copy your public key from the machine where you generated the pair to the user named username on the remote machine with the host named hostname:

$ ssh-copy-id username@hostname

This will result in your single line public key will be placed in a file named “authorized_keys” on the remote machine. Have a matching private key (typically named “id_rsa”) in the .ssh directory on the local machine. The presence of the private key is required for passwordless login from the machine.

If you get an error saying “No identies found”, the public key is missing from your .ssh directory.

See alsoFor background, see the DigitalOcean guidelines for installing a key pair. To use more than one different private keys to connect to different servers, see this question @ Ask Ubuntu. To use two different private keys towards the same server, see this article @ Medium.com.

To add another users public key to .ssh/authorized_keys in that users home directory, do as follows (assuming the user's username is "bob":

First, make sure there is a directory named .ssh in the users home directory, owned by that user:

cd /home/bob
sudo mkdir .ssh
sudo chown bob.bob .ssh

You will typically have received the public key as a plain text file an email atatcmenet from the user. It should be a very long single line looking like this (but much longer):

ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEApoYJFnGDNCT60BVHLv8jo…bXZB9lQ== rsa-key-2016081

If the public key comes in a multiline text file like this:

---- BEGIN SSH2 PUBLIC KEY ----
Comment: "rsa-key-20160816"
AAAAB3NzaC1yc2EAAAABJQAAAQEApoYJFnGDNis/2oCT6/h9Lzz2y0BVHLv8joXM
s4SYcYUVwBxNzqJsDWbikBn/h32AC36qAW24Bft+suGMtJGS3oSX53qR7ozsXs/D
lCO5FzRxi4JodStiYaz/pPK24WFOb4sLXr758tz2u+ZP2lfDfzn9nLxregZvO9m+
zpToLCWlXrzjZxDesJOcfh/eszU9KUKXfXn6Jsey7ej8TYqB2DgYCfv8jGm+oLVe
UOLEl7fxzjgcDdiLaXbqq7dFoOsHUABBV6kaXyE9LmkbXZB9lQ==
---- END SSH2 PUBLIC KEY ----

… it was not generated by ssh-keygen. To convert a multiline file named ssh2.pub to a single line file named openssh.pub, use:

$ ssh-keygen -i -f ssh2.pub > openssh.pub

Source serverfault.com: Adding an ssh key from putty to authorized_keys.

When the file is on a single line, append it to .ssh/authorized_keys in the user's home directory.

Troubleshooting ssh

If the server has been set up to use key-based authentication, and the key is missing or wrong, you will get this:

$ ssh root@hostname
Permission denied (publickey)

To restore password-based authentication, do as follows.

Logon as root using the local or web-based console and edit /etc/ssh/sshd_config (make sure you have the right file) by changing the value next to PasswordAuthentication from “no” to “yes”. It should now look like this:

# Change to no to disable tunnelled clear text passwords
PasswordAuthentication yes

Save the file and then run the following command to reload the SSH config:

$ sudo service sshd reload

The sudo and su commands

The sudo command allows a user to run programs with the security privileges of another user (by default, the Unix superuser). It prompts the user for his or her personal password and confirms the request to execute a command by checking a file that is configured by the system administrator configures. System administrators can give certain users or groups access to some or all commands without those users having to know the root password. It also logs all commands and arguments so there is a record of who used it for what, and when.

Provided your account has been given sudo privileges, the command below will perform the command given as argument with the same privileges as the Unix superuser (root):

$ sudo command
[sudo] password for username:
…

Replace command with the actual command to execute. In the prompt, username will be your username.

The sudo command also makes it easier to practice the principle of least privilege (PoLP), by not giving administrative rights by default, but allowing some of them to have such privileges to perform specific tasks.

tipPoLP means that user privileges should by default be the least required to do what the user needs to do. It can also be applied to processes on the computer: Each component or process should have the least privileges necessary to perform its duties. This helps reduce the “attack surface” of the computer by eliminating unnecessary privileges that can result in network exploits and computer compromises. The most important result of this principle is that users are not given administrative rights by default.

The command below will spawn an interactive shell where you will have the same privileges as the Unix superuser (root).

$ sudo -i bash
[sudo] password for myuser:
#

This is pratical if you need to perform a sequence of operations requiring superuser privileges.

The su command allows a user to become another user. The following sequence of command demostrate of it may be used:

$ su
password:
# chmod a+w *
# exit
$ su username
password:
# Ctrl+d
$

The first example of the su command defaults to becomming the superuser (root). In the second example, replace username with the username of the user which you would like to run the commands as. In both cases, when promoted for a password, use the superuser password. If the command succeeds, the user will be logged in as the other user until he or she type Ctrl+d or type exit at the command prompt.

noteAllowing the users to use su command creates security hazards, and requires more administrative maintenance than the sudo command. It's not good practice to have numerous people knowing and using the superuser password because when logged in as the superuser, they can do anything to the system. This could provide too much power for inexperienced users, who could unintentionally damage the system. Additionally, each time a user should no longer use the superuser account (for example, an employee leaves), the system administrator will have to change the root password.

In general, using sudo is considered safer than changing the user id with the su command. It is possible to disable su forcing users to rely on sudo to gain administrative rights.

script

Sometimes (in particular when writing tutorials like this one) you want to capture the output from a CLI session. You do this with the command script. This command forks a sub-shell that by default records the terminal session to a file named typescript. To stop recording, you exit this sub-shell using the command exit.

Here is an example of a session where we record a terminal session. After we've terminated the recording shell, we play back the recorded session with the command cat typescript.

$ script
Script started, file is typescript.
$  pwd
/home/myusername
$  exit
exit
Script done, file is typescript
$  cat typescript
Script started on Sat Mar 16 2013 10:36:03 AM CET
$ pwd
/home/myusername
$ exit
exit

Script done on Sat Mar 16 2013 10:36:05 AM CET

Final word

In this chapter, a few very basic shell comamnd has been used without much of an explanation. These are listed below. All of them will be described in more detail in the remaining chapters of this ebook.