Unix: The shell
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.
The
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]-----+ $
The
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.
For 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.
PoLP 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.
Allowing 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.
chmod
: change file mode bits to (e.g. access mode).pwd
: print working directoryexit
: exit from a (sub-)shellcat
: catenate (display) a file