Using Secure Shell
What is SSH?
SSH is a secure networking protocol that uses Public-key cryptography to make sure all data, including
authentication, is encrypted end to end. SSH was designed in 1994 as a encrypted replacement for plaintext
TELNET, RSH, RCMD and FTP applications over insecure, public networks. SSH also supports tunneling,
forwarding TCP ports and X11 connections. All run over TCP port 22.
SSH 1.2.12 was the last “open source” version of SSH and is the basis for the OPENSSH product, the most
popular freeware SSH implementation. SSH1 is considered insecure and obsolete. OpenSSH has managed to
incorporate most the more secure SSH2 features.
SSH2 is the code set used to establish the SSH Communications Security commercial SSH products; which is
the basis for most commercial SSH implementations (Sun Solaris). In 2006, SSH-2 became a proposed Internet
standard with the publication by the IETF "secsh" working group.
OpenSSH comes with LINUX as the freeware open source version. It gets updated more frequently than the
commercial version of the SSH Communications Security product.
The two most popular freeware SSH implementations are:
OpenSSH: http://www.openssh.org - common on LINUX/UNIX
PuTTY: http://www.chiark.greenend.org.uk/~sgtatham/putty/ - common on Windows
This discussion covers SSH command line under LINUX/UNIX, though most examples will also apply to
OpenSSH for Windows. You can find numerous discussions about using PuTTY under Windows on the
The sshd server daemon is installed by LINUX by default with the usual product naming convention
sshd.xx.xx.xx.xx.rpm. . Note the ssh client programs, ssh-client, ssh-keygen, ssh-agent, ssh-add are installed as
The ssh server is started with the command:
service sshd start
At boot time:
chkconfig sshd on
First thing to do in an SSH environment is to setup a public - private key pair. There are two key types used in
SSH V2 - DSA and RSA. RSA keys are similar to DSA keys, and will let you login with the SSHv2 protocol as
well. Unless you know you explicitly need a RSA key, there's probably little reason to make one as DSA is
more commion. Key sizes range from 768 to 2048 (default) bits. Either way, the key type will have to match
the remote side of the encrypted conversation. RSA1 is used for SSHV1
The procedure is the same as for DSA keys, but simply changing the type specified to ssh-keygen:
ssh-keygen -t dsa
ssh-keygen -t rsa ... or rsa1 for SSHV1
The response will request a "passphrase" to be entered. This is a method of "seeding" the public/private key-
pair generation and verifying future users of the key-pair.
This will generate output that looks like this:
Generating public/private dsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_dsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/user/.ssh/id_dsa.
Your public key has been saved in /home/user/.ssh/id_dsa.pub.
The key fingerprint is:
The output tells you the filename for the key, the public portion of the key, and the key's fingerprint - a small
hash of the key itself which is slightly less unique, but easier to compare than the entire key length.
Sometimes it is necessary to change the key’s passphrase. To change your ssh private key's passphrase, use the
ssh-keygen will then prompt you for the location of the private key (the default is usually ok), your current
passphrase to unlock the key, and then for a new passphrase twice to lock the key.
The public portion of a keypair (with extension .pub) is meant to be handed out to wherever you wish to
connect. This key is used to encrypt data on the remote machine (the one you're connecting to), which is then
sent to the local machine.
The local client can then use your private key - either by first asking for your passphrase to decrypt it, or by use
of the ssh-agent (see below) - to decrypt the information sent, then the remote server knows that the person who
is initiating the connection must have the corresponding private key, and therefore is who they claim to be.
If you look at the public key, it will appear similar to this:
ssh-dss AAAAB3NzaC1kc3MA.....b40HgUC4= huston@xanadu
SSH public keys are a single-lined. When you view the key in some programs, it may appear to take up 8 lines
or so, but that is simply word-wrapping in your text editor. You must make sure when copying your key to the
authorized_keys file that it is all contained on a single line, or SSH will fail without any error on your end to
explain the problem. The entire key must be written on one line for the SSH daemon to read it, with no line
To actually use your keys, the public part of the key of the "client" must be listed in the file
~/.ssh/authorized_keys on the remote "server". The simple way to make sure that line breaks are not
inserted in a key erroneously, is as follows:
cd ~/.ssh ; cat id_dsa.pub >> authorized_keys, chmod 600 authorized_keys
You can add other public keys to the same file from other clients that you want to be able to access the "server"
as the userid of the home directory containing the .ssh directory on the remote "server". Once that's done, any
holder of the private key that goes with those public keys will be able to login to the account as that account on
the "server". You still have a passphrase to use for each login, instead of your password, until you modify the
procedure using ssh-agent described below.
Older versions of SSH would have two separate files, like authorized_keys2 and known_hosts2 for
SSH V2 keys since the older versions would choke on a version 2 key in a version 1 file. Newer versions of
SSH will read both files and key type from the same file.
Your authorized_keys file MUST always be is non-group and non-other writable (permissions 600), or
SSH session establishment may fail.
Not everyone runs the same version of SSH - some Unix vendors such as Sun use a commercial version from
ssh.com. The open source version we run from OpenSSH uses a different type of key
If you have a key from a remote location which uses a different SSH program, or you want to send a copy of
your key to someplace that doesn't use OpenSSH-compliant programs, you may need to convert your key to
make it work.
ssh-keygen -e (input file) > (output file)
-e: tells ssh-keygen to export a key in SECSH format
-i' tells ssh-keygen to convert from SECSH format to OpenSSH.
This section assumes you have generated a SSH key pair and installed the public key on the remote ssh server
(csc.oakton.edu in this example).
The First Time
Whenever you establish an SSH connection for the first time, the SSH client will ask if you want to add the
remote (server) ssh hosts key to the ~/.ssh/known_hosts file. An example:
The authenticity of host 'csc (126.96.36.199)' can't be established.
RSA1 key fingerprint is ab:cc:0f:8e:c3:b0:ce:7a:00:9c:1a:88:b7:82:67:01.
Are you sure you want to continue connecting (yes/no)?
Usually you will respond yes, but note the key type, RSA1 (SSHV1) is a poor encryption choice. The finger
print is the one generated on the remote host when that system performed a ssh-keygen process.
If apreviously connected SSH host has changed keys (or IP address), you may see:
@ 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 RSA1 host key has just been changed.
The fingerprint for the RSA1 key sent by the remote host is
Please contact your system administrator.
Add correct host key in /u/user/.ssh/known_hosts to get rid of this message.
Offending key in /u/user/.ssh/known_hosts:1
Password authentication is disabled to avoid trojan horses.
Agent forwarding is disabled to avoid trojan horses.
X11 forwarding is disabled to avoid trojan horses.
This is a warning that a previously connect SSH host sis presenting a fingerprint/andor
IP adderss different from one previously placed in the known_hosts file.
Depending on your knowledge of the host system, you may or may not want to change the
host fingerprint; usually by deleting the known_hosts file, but you can edit the file and
delete the specific key.
ssh <hostname>or<ip address>
ssh user@<hostname>or<ip address>
That tells the SSH software to login as user with a shell prompt on the specified hostname or ip address
(running the SSH server process).
scp and sftp are available with the SSH2 protocol to copy files to other machines. Here's a basic usage
scp [user@source hostname:]<source filename> [user@destination hostname]:<destination filename>
Either 'source' or 'destination' can be a local file, or a remote file in the form of '[user@]host:file'.
For example, to copy the local file 'testfile' to your home directory on csc:
scp testfile user1@csc:testfile
If instead you wish to copy ~/testfile from csc to the current directory, use:
scp user1@:testfile .
sftp works in a similar way, but gives a FTP-like interface:
This will give a secure FTP interface to your home directory on csc. SFTP requires that both machines run the
same version of SSH; you can override this behavior with the '-1' flag, which will force sftp to use the older
version 1 protocol (you must have SSHv1 keys created and installed for this to work):
sftp -1 csc
Note the difference here: scp does a direct copy of a file, sftp gives you an ftp command line. Both connections
occur on port 22.
ssh connection problems
The most common ssh conenction problems are caused by:
- Bad permissions on your ~/.ssh directory or the files in it
- Having spaces and/or newline characters in your key
The ssh-agent process allows you to authenticate your private keys to the local (client) machine, so that you can
use them without typing a passphrase every time.
On a local machine:
There's two ways to start a ssh-agent process; either by calling a command as a child to the agent, or installing it
in the current environment:
will make the command specified on the commandline a child of the agent, so the command will inherit the
agent's environment. This allows any other children processes to access the agent to authenticate keys. The
This will install the agent in the current environment.
Now that your agent is running, you'll need to add your keys to it to make them work. Simply using the 'ssh-
add' command will do this:
Need passphrase for /home/user/.ssh/id_dsa
Enter passphrase for /home/user/.ssh/id_dsa
Identity added: /home/user/.ssh/id_dsa (dsa w/o comment)
Now, when you attempt to login to another machine, you will not be prompted for a password, passphrase, or
anything else. It should simply exchange information between the running ssh-agent, and your keys, and let you
login with no hassle:
machine:~$ ssh csc
Last login: Tue Feb 19 15:08:26 2002 from machine
If you have multiple keys with standard names (id_dsa, id_rsa, identity) but the same passphrase. they'll all be
added by ssh-add. You can simply name them on the command line of ssh-add and all the keys you name will
be tried. ssh-add will ask for your passphrase, and add the first key; if you have multiple keys, it will then try
the same passphrase on all the others and add them if successful; otherwise it will ask again for the passphrase
for the next key.
If you have a lot of keys, it can be helpful to set all of them to use the same passphrase. This way, when you run
'ssh-add', you won't have to type separate passphrases for each key (it will try your first passphrase on all of
On a remote machine:
When you login to a remote machine, you've used the ssh-agent on your local machine to authenticate with your
keys. However, if you have a lot of keys authenticated, it's handy to forward your agent through the connection
as well. This way, you can 'hop' from one machine to another, taking your credentials with you as you go and
not having to run another agent on the far end and authenticate it again.
All the machines in Peyton have agent forwarding setup by default, but if you're connecting from a laptop or
home computer you may wish to turn it on. You can do so one of two ways:
Add the -A flag to ssh, ie ssh -A username@hostname
Edit (or create) the file ~/.ssh/config, and include these lines:
The first method might be handy for a one-off session, while the second will turn on agent forwarding for all
You can start ssh-agent automatically under bach/ksh by adding the following line to your .profile or
if [ "X$SSH_AUTH_SOCK" = "X" ] ; then
To kill the agent when you logout(so you don’t leave authenticated ssh-agent sessions open on the system),
create a file called .bash_logout with the following command:):
if [ "$SSH_AGENT_PID" -a "$SHLVL" = "1" ] ; then
eval `ssh-agent -k`
A normal TCP connection is established from a “random” source port to an application specific destination port.
SSH Tunneling forwards a *local* TCP port to a *remote* TCP port on another device using port 22. local
means an available port on the client to an application specific remote using port 22 as an encrypted tunnel .
This is useful when you:
a) need to talk "directly" (to a specific TCP port) to a machine that is separated from you by a firewall/gateway
b) can send data directly to a machine, but you don't want to send it unencrypted.
Either scenario requires port 22 connection to a device a) assumes you go thru a 3rd device rather than directly
as in b).
Example A: Using an SSH Tunnel to encrypt your session
mymachine ---> remotemachine
SSH tunnels are not only useful for bypassing firewalls, they are also useful if you want an encrypted channel
from source to destination. Suppose you can talk directly to "remotemachine" from "mymachine" with no
Issue these commands (run on "mymachine"):
ssh -N -L 33642:localhost:5900 user@remotemachine
telnet localhost 33642
The first command creates an encrypted pipe from "mymachine" to "remotemachine"(port 22) that forwards
data to itself on port 5900.
The second command opens up a telnet session on "mymachine" to port 33642. This session is then
FORWARDED over the pipe to "remotemachine", which then forwards the session to itself on port 5900.
You can extend / combine these techniques to hop thru multiple firewalls, encrpyt a tunnel within a tunnel
(assuming both firewall and remotemachine run an SSH server.
Example B: Simple 3rd party SSH tunnel
mymachine ---> firewall ---> remotemachine
You are sitting on "mymachine", and you have a program that needs to send data to a TCP port (say 5900) on
"remotemachine". If "remotemachine" is behind a "firewall", you cannot even refer to "remotemachine"
directly. As far the outside world is concerned "remotemachine" doesn't even exist. All communication
between "remotemachine" and the internet is done through "firewall".
1) If you can SSH into the "firewall",then "firewall" knows about "remotemachine", and "mymachine" knows
about "firewall", so you can setup a tunnel with the following command::
ssh -N -L 33642:remotemachine:5900 user@firewall
Note that in the above command remotemachine is usually the private IP address of the remote machine behind
the firewall. Because erver names and associated IP addrese are not usually known thru a
firewall/gateway/proxy type gateway device.
2) Then you telnet to "remotemachine" port 5900 by running the following command on "mymachine"
telnet localhost 33642
or whatever client you wish to use.
Notes on the example B:
"ssh user@firewall" is the SSH Login to the firewall (3rd device). The password is the one for your account on
the firewall. The "-N" just keeps the tunnel open.
"-L 33642:remotemachine:5900" is the relay part of the tunnel. This tells SSH that you don't want to open a
shell on the firewall, but instead that you using it as a relay. Notice that "remotemachine" isn't necessarily
addressable from the outside - it is only necessary that "firewall" knows how to find it on the inside.
"-L" tells SSH to listen to port 33642 on "mymachine" (listen locally) and redirect any received data
THROUGH "firewall" on port 22 and on to port 5900 on "remotemachine". So, in essence, telnet'ing to
"localhost 33642" is *like* telnet'ing to "remotemachine 5900".
port 33642 was chosen at random. You merely need a free port on "mymachine" to use and abuse (try
"netstat" to list ports in use).
The session is encrypted between "mymachine" and "firewall", cleartext between "firewall" and
Example C: "chain" SSH tunnels through multiple gateways
Chain SSH tunnels to get through multiple firewalls:
mymachine ---> Afirewall ---> Bfirewall ---> remotemachine
This requires you have SSH accounts on both firewalls.
First, SSH into "Afirewall" and run "netstat" to find an open port there (say 4652).
Second, , while logged into "Afirewall" set up the next SSH tunnel "hop" with the command:
ssh -N -L 4652:remotemachine:5900 user@Bfirewall
This command picks up port 4652 on "Afirewall" and forwards it through "Bfirewall" to its final destination at
"remotemachine" port 5900.
Third, back on "mymachine" execute
ssh -N -L 33642:localhost:4652 user@Afirewall
This opens up a tunnel from port 33642 on "mymachine" and forwards THROUGH "Afirewall" to ITSELF on
port 4652 (remember... when using the -L option the machine name that appears between the :: is resolved from
the point-of-view of "Afirewall", so localhost is ITSELF).
Example D: SSH Tunnel within a Tunnel
mymachine ---> Afirewall ---> remotemachine
On "Afirewall" run:
ssh -N -L 4654:localhost:22 user@remotemachine
On "mymachine" run:
ssh -N -L 43642:localhost:4654 user@Afirewall
ssh -p 43642 -N -L 43642:localhost:5900 -o HostKeyAlias="remotemachine" localhost
The "-o HostKeyAlias=" statement is VERY important.
Example E: No SSH account on the firewall.
mymachine <--- Afirewall <--- remotemachine
Suppose you don't have an SSH account on the firewall. You still want to forward port 33642 on "mymachine"
to port "5900" on "remotemachine". Since "remotemachine" is behind a firewall, "mymachine" is not. So
"remotemachine" can actually see "mymachine", just not the other way around.
There is a "-R" switch does the OPPOSITE - it captures traffic on the remote side and forwards it to the local
If you can get PHYSICAL access to login to "remotemachine", run the following command:
ssh -N -R 33642:localhost:5900 "mymachine"
That sets up a tunnel that forwards all traffic from the REMOTE port (in this case "mymachine" port 33642) to
port 5900 on localhost (i.e. "remotemachine"). After running this at work you could then set up whatever
program to listen to port 5900 and go home..
Now, at home on "mymachine" it would be easy to telnet into "remotemachine" port 5900. Just do the usual
telnet localhost 33642
IMPORANT NOTE ON TUNNEL SETUP: All the above examples use TELNET as a client for a SSH tunnel
session. This is because TELNET can connect to ANY tcp port. You will also wish to use other clients
assuming they can connect to other ports. If the client CANNOT connect to another port, you can setup SSH to
forward the application default port on mymachine to the same port on remotemachine. Note this will make
ALL port requests get forwarded to remotehost. This is bad for applications like web browsing (port 80). But
not usually used since you can specify a different port on a web browser.
Note also, most SSH clients also have a default option (-X) for automatically forwarding XWindows) GUI
session between machines.