This document covers SSH on the Linux Operating System and other OSes that use
OpenSSH. If you use Windows, please read the document SSH
Tutorial for Windows If you use Mac OS X, you should already have OpenSSH
installed and can use this document as a reference.
This is one of the top tutorials covering SSH on the Internet. It was
originally written back in 1999 and was completely revised in 2006 to include
new and more accurate information. It has been read by over 227,000 people and
consistently appears at the top of Google's search results for SSH Tutorial
and Linux SSH.
There are a couple of ways that you can access a shell (command line) remotely
on most Linux/Unix systems. One of the older ways is to use the telnet
program, which is available on most network capable operating systems.
Accessing a shell account through the telnet method though poses a danger in that
everything that you send or receive over that telnet session is visible in
plain text on your local network, and the local network of the machine you are
connecting to. So anyone who can "sniff" the connection inbetween can see your
username, password, email that you read, and commands that you run. For these
reasons you need a more sophisticated program than telnet to connect to a
remote host.
|
Unencrypted telnet session |
SSH, which is an acronym for Secure SHell, was designed and created to provide
the best security when accessing another computer remotely. Not only does it
encrypt the session, it also provides better authentication facilities, as well
as features like secure file transfer, X session forwarding, port forwarding
and more so that you can increase the security of other protocols. It can use
different forms of encryption ranging anywhere from 512 bit on up to as high as
32768 bits and includes ciphers like AES (Advanced Encryption Scheme), Triple
DES, Blowfish, CAST128 or Arcfour. Of course, the higher the bits, the longer
it will take to generate and use keys as well as the longer it will take to
pass data over the connection.
|
Encrypted SSH session |
The two diagrams above show how a telnet session can be viewed by anyone on the
network by using a sniffing program like Ethereal (now called Wireshark) or
Sniffit. It is really rather trivial to do this and so anyone on the network
can steal your passwords and other information. The first diagram shows user
jsmith logging in to a remote server through a telnet connection. He types his
username jsmith and password C0lts06!, which are viewable by anyone who is
using the same networks that he is using.
The second diagram shows how an encrypted connection like SSH is not viewable
on the network. The server still can read the information, but only after
negotiating the encrypted session with the client.
This tutorial isn't going to cover how to install SSH, but will cover how to use
it for a variety of tasks. Consult your Linux distribution's document for information
on how to setup OpenSSH.
Chances are that if you are using a version of Linux that was released after
2002, that you already have OpenSSH installed. The version of SSH that you will
want to use on Linux is called OpenSSH. As of this writing (January 2006), the
latest version available is 4.2, but you may encounter versions from 3.6 on up.
If you are using anything lower than version 3.9, I'd strongly advise you to
upgrade it.
OpenSSH can be obtained from http://www.openssh.org/
To really make ssh useful, you need a shell account on a remote machine, such
as on a suso.org account.
The first thing we'll do is simply connect to a remote machine. This is
accomplished by running 'ssh hostname' on your local machine. The hostname
that you supply as an argument is the hostname of the remote machine that you
want to connect to. By default ssh will assume that you want to authenticate
as the same user you use on your local machine. To override this and use a
different user, simply use remoteusername@hostname as the argument. Such as
in this example:
ssh username@arvo.suso.org
The first time around it will ask you if you wish to add the remote host to a
list of known_hosts, go ahead and say yes.
The authenticity of host 'arvo.suso.org (216.9.132.134)' can't be established.
RSA key fingerprint is 53:b4:ad:c8:51:17:99:4b:c9:08:ac:c1:b6:05:71:9b.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'arvo.suso.org' (RSA) to the list of known hosts.
It is important to pay attention to this question however because this is one
of SSH's major features. Host validation. To put it simply, ssh will check
to make sure that you are connecting to the host that you think you are
connecting to. That way if someone tries to trick you into logging into
their machine instead so that they can sniff your SSH session, you will have
some warning, like this:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: POSSIBLE DNS SPOOFING DETECTED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
The RSA host key for arvo.suso.org has changed,
and the key for the according IP address 216.9.137.122
is unchanged. This could either mean that
DNS SPOOFING is happening or the IP address for the host
and its host key have changed at the same time.
Offending key for IP in /home/suso/.ssh/known_hosts:10
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ 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
96:92:62:15:90:ec:40:12:47:08:00:b8:f8:4b:df:5b.
Please contact your system administrator.
Add correct host key in /home/suso/.ssh/known_hosts to get rid of this message.
Offending key in /home/suso/.ssh/known_hosts:53
RSA host key for arvo.suso.org has changed and you have requested strict
checking.
Host key verification failed.
If you ever get a warning like this, you should stop and determine if there is
a reason for the remote server's host key to change (such as if SSH was
upgraded or the server itself was upgraded). If there is no good reason for
the host key to change, then you should not try to connect to that machine
until you have contact its administrator about the situation. If this is your
own machine that you are trying to connect to, you should do some computer
forensics to determine if the machine was hacked (yes, linux can be hacked). Or
maybe your home computer's IP address has changed such as if you have a dynamic
IP address for DSL. One time I received this message when trying to connect
to my home machine's DSL line. I thought it was odd since I hadn't upgraded
SSH or anything on my home machine and so I choose not to try to override the
cached key. It was a good thing that I didn't try because I found out that my
dynamic IP address had changed and that out of chance, another Linux machine
running OpenSSH took my old IP.
After saying yes, and if there is an account on the remote system named
username, it will prompt you for username's password on the remote system.
If you type in the remote password correctly it should let you in. If it
doesn't, try again and if it still fails, you might check with the
administrator that you have an account on that machine and that your password
is correct.
Now that you have spent all that time reading and are now connected, go ahead
and logout. ;-) Once you're back to your local computer's command prompt enter
the command 'ssh-keygen -t dsa'.
ssh-keygen -t dsa
It should begin spitting out the following:
Generating public/private dsa key pair.
Enter file in which to save the key (/home/localuser/.ssh/id_dsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/localuser/.ssh/id_dsa.
Your public key has been saved in /home/localuser/.ssh/id_dsa.pub.
The key fingerprint is:
93:58:20:56:72:d7:bd:14:86:9f:42:aa:82:3d:f8:e5 localuser@mybox.home.com
It will prompt you for the location of the keyfile. Unless you have already
created a keyfile in the default location, you can accept the default by
pressing 'enter'.
Next it will ask you for a passphrase and ask you to confirm it. The idea
behind what you should use for a passphrase is different from that of a
password. Ideally, you should choose something unique and unguessable, just
like your password, but it should probably be something much longer, like a
whole sentence. Here are some examples of passphrases I've used in the past:
The right thing changes from state to state the purpose of life is to give it purpose They're not going to guess this passphrase! The RIAA can just suck my big ass It is never a good day at Teletron
Some passphrases that I've used have had as many as 60 characters along with
punctuation and numbers. This makes the passphrase harder to guess. To give
you an idea of how much more secure a passphrase is than a password. Consider
this. Even if you narrowed down the number of words someone could use in a
passphrase to 2000 words, if that person used 5 words in a sentence from that
2000 word set, it would mean there are 32,000,000,000,000,000 different
combinations. Compare this with 72,057,594,037,927,936 (only 2.5 times more
combinations), which is the total possible combinations in an 8 character
password. Most people choose words from a set of 10,000 or more words,
bringing the complexity of a 5 word passphrase to 1,387 or more times greater
than that of a 8 character password.
Don't use any famous quotes or phrases for your passphrase, they may be
easily guessed.
The reason why you would generate a keyfile is so that you can increase the
security of your SSH session by not using your system password. When you
generate a key, you are actually generating two key files. One private key and
one public key, which is different from the private key. The private key
should always stay on your local computer and you should take care not to lose
it or let it fall into the wrong hands. Your public key can be put on the
machines you want to connect to in a file called .ssh/authorized_keys. The
public key is safe to be viewed by anybody and mathematically cannot be used to
derive the private key. Its just like if I gave you a number 38,147,918,357 and
asked you to find the numbers and operations I used to generate that number. There
are nearly infinate possibilities.
Whenever you connect via ssh to a host that has your public key loaded in the
authorized_keys file, it will use a challenge response type of authentication
which uses your private key and public key to determine if you should be
granted access to that computer It will ask you for your key passphrase
though. But this is your local ssh process that is asking for your passphrase,
not the ssh server on the remote side. It is asking to authenticate you
according to data in your private key. Using key based authentication instead
of system password authentication may not seem like much of a gain at first,
but there are other benefits that will be explained later, such as logging in
automatically from X windows.
Go ahead and copy your public key which is in ~/.ssh/id_dsa.pub to the remote machine.
scp ~/.ssh/id_dsa.pub username@arvo.suso.org:.ssh/authorized_keys
It will ask you for your system password on the remote machine and after
authenticating it will transfer the file. You may have to create the .ssh
directory in your home directory on the remote machine first. By the way, scp
is a file transfer program that uses ssh. We'll talk more about it later.
Now when ssh to the remote machine, it should ask you for your key passphrase
instead of your password. If it doesn't, it could be that the permissions
and mode of the authorized_keys file and .ssh directory on the remote server
need to be set more restrictively. You can do that with these commands on
the remote server:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
You can also put the public key in the remote authorized_keys file by simply
copying it into your paste buffer, logging into the remote machine and pasting
it directly into the file from an editor like vi, emacs or nano. I would
recommend using the 'cat' program to view the contents of the public key file though
because using less will end up breaking the single line into multiple lines.
cat ~/.ssh/id_dsa.pub
The true usefulness of using key based authentication comes in the use
of the ssh-agent program. Usually, the ssh-agent program is a program
that starts up before starting X windows and in turn starts X windows
for you. All X windows programs inherit a connection back to the ssh-agent,
including your terminal windows like Gnome Terminal, aterm, xterm and so on.
What this means is that after you've started up X windows through ssh-agent,
you can use the ssh-add program to add your passphrase one time to the
agent and the agent will in turn pass this authentication information
automatically every time you need to use your passphrase. So the next time
you run:
ssh username@arvo.suso.org
you will be logged in automatically without having to enter a passphrase or
password. Most recent distributions will automatically start ssh-agent when
you login to X windows through a session manager like gdm (graphical login). I found
that as of this writing the following distributions started ssh-agent by default.
- Debian
- Fedora Core
- Gentoo
- SuSE
Here are distributions that suppossibly start ssh-agent by default:
- Ubuntu
- Most distributions prior to 2002 did not start it.
Don't worry if you don't see your distro listed in here. You can check if it is already running by running this command.
ps auxw | grep ssh-agent
If there is an ssh-agent process listed there, then you can just start using
it, otherwise, you should consult your distribution's documentation on OpenSSH
and running the ssh-agent.
Once you've verified that ssh-agent is running, you can add your ssh key to it by
running the ssh-add command:
ssh-add
If the program finds the DSA key that you created above, it will prompt you for
the passphrase. Once you have done so it should tell you that it has added your
identity to the ssh-agent:
Identity added: /home/username/.ssh/id_dsa (/home/username/.ssh/id_dsa)
Now you can try logging into that remote machine again and this time you will
notice that it just logs you right in without prompting you for any password or
passphrase.
To make adding your passphrase easier, you can add the ssh-add program to your
desktop session startup programs and it will bring up a prompt in X windows to
ask for your passphrase every time you login to your desktop. You should also
have the gtk2-askpass program installed. Or x11-askpass. They are the real
programs that actually prompt you for your password. ssh-add just runs them if
its not being run in a terminal. Below is a screenshot of the Gnome Sessions
Configuration dialog with ssh-add added to the startup programs.
|
Gnome Session with ssh-add program set to run and prompt for your key's passphrase |
One lesser known feature of X windows is its network transparency. It was
designed to be able to transmit window and bitmap information over a network
connection. So essentially you can login to a remote desktop machine and run
some X windows program like Gnumeric, Gimp or even Firefox and the program will
run on the remote computer, but will display its graphical output on your local
computer.
To try this out, you will need an account on a remote computer that has X
windows installed with some X windows applications. suso.org servers do not
have any such programs so you will need to either login to one of your other
workstations or another server that does have them. The key to making it work
is using the -X option, which means "forward the X connection through the SSH
connection". This is a form of tunneling.
ssh -X username@desktopmachine.domain.com
If this doesn't work, you may have to setup the SSH daemon on the remote computer
to allow X11Forwarding, check that the following lines are set in /etc/ssh/sshd_config on
that computer:
X11Forwarding yes
X11DisplayOffset 10
X11UseLocalhost yes
For some newer programs and newer versions of X windows, you may need to use
the -Y option instead for trusted X11 forwarding. Try using this option if your
X11 windows program fails to start running with a message like this one that was
for Gimp:
The program 'gimp-2.2' received an X Window System error.
This probably reflects a bug in the program.
The error was 'BadWindow (invalid Window parameter)'.
(Details: serial 154 error_code 3 request_code 38 minor_code 0)
(Note to programmers: normally, X errors are reported asynchronously;
that is, you will receive the error a while after causing it.
To debug your program, run it with the --sync command line
option to change this behavior. You can then get a meaningful
backtrace from your debugger if you break on the gdk_x_error()
function.)
Like X11 session forwarding, SSH can also forward other TCP application level
ports both forward and backwards across the SSH session that you establish.
For example, you can setup a port forward for your connection from your home
machine to arvo.suso.org so that it will take connections to localhost port
3306 and forward them to the remote side mysql.suso.org port 3306. Port 3306
is the port that the MySQL server listens on, so this would allow you to bypass
the normal host checks that the MySQL server would make and allow you to run
GUI MySQL programs on your local computer while using the database on your suso
account. Here is the command to accomplish this:
ssh -L 3306:mysql.suso.org:3306 username@arvo.suso.org
The -L (which means Local port) takes one argument of
<local-port>:<connect-to-host>:<connect-to-port>
so you specify what host and port the connection will go to on the other side
of the SSH connection. When you make a connection to the <local-port>
port, it sends the data through the SSH connection and then connects to
<connect-to-host>:<connect-to-port> on the other side. From the
point of view of <connect-to-host>, its as if the connection came from
the SSH server that you login to. In the case above, arvo.suso.org.
This is much like a VPN connection allows you to act like you are making connections
from the remote network that you VPN into.
Take a moment to think of other useful connections you can make with this type of
network tunnel.
Another useful one is for when you are away from home and can't send mail
through your home ISP's mail server because it only allows local connections to
block spam. You can create an SSH tunnel to an SSH server that is local to
your ISP and then have your GUI mail client like Thunderbird make a connection
to localhost port 8025 to send the mail. Here is the command to create the
tunnel:
ssh -L 8025:smtp.homeisp.net:25 username@shell.homeisp.net
One thing to note is that non-root users do not normally have the ability to
listen on network ports lower than 1024, so listening on port 25 would not
work, thus we use 8025. It really doesn't matter, you can use any port as long
as your email client can connect to it.
You can also reverse the direction and create a reverse port forward. This can
be useful if you want to connect to a machine remotely to allow connections
back in. For instance, I use this sometimes so that I can create a reverse
port 22 (SSH) tunnel so that I can reconnect through SSH to a machine that is
behind a firewall once I have gone away from that network.
ssh -R 8022:localhost:22 username@my.home.ip.address
This will connect to my home machine and start listening on port 8022 there.
Once I get home, I can then connect back to the machine I created the
connection from using the following command:
ssh -p 8022 username@localhost
Remember to use the right username for the machine that you started the tunnel
from. It can get confusing. You also have to keep in mind that since you are
connecting to the host called localhost, but its really a port going to a
different SSH server, you may wind up with a different host key for localhost
the next time you connect to localhost. In that case you would need to edit
your .ssh/known_hosts file to remove the localhost line. You really should know
more about SSH before doing this blindly.
As a final exercise, you can keep your reverse port forward open all the time
by starting the connection with this loop:
while true ; do ssh -R 8022:localhost:22 suso@my.home.ip.address \
; sleep 60 ; done
This way, if you happen to reboot your home machine, the reverse tunnel will
try to reconnect after 60 seconds. Provided you've setup keys and your
ssh-agent on the remote machine. ;-)
So thats great and all, but eventually you are going to want to know how you
can do tunneling without having to specify the address that you want to forward to.
This is accomplished through the -D SOCKS5 option.
ssh -D 9999 username@remotehost.net
Any application that supports the SOCKS5 protocol (and most of the big network
programs do) can forward its network connection over SSH and dynamically
forward to any hostname that you specify. So for a web browser, any URL that
you type in the URL field, would be sent through the SSH tunnel. Firefox,
Xchat, Gaim and many others all support using SOCKS5. The setting is usually
under preferences in the connection settings.
Remember, in the words of Benjamin "Uncle Ben"
Parker, with great power comes great responsibility. Just because you
can get around firewalls and use other
hosts for sending network traffic, doesn't mean that some system
administrator
isn't going to notice you.
Sometimes you don't really want to run a shell like Bash on the host you are
connecting to. Maybe you just want to run a command and exit. This is very
simply accomplished by putting the command you wish to run at the end of your
ssh connection command.
ssh username@remotehost.net ls -l /
This will probably generate the following output.
total 220
drwxr-xr-x 2 root root 4096 Nov 9 04:08 bin
drwxr-xr-x 3 root root 4096 Nov 11 09:29 boot
drwxr-xr-x 23 root root 122880 Nov 14 02:36 dev
drwxr-xr-x 68 root root 12288 Jan 10 04:03 etc
drwxr-xr-x 189 root root 4096 Jan 9 00:40 home
drwxr-xr-x 2 root root 4096 Mar 12 2004 initrd
drwxr-xr-x 9 root root 4096 Nov 9 04:07 lib
drwx------ 2 root root 16384 Sep 26 2004 lost+found
drwxr-xr-x 2 root root 4096 Apr 14 2004 misc
drwxr-xr-x 6 root root 4096 Nov 12 02:11 mnt
drwxr-xr-x 3 root root 4096 Oct 15 22:17 opt
dr-xr-xr-x 307 root root 0 Nov 14 02:36 proc
drwx------ 44 root root 8192 Jan 9 16:23 root
drwxr-xr-x 2 root root 8192 Nov 9 04:08 sbin
drwxr-xr-x 2 root root 4096 Mar 12 2004 selinux
drwxr-xr-x 9 root root 0 Nov 14 02:36 sys
drwxrwxrwt 20 root root 4096 Jan 10 06:46 tmp
drwxr-xr-x 17 root root 4096 Dec 7 2004 usr
drwxr-xr-x 26 root root 4096 Jan 10 2005 var
Then you can process the output however you want using the normal shell
conventions.
You can also do something called forced-command where you force any
login attempt to run a specific command regardless of what is specified
on the command line by the client.
To do this, you put this variable and the command you want to force
in the authorized_keys file on the remote host:
command="/usr/bin/backup" ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAvna.....
Put the variable before the start of the line for the key. There are other
variables you can use here like from="" to allow only from a specific host.
These variables can be put together seperated by commas.
SCP is basically a program that uses the SSH protocol to send files between
hosts over and encrypted connection. You can transfer files from your local
computer to a remote host or vice versa or even from a remote host to another
remote host.
Here is a basic command that copies a file called report.doc from the local
computer to a file by the same name on the remote computer.
scp report.doc username@remote.host.net:
Note how the lack of a destination filename just preserves the original name of
the file. This is also the case if the remote destionation includes the path
to a directory on the remote host.
To copy the file back from the server, you just reverse the from and to.
scp username@remote.host.net:report.doc report.doc
If you want to specify a new name for the file on the remote computer, simply
give the name after the colon on the to side.
scp report.doc username@remote.host.net:monday.doc
Or if you want to copy it to a directory relative to the home directory for the
remote user specified.
scp report.doc username@remote.host.net:reports/monday.doc
You can also use fullpaths which are preceeded with a /.
To copy a whole directory recursively to a remote location, use the -r option.
The following command copies a directory named mail to the home directory of
the user on the remote computer.
scp -r mail username@remote.host.net:
Sometimes you will want to preserve the timestamps of the files and directories
and if possible, the users, groups and permissions. To do this, use the -p
option.
scp -rp mail username@remote.host.net:
Sometimes you may have trouble keeping your SSH session up and idle. For
whatever reason, the connection just dies after X minutes of inactivity.
Usually this happens because there is a firewall between you and the internet
that is configured to only keep stateful connections in its memory for 15 or so
minutes.
Fortunately, in recent versions of OpenSSH, there is a fix for this problem.
Simply put the following:
Host *
Protocol 2
TCPKeepAlive yes
ServerAliveInterval 60
in the file
~/.ssh/config
The file above can be used for any client side SSH configuration. See the
ssh_config man page for more details. The 'TCPKeepAlive yes' directive tells
the ssh client that it should send a little bit of data over the connection
periodically to let the server know that it is still there.
'ServerAliveInterval 60' sets this time period for these messages to 60
seconds. This tricks many firewalls that would otherwise drop the connection,
to keep your connection going.
All good things come to an end. And there are many common ways to end your SSH session.
exit
logout
(Ctrl-d)
The last one is actually the user pressing the 'Ctrl' key and the letter 'd'
at the same time. These all are ways of terminating the SSH session from the
server side. They usually exit the shell which in turn logs you off the machine.
What you may not know, is that there is another way to close an SSH session.
This is useful if you lose connectivity with the machine and you have no way of
ending your shell session. For example, this happens momentarily if you stay
logged into a machine while it is shutdown. SSH has its own command line
escape sequences. These can be used to end connections, create new port
forwards or list current ones and a few other functions. To end a connection
even when you don't have a command prompt, type return twice (for good measure)
and then the sequence '~.'. That's a tilde followed by a period.
(RETURN) (RETURN) ~.
This will terminate the SSH connection from the client end instead of the server end.
Happy SSH'ing!
- Original document, graphics and examples by Mark Krenz (mark@suso.org)
- Thank you to the following people for sending corrections:
- Zake Stahl (Several corrections)
- Christopher Mylonas (noticing that MySQL should be 3306, not 3066)
Modified: 2007-06-26 14:30:36
|