December 5, 2005

CLI Magic: More on SSH

Author: Joe 'Zonker' Brockmeier

We've covered SSH before in CLI Magic, but this week let's look at some additional SSH features that new users might not be aware of. For the purpose of this article, we'll be looking specifically at OpenSSH, but many of these features apply to other SSH variants as well.

SSH is the best way to establish a secure connection to a remote networked machine. Whether you want to transfer files, encrypt traffic, or just log in to a remote machine, SSH is the way to go.

Logging in without passwords

Let's start with one of the basics. If you log into a remote machine frequently, you might be tired of typing your password over and over again. You can set up SSH so that you can authenticate without typing a password.

First, you'll need to create an authentication key for SSH. This will actually consist of a key pair: a private key and a public key. To create your keys, run the command:

ssh-keygen -t dsa

You will be prompted for the file to save the key in. It's usually OK to accept the default of /home/user/.ssh/id_dsa. Then you'll be asked to enter a passphrase. Since we want to be able to log in with no password, just press Enter. You'll be prompted to enter the same passphrase, so press Enter again, and you should see a message like:

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:
xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx user@host

Note that the public key is saved in /home/user/.ssh/id_dsa.pub. We're going to copy that to the remote machine. Make sure to copy the id_dsa.pub file, and not the id_dsa file. The id_dsa.pub file is public, so it's okay to distribute it to your remote computers. The id_dsa file is private, and should not be distributed:

scp id_dsa.pub user@host:/home/user/

Now, we need to add this key to the file authorized_keys2 under the .ssh directory. Log into your remote machine. If the authorized_keys2 file doesn't exist yet -- if you haven't set up any authorized keys before -- run cp id_dsa.pub .ssh/authorized_keys2. If it does exist, or you're adding a second key, use cat id_dsa.pub >> .ssh/authorized_keys2 instead.

Finally, make sure that the file has the correct permissions. It should be user read/write, and read-only for everyone else. If the permissions are not correct, set them correctly using chmod 644 .ssh/authorized_keys2.

Having an authorized key is also very useful for scripts. Without a key, you'd need to enter your password when using rsync over SSH to transfer files to a remote host (or vice versa). That's pretty inconvenient when you've got a cron job set to run a script every morning at 3 a.m. that uses rsync over SSH to transfer files.

Disable root login

While we're configuring SSH, let's implement a good security practice. Some distributions disable remote root login by default, while others do not. It's a good idea to deny root logins via SSH. It's better to log in as a non-privileged user and run commands using sudo, or to log in as a non-privileged user and escalate to root when necessary.

It's simple to change this setting if your distro does allow root logins. You'll need to edit the file /etc/ssh/sshd_config, and look for the following line:

PermitRootLogin yes

Simply change that to PermitRootLogin no and restart sshd. That's all there is to it. Don't worry about restarting sshd -- it won't disconnect users that are logged in via SSH.

Executing commands on a remote machine

If you just want to run a quick command on a remote machine, it can be faster to just run the command and skip getting a shell on the remote machine. There's no need to log in if you just want to make a quick edit to a file, or just run one command, right? SSH allows you do to this pretty easily. The syntax is ssh user@hostcommand. For instance, if you want to restart Apache on a remote machine without logging in, you could run the following:

ssh user@webserver sudo /etc/init.d/apache2 restart

Note that you can omit user@ if your username is the same on the local machine and the remote machine.

This is a quick and easy way to restart services or run other one-line commands without needing to establish a remote shell.

Encrypting X sessions

One of the nifty things about the X Window System is its client/server architecture, which allows you to run a program on a remote host, and display the program on the local host. For example, I can run Gaim on my main workstation, but actually display the Gaim windows and such on my laptop, if I use X forwarding. (This works best over a local network -- if you're connecting to your home computer over the Internet from work, the performance is probably going to be pretty bad.) You can forward X traffic without using SSH, but SSH has the added benefit of encrypting the connection. To do this, just add the -X option:

ssh -X hostname

This will open a shell on the remote host, and forward X traffic to your local machine. It's worth mentioning that this isn't Linux-specific either. For example, if you have a Mac OS X machine with X installed, you can run an application on a Linux box and display it on your Mac. The same is true for pretty much any Unix-type OS with X installed.

Port forwarding

Here's another nifty SSH feature. You already know it's a very bad idea to send important data over the network unencrypted. But what if you want to work with a remote service that doesn't offer encryption by default? Or what if you'd like to reach a machine that's behind a firewall? Using SSH's port forwarding features, you can do all this and more.

First, you can forward a port on your local host directly to a port on a remote host. For example, let's say I'd like to be able to use a MySQL GUI application on my local machine to work with MySQL on my Web server. All I need to do is run the command:

ssh -f -N -L 3306:localhost:3306 username@webserver

Let's break that down a little. The -f option tells ssh to go into the background, while the -N option tells ssh not to execute any remote commands -- like a shell. The -f -N options are useful when forwarding ports, especially when you're using this in a script, unless you want to open a shell on the remote host in addition to forwarding a port.

The -L option tells ssh to forward a port from the local host to a port on the remote host. In this case, both ports are 3306, so any traffic directed to port 3306 on my local machine will be directed to port 3306 on the Web server. Note that you will need to be logged in as root to forward the privileged ports below 1024.

Now, if I fire up my MySQL GUI client and point it at localhost port 3306, it will actually be communicating with MySQL on the Web server over an encrypted connection.

But that's not all! What if there's a firewall between my Web server and me, so that I can't connect directly to the Web server via SSH? Assuming you're working with a Linux firewall, or other firewall that's running SSH, you can still connect. This time, let's try forwarding a local port to port 25, so that I can connect to SMTP over a secured connection. Here's how it's done:

ssh -f -N -L 2205:webserver:25 username@firewall

The first argument, 2205:webserver:25 tells ssh to forward traffic from local port 2205 to port 25 on host Web server. Because I've specified firewall as the host to forward traffic through, by using username@firewall, the traffic will pass through that host.

There is a drawback here, however. Traffic from my workstation to the firewall will be encrypted, but traffic between the firewall and the Web server will not.

Last, but not least, you can go the other direction and forward traffic from a remote host to your local host. To do this, use the -R option instead of the -L option, like this:

ssh -f -N -R 8081:localhost:8080 webserver

This will forward all traffic from port 8081 on the host webserver to port 8080 on the local machine. Note that you need to be a privileged user on the remote host to open privileged ports.

Summary

This is just a short list of some of SSH's more useful features. Be sure to check the ssh man page for more, as well as the OpenSSH FAQ. If you have favorite SSH trick or tip, share it with us in the comments.

Click Here!