Simple SSH Tutorial Outline
This is the outline for the talk I gave for the UMBC LUG on SSH. It
probably won't be terribly helpful, as I wrote it for me, and I know all
of this anyway, but it might be of some use to other people. I make no
guarantees.
- Concepts
- Encryption
Scrambles information so other people can't read it.
- Shared secrets
Common case. There is a "password" (or similar) that both sides must know
to encrypt/decrypt.
- Public keys
There is a pair of keys. Things encrypted with one may only be decrypted
with the other. Usually, one is kept secret while the other is publically
distributed.
- Public key authentication
If you have the public key, you can use it to check if the other end
really has the private key (thus proving its authenticity).
- Fingerprints
When you receive a public key, you may not know if it really belongs to
the person you want to talk to. One method of verifying keys is via
fingerprints. If you know the key's fingerprint ahead of time, you can
check that agains the key you have. (Fingerprints are much shorter than
actual keys and more practical to write down on sheets of paper.)
- Accessing machines remotely.
- Local access
When you sit at a computer (and a command line), everything you type goes
directly to the shell (which provides the "command line").
- telnet
telnet goes across the network to simulate the same thing. Whatever you
type is picked up, sent across the network, and sent to the shell on the
remote machine.
- telnet is plaintext
telnet sends everything literally across the network, so anyone watching
the network will see exactly what you type, including things that you
don't even see on the screen (like passwords).
- ssh
ssh has the same basic concept as telnet--it takes what you type and sends
it across the network to a shell on the remote computer.
- ssh is encrypted
ssh, however, uses encryption to protect your information. People
watching an ssh session on the network will see only gibberish.
- Versions of ssh
There have been two major versions of the SSH protocol, as well as
multiple implementations of it.
- The protocol
Version 2 has a lot of nice features, including not being vulnerable
to one particular security hole present in the first version of the
protocol.
- Implementations
There are three common implementations of ssh. OpenSSH, F-Secure SSH,
and SSH.com SSH.
- UMBC
UMBC uses SSH.com's SSH1, which only supports version 1 of the SSH
protocol. (It does have compensation code to make the security hole
harder to exploit.)
- Basic SSH
- Standard case
Usually, ssh is used just as you would telnet. ssh to a host, type your
password (correctly), and you're in.
- Example
$ ssh somehost
user@somehost's password: [not shown]
somehost$
- Description
Note that ssh does not ask for your username as telnet does. ssh assumes
the username on the remote computer is the same as that on the local one.
- Host keys
ssh uses public key encryption for the initial conversation with the
host.
- Usefulness of PKI
- Encryption
public keys are slow to use, so the ssh client sends a password encrypted
with the server's public key.
- Authentication
To prevent a man-in-the-middle attack, the client uses the host key to
verify the host's authenticity.
- Man-in-the-middle attack
Once the data is encrypted on the network, it can only be read by the
intended recipient. However, someone may set up a computer that pretends
to be the host that you want so you connect to that fake computer instead
of the real one. The fake computer can then decrypt your data, look at
it, encrypt it again, and send it on to the real host. Since your data is
going all the way to the real computer (and back), you might never notice
the intrusion.
However, since the host's private key is kept secret, a man-in-the-middle
can't fake it and is doomed to failure.
- Practical considerations
When you ssh to a host you've never talked to before, it sends you its
public key. This is possibly a security hole, since a fake host could get
you to take its key instead at this point.
- Example
$ ssh somehost
The authenticity of host 'somehost (192.168.1.1)' can't be established.
RSA key fingerprint is 90:9c:46:ab:03:1d:30:2c:5c:87:c5:c7:d9:13:5d:75.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'somehost' (RSA) to the list of known hosts.
user@somehost's password: [not shown]
somehost$
- Explanation
ssh is warning you that it doesn't really know about this host yet. It
shows you the hostname and IP address, so you can be sure you're talking
to the correct computer. It also shows the fingerprint of the server's
public key. If you know what the fingerprint should be, you can check it
and disallow it if it doesn't match.
- Reasonable paranoia
Most of the time, it's pretty safe to just accept host keys. At least
within a controlled environment such as UMBC, it's unlikely that someone
could compromise the network enough to have their computer masquerading
as, say, one of the gl machines. In other situations, it's up to you to
decide whether to get key information from the server admin before
connecting.
- Changed host key example
$ ssh somehost
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that the RSA host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
90:9c:46:ab:03:1d:30:2c:5c:87:c5:c7:d9:13:5d:75.
Please contact your system administrator.
Add correct host key in /home/user/.ssh/known_hosts to get rid of this message.
Offending key in /home/user/.ssh/known_hosts:1
Password authentication is disabled to avoid man-in-the-middle attacks.
Agent forwarding is disabled to avoid man-in-the-middle attacks.
X11 forwarding is disabled to avoid man-in-the-middle attacks.
Permission denied (publickey,password,keyboard-interactive).
$
- User names
ssh assumes that your username on the remote computer is the same as it is
locally.
- Different username
$ ssh othername@somehost
othername@somehost's password: [not shown]
somehost$
- Explanation
You can specify the username on the command line if it differs from the
local username. You can also put it in a config file, which comes later.
- scp
ssh also has a program for copying files across the network. It encrypts
everything, of course, so neither your password nor the data is visible to
prying eyes. (FTP, the other most common method for copying files, leaves
both your password and the file visible)
- Example
$ scp localfile somehost:public_html/
user@somehost's password: [not shown]
localfile 100% |*****************************| 2048 KB 00:03
$ scp othername@somehost:public_html/index.html ~/public_html/
othername@somehost's password: [not shown]
index.html 100% |*****************************| 10198 KB 00:05
$
- Explanation
scp works just like cp. It copies files from one place to another. The
only things it adds is the possibility of some of those places being on
other computers. The syntax for a remote computer is to put
'computername:' in front of the file name. (Note that relative paths are
relative to your home directory.) Like ssh, you can put 'username@'
before the hostname if your username is different there.
- Intermediate SSH
- Remote commands
You don't have to connect to a shell on the remote computer. You can just
tell ssh to run a command remotely and give you its output.
- Example
$ hostname
thishost
$ ssh somehost hostname
user@somehost's password: [not shown]
somehost
$
- Programs that use a terminal
Some programs manipulate the terminal as they run. Usually these are
interactive programs, like pine or emacs. Normally, ssh will run the
remote command non-interactively and just spit its output back at you.
For terminal-using programs, you must tell ssh to use a pseudoterminal
with the -t option.
- Example
$ ssh -t somehost pine
user@somehost's password: [not shown]
[pine opens; user reads mail; user exits]
$
- X11 forwarding
Graphical programs use the X Window protocol to display on your screen.
With X, you can run a program on a remote computer have have it display
locally. Normally, X runs unencrypted over the network. With ssh's -X
option, you can tell it to use its encrypted connection for X programs.
- Example
$ ssh -X -f somehost xclock
user@somehost's password: [not shown]
[xclock appears on screen]
$
- Note on -f
I also used the -f option here. -f puts ssh in the background after it
asks for your password. The above command is the remote equivalent of
'xclock&'.
- Config files
The config file is ~/.ssh/config and can contain lots of stuff. (Note
that only the local options file is important--ssh reads it before
connecting to the remote host.)
- Host <foo>
The file is broken up into chunks by Host directives. Everything after a
Host line applies to that host. (Until the next Host line, of course.)
The argument after 'Host' is the name that you'd type on the command
line.
- Host *
There is a special hostname, "*", which represents all hosts. You can use
this hostname to set default values for settings. (Note that OpenSSH
gives priority to things that are earlier in the file, so 'Host *' must
appear last if you want more specific Host settings to override the
generic ones. (Also note that SSH.com's SSH2 reverses this order;
'Host * must come first there.))
- HostName <name>
If HostName is specified, ssh will connect to that host instead of the one
specified on the command line.
- Example
-----
Host moo
HostName supercalifragilisticexpialidocious
-----
$ host moo
moo does not exist
$ host supercalifragilisticexpialidocious
supercalifragilisticexpialidocious is 192.168.1.2
$ ssh moo
user@moo's password: [not shown]
supercalifragilisticexpialidocious$
- User <username>
When this is present, ssh uses the specified user. This is much easier
than typing 'user@' on the command line all the time.
- Compression <yes or no>
Setting 'Compression yes' turns on data compression, which helps with slow
links.
- Lots of others
There's a lot of stuff you can set in the config file. Check the man page
or SSH book for other things.
- Advanced SSH
- RSA authentication
ssh can use a number of methods to authenticate you to the remote host.
Passwords are the default, since they're the most common. A more flexible
approach is to use RSA keys.
These work in much the same way that ssh uses the server's host key to
verify the remote computer's identity.
- Versions
The programs and file locations here will work in SSH.com's SSH1 and
OpenSSH. They are different in SSH2.
- Advantages
- Can't be compromised remotely
The server never sees your private key, so even if it's compromised the
attacker can't steal your password for other hosts.
- Can use an agent to hold the key
If you have a local ssh-agent with your key loaded, ssh will use it
instead of asking you for a password every time. This is quite convenient
while still pretty secure.
(Agents will be covered next.)
- Can restrict keys to executing specific commands
If you add 'command="<program>" ' to the beginning of the key's line in
~/.ssh/authorized_keys, anyone authenticating with that key will have
<program> automatically run. They will not get a shell or any other
program.
Check the man page or SSH book for more info.
- Creating a key
Use ssh-keygen. I recommend the '-t rsa' option, which creates an RSA key
for use with version 2 of the SSH protocol. (You can use '-t rsa1' for a
version 1 key and '-t dsa' for a DSA key, which may not be supported
everywhere.)
Note that with SSH1 there is no -t option, because there's only one type
of key.
- Running ssh-keygen
$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_rsa): [press enter for default]
Enter passphrase (empty for no passphrase): [not shown]
Enter same passphrase again: [not shown]
Your identification has been saved in /home/user/.ssh/id_rsa.
Your public key has been saved in /home/user/.ssh/id_rsa.pub.
The key fingerprint is:
44:c8:07:c9:f8:f4:f5:9b:05:d1:0f:d1:05:f0:5d:bf user@localhost
$
- Allowing login via that key
On the remote host, add the line in /home/user/.ssh/id_rsa.pub to
~/.ssh/authorized_keys.
- Quick approach
$ scp ~/.ssh/id_rsa.pub somehost:.
user@somehost's password: [not shown]
id_rsa.pub 100% |*****************************| 225 00:00
$ ssh somehost
user@somehost's password: [not shown]
somehost$ cat id_rsa.pub >> ~/.ssh/authorized_keys
somehost$ rm id_rsa.pub
somehost$ exit
$ ssh somehost
Enter passphrase for key '/home/user/.ssh/id_rsa': [not shown]
somehost$
- Done
You can now log in to the remote host using your RSA key.
- ssh-agent
An ssh-agent is a program that keeps a copy of your key in memory for ssh
programs to use. (Normally, you have to type the passphrase for the key
every time its needed.) It makes ssh as easy as this:
$ ssh somehost
somehost$
- Security concerns
The agent is pretty good about security. It never even divulges your
key--ssh programs hand data to it and it does the needed work with the key
itself. However, there are some possible problems.
- Unattended use of the agent
If you walk away from your computer, someone can sit down at it and ssh
places as you. Solution: remove the key from the agent when you're going
to be gone from your computer. (And/or just lock the screen.)
- Tricking the agent
If someone else on the computer can act as you (root can do this), they
can give data to the agent and have it processed as if you asked.
Solution: don't run an agent on a computer where you don't trust the
admin.
- Stealing the key
Someone with access to the computer's memory (usually, this is only root)
can search through the agent's data and get an unencrypted copy of the
key. Solution: again, don't run an agent on a computer where you don't
trust the admin.
- Starting the agent
The procedure for running the agent differes slightly depending on whether
you're running a Bourne Shell derivative such as bash, ksh, or zsh (this
is probably the case) or a C-Shell derivative such as csh or tcsh (this is
less likely).
- Bourne Shell
$ eval `ssh-agent -s`
$
- C-Shell
> eval `ssh-agent -c`
>
- Adding and removing keys
Key management with an agent is done via the ssh-add program.
- Adding keys
$ ssh-add ~/.ssh/id_rsa
Enter passphrase for /home/user/.ssh/id_rsa: [not shown]
Identity added: /home/user/.ssh/id_rsa (/home/user/.ssh/id_rsa)
$
- Listing
$ ssh-add -l
1024 75:a4:2c:9b:b1:58:8f:9c:96:d8:99:77:fc:01:0d:8a /home/user/.ssh/id_rsa (RSA)
$
- Removing keys
$ ssh-add -d ~/.ssh/id_rsa
Identity removed: /home/user/.ssh/id_rsa (/home/user/.ssh/id_rsa.pub)
$
- Using the agent
Once the keys are loaded, the agent is used automatically.
$ ssh somehost
somehost$
- Note on multiple shells
The agent's setup is only designed to work with a single shell. All you
really need to do to have multiple shells (e.g. multiple xterms, etc.) use
the same agent is to copy the value of the environment variable
$SSH_AUTH_SOCK from one to the other.
$ echo $SSH_AUTH_SOCK
/tmp/ssh-XXLN11Tv/agent.953
[In another shell on the came computer:]
$ export SSH_AUTH_SOCK=/tmp/ssh-XXLN11Tv/agent.953
$
(Note that in C-Shell derivatives, the command is
'setenv SSH_AUTH_SOCK ').
- keychain
I use a program called 'keychain' to manage multiple shells with the same
ssh agent. You can install it and read the documentation for more info,
but basically, all you need to do is run 'keychain ~/.ssh/id_rsa' in your
of your shell's startup files, and it will check for an existing agent,
connect to it if it exists, and create a new one (loading the supplied
key) if it doesn't.
- Exiting the agent
From the shell where you started it, run 'eval `ssh-agent -k`' and the
running agent will be shut down. If you copied $SSH_AUTH_SOCK to other
shells, those variables will have to be unset by hand.
- Port forwarding
The ssh program can also be told to listen on arbitrary ports eith on the
local or remote computer, forward any data through the encrypted
connection, and send it to some other destination from the other end.
- More concrete example
- Scenario
I have a web proxy on a remote computer. I want my local browser to use
an encrypted connection to that computer to use the proxy.
So, ssh will listen for connections locally, forward the data across the
encrypted connection and send it to the proxy on the remote computer. My
web browser will be told to use a port on the local browser as its proxy.
- Numbers
The remote computer is somehost. The local computer is localhost. The
proxy is listening on port 5865 on the remote host. I'll have ssh use
port 5001 on the local host.
- Commands
$ ssh -L 5001:somehost:5865 somehost
user@somehost's password: [not shown]
somehost$
- Explanation
The -L option tells ssh to listen on the local host and forward to the
remote host. (Use the -R option for the reverse situation.)
The first number is the port to listen on at the local computer. In this
case, it's 5001.
The second value is the computer to which the data should go after it
comes out of the encrypted connection. (Since this example has the data
going to the same computer as the connection goes to, I could have used
the special name 'localhost', but avoided that, as it would confuse
things.) Yes, the computer specified can be any computer on the network.
The last number is the port that the data will be sent to on the
destination computer. In this example, that port is 5865, where the web
proxy is listening.
I would then set my browser to use 'localhost:5001' as its HTTP proxy.
The tunnel remains open for as long as you're conencted via ssh.
- Listening non-locally
Normally, OpenSSH will only accept connection from the computer on which
it's listening. If you want other computers on the network to use the
encrypted tunnel, you must also use the -g option to ssh.
- Tunnel without a terminal
OpenSSH has a -N option that can be used to just create an encrypted
tunnel without opening a shell on the remote computer. The tunnel remains
open until the client ssh is killed.
Phil! Gregory