Linux

Optimize OpenSSH on Linux for better networking and security

Learn how to take advantage of some of the advanced features of OpenSSH that can simplify and extend its use.

If you run Linux in a networked environment and don't yet know what OpenSSH is, you have no idea what you’re missing. If you use telnet and still don't know what OpenSSH is, then you are in dire need of a little education. OpenSSH is an open source and free implementation of the SSH (Secure Shell) protocol. With it, you can connect to computers across a network or the Internet in a completely secure fashion, with everything from passwords to the text you type encrypted. If you've been using telnet and have never given OpenSSH a try, you need to stop right now and try it.

This Daily Drill Down, however, is not about how to install OpenSSH, or even about the basic uses of OpenSSH. While in its most basic form it can be used for secure remote logins and secure copying of files to and from remote computers, there is far more that OpenSSH can do. In this Daily Drill Down, we will explore some of the more advanced features of OpenSSH and discover how to make using it simpler and more powerful.

Key-based authentication
Typically, when you connect to a remote site, you need to supply a password. This is true for remote logins and for copying files securely. The password is required to authenticate you so that the remote system knows that you are who you say you are, and that you have appropriate access to the system.

OpenSSH also uses a key-based method of authentication, which means that you can make use of password-less connections to the remote machine. If you connect to a remote system often, this may be the best method for you to make use of, because it offers the benefit of fewer keystrokes and is just as secure as using password authentication, especially if you use strange and convoluted passwords (which you should). Using this method, you only have to enter your password once, at the beginning of your session.

The first step is to create your private and public keys. To do this, simply run the command:
ssh-keygen

This will work for any OpenSSH or SSH 1.x server. If the remote server uses SSH 2.x, you will want to run this command instead:
ssh-keygen -d

Because SSH 2.x uses a different algorithm, it will create a DSA key instead. If you connect to various servers, some using OpenSSH and others using SSH 2.x, you can run both commands. Since both keys are saved in different files, they can peacefully coexist. SSH 1.x and 2.x are both commercial implementations of SSH and are not free, unlike OpenSSH itself.

Once you have completed this command, you will have a file called /home/user/.ssh/identity and another called /home/user/.ssh/identity.pub. The first is your private key, and the second is your public key. If you use the -d option, these files will be /home/user/.ssh/id_dsa and /home/user/.ssh/id_dsa.pub.

Now that you have your keypair generated, you need to secure your private key. (If your private key ever becomes compromised, you will have to recreate your private key, so take pains to ensure it does not become so.) The easiest way is to change the permissions of the file so they are readable and writable only by you and no one else. Run the following command to change the permissions:
chmod 600 ~/.ssh/identity

This will make sure that only the user who created the keypair has access to the file. The next step is to distribute your public key to the servers you will be connecting to via SSH. This is easily done since you should already have access to the remote system. Simply copy your new ~/.ssh/identity.pub to the remote system and place it into the ~/.ssh directory on the remote system. For instance, if your user name is joe, but on the remote system it is joedoe, you will have to copy /home/joe/.ssh/identity.pub on the local system to /home/joedoe/.ssh/authorized_keys on the remote system. Once you have done this, you must make the authorized_keys file world-readable and writable only by you by doing:
chmod 644 ~/.ssh/authorized_keys

on the remote machine. Now, the authorized_keys file can hold more than one public key. If you connect to the remote machine by multiple computers, you can include the public key for each user on those computers in the remote authorized_keys file by inserting the contents of the local ~/.ssh/identity.pub file into it.

Once this is completed, you are almost ready to begin. The next step is to make use of the ssh-add and ssh-agent programs. These programs will allow you to store your key in memory once you have entered the passphrase that ssh-keygen prompted you for. If you did not enter a password when you generated your keypair, you will still need to run these programs; you simply won't be asked for a password. The first thing you will need to do is run the ssh-agent program using the shell's eval command. The ssh-agent program is an authentication agent that will run in the background and seamlessly handle requests to connect to remote sites. Run the following command:
eval $(ssh-agent)

You will then see a message that displays the ssh-agent's PID number. Once that has been printed to the screen, run the ssh-add program:
ssh-add

This program must be run in the exact same terminal that you ran ssh-agent in. It will load the key into memory and ask you for your password. Now you will be able to start SSH sessions from that terminal alone without ever having to enter your password again (until you close or log off the terminal, of course).

If you want to have this capability in all terminals you open, you will need to add the eval command to your X startup files: ~/.xinitrc if you start X from the console, or ~/.xsession if you boot directly into X. Then you can run ssh-add from any terminal, and any future terminals you open during that login will be likewise authenticated. If you want to list the key(s) that are currently stored in memory, you can do so using:
ssh-add -l

and you can also remove an identity from the system memory by using:
ssh-add -d

Port forwarding
OpenSSH also provides a method to tunnel protocols securely using port forwarding. What this means is that you can create a secure connection to a remote computer and transfer files, mail, or any other TCP/IP service through the SSH connection by connecting to a local port which travels through the SSH "tunnel." At the remote end, they will connect from the secure SSH port to the unencrypted (normal) port, and all data will be encrypted. This entire operation is seamless for your client connections. Of course, the remote server must also run SSH in order for this to work. You can easily determine whether the remote system runs SSH by either trying to use the SSH client to connect to it or by telneting to the standard SSH port (22) on the remote machine. If the connection is permitted, the remote server runs SSH. If it is denied, the remote server does not run SSH, and you will not be able to connect to it securely.

The syntax for port forwarding is as follows, and it may seem a little complicated at first glance:
ssh -f [user@remote] -L [localport]:[fqdn-of-remote]:[remoteport] [command]

Let's take a look at a commonly used example. Many people use SSH tunneling to retrieve their POP3 mail from their ISP or other system. By using SSH tunneling for this, you prevent people from sniffing your POP3 password, and you also prevent anyone from sniffing the contents of your e-mail. OpenSSH also provides an option to compress data, which may help you get your mail faster. To use compression, use the -c command-line option.

Let’s assume for a moment that your POP3 username is joe and that your POP3 account is located at mail.somehost.com. To establish the tunnel, use the following command:
ssh -f -c joe@mail.somehost.com -L 1110:mail.somehost.com:110 sleep 10

This command will start the port forward command with compression enabled. Our login on the remote machine, mail.somehost.com, is joe, so we provide that as the username and the fully qualified domain name for the remote host name on the command line. We then create a tunnel from port 1110 on the localhost to port 110 (the POP3 port) on the remote host. We then run the command sleep 10 to keep the connection alive long enough for the mail client to connect to the remote server. You can basically put anything here that produces some activity, such as using tail on a log file, so that some data keeps the connection alive.

Once you execute the command, you will be prompted for your password on the remote system. Once you've done this, you can then point your mail client to port 1110 on the localhost to retrieve your e-mail. To take the example further, let's take a quick look at the fetchmail program and see how you would have to configure fetchmail to make use of this SSH tunnel.

If you use fetchmail, you will be aware of the ~/.fetchmailrc configuration file that it uses. Expanding upon the example above, let's look at a sample ~/.fetchmailrc file:
poll localhost with protocol pop3 and port 1110:
preconnect "ssh -f -c joe@mail.somehost.com -L 1110:mail.somehost.com:110 sleep 10"
password private;


And that's it! What this does is tell fetchmail to connect to port 1110 on the local system. The preconnect command tells fetchmail to execute the command in quotes prior to making the POP3 connection to download mail. The last line provides the password for the POP3 account.

To take this one step further, combine this with the ssh-agent and ssh-add commands we looked at previously, and you will only need to enter your password once. Or you can use a BASH script similar to this, which will run fetchmail every five minutes to download mail:
#!/bin/sh
ssh-add
while true; do fetchmail --syslog --invisible; sleep 5m; done


Then you can run the following command when you log in to your system:
ssh-agent ~/bin/getmail

if you saved the above script as the executable file ~/bin/getmail.

Now let's take a look at another use for SSH tunneling. Suppose you wanted to run X applications from a remote server and have them displayed on your local computer. This is easily done with OpenSSH as well and provides a secure way to use remote applications. The first step is to log in to the remote machine and create a file called ~/.ssh/environment, which contains the following line:
XAUTHORITY=/home/user/.Xauthority

The /home/user directory is, of course, the home directory of the remote user. Once you have done this, close the session and then start another session using:
ssh -f -x -l [user] [remote host] xterm

This will open up an xterm from the remote machine onto your local computer. You can do this with any application you like, such as Netscape, xchat, or an administrative program. As long as you have permission to execute the program, you will be able to run it in this manner.

Further configuration options
You can also configure OpenSSH to make it easier and more convenient for you to use. There are three ways that you can pass options to OpenSSH, and they are, in order of priority: command line, user configuration, and system-wide configuration. By default, you will not have a user configuration file, so you may want to copy /etc/ssh/ssh_config to ~/.ssh/ssh_config. To change system-wide configuration options, simply edit the /etc/ssh/ssh_config file.

The configuration file is read from top to bottom. It uses matching, so the first configuration option that matches the situation is the one that will be used. Because of this, your specifics should be listed first and the more general options specified last.

Let's look at a quick example: Assume that you have an account on somehost.com as the user joe. You're using the one-time password authentication method discussed previously, and you want to simply type sh instead of somehost.com whenever you connect to the remote machine. You also want to be able to use X11 forwarding to run remote applications on your local machine. However, you still want to keep the paranoid settings for every other host, which are the default in the configuration file. You might edit your ~/.ssh/ssh_config file to look like this:
Host *sh
HostName somehost.com
User joe
ForwardAgent yes
# Be paranoid by default
Host *
ForwardAgent no
ForwardX11 no
FallBackToRsh no


Now all you need to do is type:
ssh sh

instead of:
ssh joe@somehost.com

to connect to the remote machine. OpenSSH will look up the host name in the configuration file, use your user name to log in, and authenticate using your key. Simple, isn't it? Connections to all other machines will continue to use the default paranoid settings, which will protect you from untrusted hosts.

Conclusion
There are a number of shortcuts you can take with OpenSSH without reducing security. Using key-based authentication is a simple, yet secure, means of making life a little easier. Creating secure tunnels with SSH also has many advantages. You can use tunneling for anything from POP3 to SMTP, and even use it for FTP and HTTP connections. Creating a tunnel for FTP is unnecessary, however, as you can use scp (secure copy) to transfer files or use sftp, a secure FTP client and its associated secure FTP server, to make use of SSH-enabled FTP.

With all the obvious advantages of using OpenSSH, using other insecure options should be considered a thing of the past. OpenSSH is more than a simple secure shell. It can be used to secure many aspects of your system and generally make life easier and let network administrators breathe easier. And since OpenSSH is completely free, there is no reason why it should not be used.
The authors and editors have taken care in preparation of the content contained herein but make no expressed or implied warranty of any kind and assume no responsibility for errors or omissions. No liability is assumed for any damages. Always have a verified backup before making any changes.

About

Vincent Danen works on the Red Hat Security Response Team and lives in Canada. He has been writing about and developing on Linux for over 10 years and is a veteran Mac user.

0 comments

Editor's Picks