Here is a quick way to drastically improve the security of your
OpenSSH server
installations. Apart from past flaws in the OpenSSH daemon itself that
have allowed remote compromise (very rare), most break-ins result from
successful brute-force attacks. You can see them in your firewall,
system or auth logs, they are an extremely common form of attack. Here
is an excerpt from the /var/log/messages file on a CentOS Linux box
(the attacking hostname has been obfuscated). You can see multiple
attempts to login as users root and ftp. Also note the time between
repeated attempts - one second or less, much too quick to be a
human. This is an automated attack.

From personal experience with clients over the years, I have found
that most administrators tend to install an SSH server and leave it at
its default settings, typically to allow password authentication and
root logins. Many don't even know that there is an alternative
(key-based authentication), or they think the alternative is too hard
to use. It is not - it takes all of five minutes to configure
key-based authentication and disable root logins, and the security
gains are enormous. Below, I'll step you through the process.

Configuring and Testing Key-Based Authentication

This is not really a hard as it seems. By default, all recent OpenSSH
configurations allow public key authentication. You just have to
generate a pair of SSH keys on the client, and append the generated
public key to a file
named authorized_keys on the
server. This works on any Unix/Linux with OpenSSH, or even under
Windows with Cygwin's OpenSSH port (I won't mention it further here,
but If you are stuck on a Windows client
without Cygwin,
use
href='http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html'>PuTTY
and check
out
href='http://the.earth.li/~sgtatham/putty/0.58/htmldoc/Chapter8.html#pubkey-puttygen'>Using
PuTTYgen).

Let's say you routinely use SSH to login from your home workstation,
sshclient, as
user obiwan, to a remote SSH
server as user vader. For
consistency's sake, we'll call the remote
server sshserver. I'm assuming
you have working password authentication already.

On sshclient, log in under your user
account obiwan, and run the
following three commands.

obiwan@sshclient:~$ ssh-keygen -t dsa

This first command generates the public/private key pair for you,
assigns a passphrase to the private key, and stores both keys in the
directory ~/.ssh by default. Just accept the defaults, and enter a
passphrase when prompted.
obiwan@sshclient:~$ cat ~/.ssh/id_dsa.pub | ssh vader@sshserver 'cat >> .ssh/authorized_keys'

or, you can simply use the 'ssh-copy-id' command:

obiwan@sshclient:~$ ssh-copy-id vader@sshserver

This command appends your public key, which is stored
in ~/.ssh/id_dsa.pub by
default, to the authorized_keys file on the remote host. One caveat,
you may not have a '.ssh' directory on the remote server in vader's
home directory. Create it if needed.

This last command changes the permissions on the remote
authorized_keys file to be more secure, and to prevent a common
problem that prevents key-based authentication.

Now, test SSH login to 'vader@sshserver'. You should be prompted for a
passphrase this time, not a password. Enter the passphrase you chose
when you created your keys, and you should be logged in.

Disabling Password Authentication

Once key-based logins are working, disable password authentication. Find your SSH server's configuration file. This is usually in
/etc/ssh/sshd_config. Find the line that says:

PasswordAuthentication yes

and change it to

PasswordAuthentication no

You should also disable challenge-response authentication, in case
your version of OpenSSH is using PAM to authenticate (see below for an explanation):

ChallengeResponseAuthentication no

Disabling Root-Logins

Finally, disable root logins. Kudos go to NetBSD and FreeBSD, whose
default configurations do not allow root logins, so there will be
nothing to do for you to do in this step if you are using a recent
version of either one. OpenBSD and most Linux distributions allow root
logins by default. Again
in /etc/ssh/sshd_config, find
the line that reads

PermitRootLogin yes

and change it to

PermitRootLogin no

Reload your SSH server's configuration
with /etc/init.d/ssh reload
(Debian Linux-based), service sshd
reload (Red Hat
Linux-based), /etc/rc.d/sshd
reload (NetBSD/FreeBSD) or just send sshd a HUP signal, usually
with something like kill -HUP
pid, where pid is the
process ID of the SSH server, you can get it quickly on any Unix
platform by running something like ps
ax | grep sshd.

Details on PAM Authentication

Disabling PAM-based password authentication is rather
un-intuitive. It is needed on pretty much all GNU/Linux distributions
(with the notable exception of Slackware), along with FreeBSD. If
you're not careful, you can have PasswordAuthentication set to 'no'
and still login with just a password through PAM authentication. It
turns out that you need to set 'ChallengeResponseAuthentication' to
'no' in order to truly disable PAM authentication. The FreeBSD man
pages have this to say, which may help to clarify the situation a bit:

Note that if ChallengeResponseAuthentication is 'yes', and the PAM
authentication policy for sshd includes pam_unix(8), password
authentication will be allowed through the challenge-response
mechanism regardless of the value of PasswordAuthentication.

Common Objections

Many sysadmins advocate leaving password authentication in place,
and mandate the use of strong passwords. This is an example of
'shallow defense', and is a bad idea for a few reasons. First, even if
you pick a password strong enough to make brute-force attacks next to
impossible, you are still relying on a single authentication
factor. Depending on your circumstances, you should take into account
non-brute force methods of attack that may compromise passwords, like
social engineering or exploiting weaknesses in underlying
authentication algorithms. Again, this depends on your
circumstances. If you are the only SSH user and are willing to accept
the risks of password authentication, it may work fine for you. The
idea of not relying on a single authentication method, applying
defense in depth whenever possible, underlies the idea of using
two-factor (keys + passphrases) authentication.

Another common recommendation is to leave OpenSSH in its default state
(using password authentication), and use a tool
like Denyhosts. I've
never been a big fan of methods like this, I think using the security
features present in OpenSSH itself makes for a simpler and cleaner
solution. I'm also very wary of any tool that automates the blocking
of network connections.

Closing Thoughts

There is much more to OpenSSH configuration and security, but
these few, simple steps will go a long way towards preventing
brute-force attacks and letting you sleep at night. Repeat the above
steps on all your SSH servers, copying your SSH public key to each
server as needed (it may not be obvious if you've never used key-based
authentication before, but don't regenerate your keys for each host).