Skip to content

Documentation SSH introduction

scs edited this page Jul 13, 2012 · 2 revisions

Table of Contents

SSH introduction

This guide gives an introduction to using SSH on the leanXcam as well as some general hints about how to make your life with SSH more easy.

All examples in this guide are demonstrated using the OpenSSH 5.1 ssh client command in conjunction with the Dropbear SSH server on the leanXcam. Most of what is shown here can be done with most SSH clients and servers but commands/usage may differ. A later version of this guide may include descriptions for other software, especially GUI based ssh clients like Putty.

The SSH protocol

SSH stands for secure shell and is a protocol which is primarily used to gain shell access on a remote machine in a secure manner, but other uses include tunneling, connection proxying and file transfer.

The current version of the SSH protocol is version 2. By default, it uses AES for encryption and RSA for key exchange and authentication.

Further Reading

This guide gives just an introduction to the different functions and features of SSH. Anything more specific can be found in the documentation of your SSH distribution. On a standard Linux installation these can be accessed by typing man ssh and man ssh_config.

 NAME
      ssh -- OpenSSH SSH client (remote login program)
 
 SYNOPSIS
      ssh [-1246AaCfgKkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec] [-D
 ...

Opening a connection

Before SSH is of any use, a connection to an SSH server has to be opened. From the console, this is done with the ssh command followed by the IP address or domain name of the server you want to connect to.

 $ ssh example.com
 The authenticity of host 'example.com (2001:db8::5)' can't be established.
 RSA key fingerprint is 96:89:25:00:f3:6f:ce:56:99:f0:84:2e:20:5b:7d:4e.
 Are you sure you want to continue connecting (yes/no)? 

Server Authentication

The first thing that happens when a connection is opened, is that the remote host (the server) has to authenticate itself with the client (your machine). This is done to ensure that you are connected to the machine intended to so you don't send your password some rouge server.

Server authentication uses public key cryptography and so effectively prevents man in the middle attacks. The first time of course, your machine doesn't know the server and asks you wether the fingerprint of the public key used by the server is correct. If you are in a safe environment like a closed company network, you can safely let ssh proceed and store the public key in it's database. The key is compared on consequent connections so the user may be warned when the public key doesn't match.

 $ ssh example.com
 The authenticity of host 'example.com (2001:db8::5)' can't be established.
 RSA key fingerprint is 96:89:25:00:f3:6f:ce:56:99:f0:84:2e:20:5b:7d:4e.
 Are you sure you want to continue connecting (yes/no)? yes
 Warning: Permanently added 'example.com' (RSA) to the list of known hosts.
 Password:
 Last login: Thu Jan 22 09:59:10 2009 from localhost
 guru@example$ 

In case of a public key mismatch the following will be printed and ssh will refuse to open a connection:

 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 @    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:89:25:00:f3:6f:ce:56:99:f0:84:2e:20:5b:7d:4e.
 Please contact your system administrator.
 Add correct host key in ~/.ssh/known_hosts to get rid of this message.
 Offending key in ~/.ssh/known_hosts:36
 RSA host key for localhost has changed and you have requested strict checking.
 Host key verification failed.

If you know that the RSA keypair of the remote host has changed, perhaps because it has been newly setup, then you can remove the old key from the public key database located in ~/.ssh/known_hosts and then let ssh add the new one to the database:

 $ favorite-editor ~/.ssh/known_hosts
   [ remove the line containing the host name or IP address ]
 $ ssh example.com
 ...

User Authentication

Password Authentication

After a connection has been opened and encryption keys have been exchanged, the user has to authenticate itself to the server. This is normally done either through the password of the remote account or public key authentication.

If you are using a password, the server will ask you as soon as the connection has been opened. After you've entered the password correctly and pressed return, the remote server will give you a login shell.

 $ ssh example.com
 Password:
 Last login: Thu Jan 22 10:28:17 2009
 guru@example$ 

Public Key Authentication

Another way is to use an RSA keypair and upload the public key to the remote host. This enables you to log in to the remote server without typing a password each time.

To do this, you first have to generate an RSA keypair. This is done using ssh-keygen:

 $ ssh-keygen -t rsa
 Generating public/private rsa key pair.
 Enter file in which to save the key (/Users/michi/.ssh/id_rsa): 
 Enter passphrase (empty for no passphrase): 
 Enter same passphrase again: 
 Your identification has been saved in test.
 Your public key has been saved in test.pub.
 The key fingerprint is:
 86:62:77:ad:0f:ff:c6:c6:5d:a2:a6:c8:0d:9a:d1:dc michi@localhost

If you'll only generate one key you can use the default file ~/.ssh/id_rsa to save the key to. If you do not want to let anyone having physical access to your machine also use your keys, you should encrypt them with a passphrase. It is wise to do this on a laptop or another machine where you can't trust all the people having access to it.

Now you'll just have to upload the public part of the keypair to your home directory's .ssh/authorized_keys file on the remote host. If the ssh-copy-id script is installed on your system, you may use it to upload you public key to the server:

 $ ssh-copy-id -i ~/.ssh/id_rsa.pub example.com

This loads the public key from the file ~/.ssh/id_rsa.pub generated earlier and appends it to the file ~/.ssh/authorized_keys on the remote host.

If you do not have this script installed you can upload the public key manually. For this you can display the public key part of the keypair on your local machine:

 $ cat .ssh/id_rsa.pub
 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAqtiNXdJ9WyS2InjrA4KpWVwxJ4hn/L/xjTIvSunukV4q
 jgmOVdPkOcVom7dmvaHxFUgwlYsFu3NSbrJO8/ovcpgirDuKV3t99d66VPIIJRk5g+nqTy10Evpsduu0
 1jGNNfqlpmdMP89XKBrTxqRv0DxAoDm2x23LmgnXHaHfKrP7sfOzzeu8/bC8b5lenZHGulCWhlTCGGeA
 18FsdzTGMb20T5SkfgUkfDfSyBqwuFoeRBG5efPq9rV9Tz4R7rGWIpiJNsln9mwY8afxUpvWki0e3mdl
 F6UZKxoSvaWL4JsCutIO9By/4RSmYtQspjw8OAVf2uKfcxbatgCW7uMZQQ== guru@localhost

Now you can copy this string, log into the remote account with your password and append it to the file ~/.ssh/authorized_keys. To close the input of cat, you can press control-D:

 $ ssh example.com
 cat >> .ssh/authorized_keys
  [ paste the clipboard ]
 ^D

Now that you've done this, you should be able to log in to the remote host without entering your password.

ssh-agent

If you've chosen to use a password to encrypt your private key used by public key authentication, ssh asks for you password each time you log into the remote host, which sort of defies it's purpose. It is still more secure this way, but it's not more convenient.

To solve this problem, you can use ssh-agent on your local machine. ssh-agent acts as a background daemon into which you can load your decrypted ssh keys which will then be used whenever you open an ssh connection.

Most Linux and Unix distributions like Debian, Ubuntu, Fedora or Mac OS X have ssh-agent enabled by default. To use it you can use ssh-add to load your private keys into ssh-agent. ssh-add will ask for the passwords used to encrypt the private keys found in your ~/.ssh/ folder:

 $ ssh-add
 Enter passphrase for /Users/michi/.ssh/id_rsa:

This stores the decrypted keys in ram as long as you're logged in so they can be used for logging in on remote hosts. To purge the keys from ram you can use ssh-add:

 $ ssh-add -D

This will explicitly tell ssh-agent to forget all private keys is has stored so you will have to add them again with your password bevore they can be used again. This is normally not needed but can be used if you have to leave your machine unattended but can't lock it from unauthorized access.

Logging in as a Different User

Normally, ssh will use your local user name to log in to the remote host. If you want to log in as under a different user name on the remote machine, you can prepend it to the host name or IP address separated by an at sign:

 $ ssh user@example.com
 Password:
 user@example.com$ 

Now the ssh server will try to authenticate with a different user account using a password or your private keys.

Proxying and Tunneling

TCP Tunneling

SSH support forwarding of TCP connections from or to the remote host over the encrypted connection. This is useful if you want to connect from your local machine to a third machine, but the connection should originate from the remote machine you're connecting to via SSH. This may be needed if you need to connect to a machine which is behind a firewall with a protocol which is filtered by the firewall or you are behind a firewall yourself and can only connect to the outside via SSH.

To forward a connection from your local machine to the remote host, use the -L option to ssh:

 $ ssh -L 8080:google.com:80 example.com

With this command, while you are connecting to example.com, the SSH client opens a TCP socket on the local machine on port 8080 and whenever a connection to that socket is made it is forwarded to the remote host over SSH, from where a connection to google.com. You can see what's going on by using the -v option to ssh at the same time:

 $ ssh -v -L 8080:google.com:80 example.com
   [ ... ]
 debug1: Local connections to LOCALHOST:8080 forwarded to remote address evil-empire.com:80
 debug1: Local forwarding listening on ::1 port 8080.
 debug1: Local forwarding listening on 127.0.0.1 port 8080.
   [ ... ]

This means that the local socket only listen for connections from this machine. This is done by attaching the socket to the loopback device (::1 for IPv6 and 127.0.0.1 for IPv4). If you want to allow connections from other machines to be forwarded over the same connection, you can prepend the argument to the -L option with a colon:

 $ ssh -v -L :8080:google.com:80 example.com
   [ ... ]
 debug1: Local connections to :8080 forwarded to remote address google.com:80
 debug1: Local forwarding listening on :: port 8080.
 debug1: Local forwarding listening on 0.0.0.0 port 8080.
   [ ... ]

It is also possible to forward connections form the remote host to the local machine. This done using the -R option instead:

 $ ssh -R 8080:google.com:80 example.com

This opens a TCP socket that listens on port 8080 on the remote host and forwards connections to that socket to the local machine which then forwards them to specified host and port.

SOCKS proxy

ssh may also use the SOCKS protocol to allow client applications to open arbitrary TCP connections from the remote host. To open a SOCKS server port on your local machine, use the following command:

 $ ssh -D 9000 example.com

This allows applications supporting the SOCKS protocol to open TCP connections as if they originated from the remote host.

X forwarding

SSH may also be used to forward X connections. This enables you to use graphical programs on the remote machine but have the user interface on your local machine:

 $ ssh -X example.com
 guru@example.com$ gnome-terminal

File copying and remote command execution

Copying files with SCP

scp is another command line tool which may be used to copy files and directories to or from a remote machine vie SSH. The usage is pretty much the same as for cp with the addition that the source or destination paths may contain a host name prepended to the remote path with a colon.

This copies a file to a remote hosts temporary directory:

 $ scp file example.com:/tmp/file

If you omit the slash after the colon, the path will be relative to your home directory:

 $ scp file example.com:file

If you name an existing target directory as the destination, the file will be copied under its original name into that directory:

 $ scp file example.com:dir/

You may also add a used to the host name in the same way as with ssh:

 $ scp file guru@example.com:/etc/

If the host name is prepended to the source file name, that file is copied from the remote host to the local target path:

 $ scp example.com:file file

A single dot as the local target path specifies the current directory:

 $ scp example.com:file .

A directory may be copied by specifying it as the source and adding the -r option to the command line:

 $ scp -r dir/ example.com:

To preserver the files metadata like access modes and times, use the -p option. This is useful to copy an executable file to a target machine and having it's executable bit set on the remote copy.

 $ scp -p app_target example.com:/bin/app

Remote command execution

Sometimes it is useful to log in to a remote machine just to execute a single command, e.g. inside a script or makefile that is run locally or to pipe output from or to a local command to or from the remote command.

A remote command to be run on the remote host is simply put at the end of the ssh command line:

 $ ssh example.com ls
 dir
 file

The SSH connection is automatically closed after the command on the remote machine finishes. The output of the command can be used like the output of a local command:

 $ ssh example.com cat /proc/meminfo | grep Swap
 SwapCached:      66900 kB
 SwapTotal:     2650684 kB
 SwapFree:      2411120 kB

Note that in the above example, the grep command is run locally while the cat command is run on the remote machine. To use special character that are special to your local shell, you will have to escape them with backslashes:

 $ echo *
   <<local files>>
 $ echo \*
   <<remote files>>

To have special characters interpreted neither by your local nor the remote shell, they have to be escaped twice:

 $ echo \\\*
 *

SSH Configuration

SSH allows a great deal of options to be configured on a global or per-host basis. This allows you to specify options that should be used whenever you connect to a certain host without having to type it on the command line each time.

The user specific SSH configuration file is located at ~/.ssh/config. Create or edit it with your favorite text editor. The configuration file contains a global set of configurations and a set of per-host sets of configuration. The global set precedes any Host declarations.

A Host declaration is the word Host followed by a set of domain names and IP addresses separated by spaces. Globbing is allowed in domain names and IP addresses using the * and ? characters. All declarations that follow a Host declaration are only used when connecting to hosts that are selected by that declaration, up until the next Host declaration.

The options I use when developing for the leanXcam are User and StrictHostKeyChecking. User allows you to specify another username as your current login name to be used by default when connecting to a group of hosts.

StrictHostKeyChecking may be set to one of yes, ask or no and controls what should be done if public key stored in the public key database mismatches or is missing. ask is usually the default and lets you add missing public keys to the database but barfs at you if there is already another key in the database. yes is even more restrictive and makes you add missing public keys to the database manually. no makes ssh still check the public key of the remote host but will only print a warning if they mismatch and still continue. This should only be used when a host inevitably often changes host keys and should only be enabled for these hosts.

A configuration file may look like this:

 Host 192.168.1.10 192.168.11.*
     User root
     StrictHostKeyChecking no

This allows me to connect to the cameras at 192.168.1.10 or any address in the 192.168.11.0/24 subnet as root just by typing ssh ''&lt;ip-adress&gt;''

Clone this wiki locally