Published on September 10, 2012 by Silviu-Mihai Popescu
Tagged: SSH, security, remote access

This is an article aiming to familiarize the reader with the features and benefits of using Secure Shell (SSH), particularly with the OpenSSH implementation. SSH is an application level protocol used for secure data communication, whether that means remote shell access, command execution, file transfer and some other aspects described in this article. It was meant to be a replacement for existing insecure remote shell protocols such as telnet, rsh and rexec which send information in plaintext, including usernames and passwords.

SSH uses public-key cryptography for authentication purposes. In short, this works like this: each user has a pair of keys, one public and one private. They are mathematically related, but it is computationally infeasible to derive one from the other. The public key is … well, public! Anyone can get that, and they would use it to encrypt messages. The private key, however, is (or should be) accessible only by the user, and used to decrypt incoming messages.

The two parties of a SSH communication are the server and the client. The server usually runs on port 22, but that is not a requirement, and the client will use a random available port on the client machine.

Setting up SSH

The simplest way to install a SSH client is with your package manager. On Debian-based distros, it would be something like:

$ sudo apt-get install openssh-client

After that finishes, you can generate a pair of cryptographic keys using the command ssh-keygen:

$ ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/home/silviu/.ssh/id_rsa): test
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:
eb:8b:a9:c5:22:46:c8:36:d9:c1:40:67:e1:b3:ec:66 silviu@keter
The key's randomart image is:
+--[ RSA 2048]----+
|.o +.            |
|  *              |
|   =             |
|..+ +            |
|.=.+    S        |
|..o  .   .       |
|  oE. o .        |
| .o. o +         |
|    ..o o.       |
+-----------------+

The lines ending in colon represent where you have to provide input. You may have noticed the word passphrase. This is used to lock the private key with a string that you choose. In order to use that key pair, the passphrase is provided and checked locally, not transmitted over the network. Please do not mistake this for the remote password.

The default size for the RSA key is 2048 bits. You can change this and other aspects by checking the manual page for ssh-keygen,

On the server you would install the openssh-server package:

$ sudo apt-get install openssh-server

Among other things, this should put a script in /etc/init.d/ssh and start the server. Depending on whether you distro uses inittab or upstart, you can check if the server is running with the following commands:

$ /etc/init.d/ssh status
$ service ssh status

You can start the server by passing start as the last argument in those commands, but you’d also need root access to do that.

And now you can test the installation from the client like this:

$ ssh my_user@my.server.com

By default, this will try to connect to the specified server on port 22, using the default key at ~/.ssh/id_rsa. You can change this behaviour by a quick glance at the manual page. Also, if you specified a passphrase during the generation of the key, you will have to provide that and the remote password for the user you are trying to log on as. You can specify the IP instead of the DNS name for the server.

You can also run just one line of commands, such as:

$ ssh my_user@my.server.com 'ls -la; apt-get moo'

So this would be the basic usage of SSH. You can do a lot just with what is written up to this point, and you might be tempted to close the article and just get back to what you wanted to do in the first place. But seriously, you would be missing a lot of the cool stuff SSH can do. Just bear with me for a moment and you will end up being more productive with SSH.

Copying files remotely

You can use cat and pipes to copy a file remotely:

$ cat test.txt | ssh -e none user@host 'cat > remote_test.txt'

The -e option disables escape characters so that you can send any bytes that your file may contain. The rest is a trick: the output of the remote cat is redirected to a file, but the input comes from the output of the first half of the pipe, which is the contents of the file you want to transfer. Neat, right?

However, that solution is kind of tedious. Instead you would better use scp, which comes with the package:

$ scp test.txt user@host:remote_test.txt

Notice that colon after host because it is critical. If you did not want to rename the file you would have just used user@host:. The colon tells scp the destination is a remote location. Otherwise, you would just copy test.txt to a file named user@host.

Also, the path after the colon is relative to the home directory of the remote user.

There is also the sftp utility which provides a FTP-like interface.

Passwordless authentication

So, up until now you have connected via SSH by providing your password, maybe even a passphrase. You can probably see by now that this is troublesome and can be a major drawback if you would like to make a script using SSH. How about we ditch that remote password?

To do this, you would basically need to append the contents of your public key to a file located at ~/.ssh/authorized_keys on the server.

Luckily for you, most SSH packages provide an utility called ssh-copy-id that does just that. So you would just run:

$ ssh-copy-id user@host

Next time you will try to log on to that account, you will not be prompted for your password.

As an exercise, knowing what you have read thus far, figure out two more ways of achieving the same result, just in case you do not have ssh-copy-id.

Config file

If you are going to use SSH with several servers, with various settings and different key pairs you will soon have to enter something like this:

$ ssh -i ~/.ssh/private_key_file10 -l user -p 2222 -o "ForwardX11 yes" the.mother.of.all.servers.com

Now that is an extremely long and ugly line with no particular purpose but to illustrate the complexity of ssh commands. Some who have read the manual page know that X forwading can be achieved by passing -X.

Anyway, an initial approach to bypassing this issue is by using aliases of bash functions. But those are limited in functionality and basically you are just placing that ugly command somewhere else. Not cool, not cool.

You can put settings on your local computer in ~/.ssh/config. The full list of options, and their possible values, is available via man ssh_config.

Here is a modified version (for security reasons) of my config file:

Host compilers
	User ubuntu
	Hostname ec2-50-17-91-154.compute-1.amazonaws.com
	IdentityFile /home/silviu/.ssh/amazon
Host *.cs.pub.ro
	User you_d_like_to_know
	IdentityFile /home/silviu/.ssh/cs
Host so2-lin
	User root
	Hostname 192.168.56.101
	PubkeyAuthentication no
Host so-lin
	User student
	Hostname 10,0.2,15
	PubkeyAuthentication no
Host ubuntu-dev
	User silviu
	Hostname 172.16.48.129
	PubkeyAuthentication no
Host github
	User git
	Hostname github.com
	PreferredAuthentications publickey
	IdentityFile ~/.ssh/github

Now you could put all those options for that long command above in a organized manner, and it will work with all SSH-related utilities, even scp, with the options you specified:

$ scp something mother:

Local port forwarding

Let’s assume that your employer has banned Facebook, so that people might actually do something useful.

Let’s also assume that you have a SSH server that you can reach and has no filtering for Facebook.

You could do something like this

$ ssh your.server.com -L 80:facebook.com:80

This achieves the following effect: any connection to port 80 on your machine is passed, via your remote machine, to port 80 on facebook.com, which is the standard port for HTTP.

After that, set an entry matching facebook.com to 127.0.0.1 in /etc/hosts and procrastinate.

But first, take a moment to come up with a section in your config file that does this forwarding. (Hint: LocalForward)

Conclusions

So now you have a set of things you could do with SSH that can make you be more productive (or not if you just read the last part). I hope you found the article useful.

If you want to know about more things you could do with SSH here is a list of terms you might want to search the web for:

  • SSH tunnels
  • SSH remote port forwarding
  • Set up a SOCKS proxy for Firefox with SSH
  • sshfs
  • SSH master sessions
  • ssh-agent and ssh-reagent

comments powered by Disqus