Securing Against OpenSSH’s Less-Then-Perfect Defaults

There’s a general security principle: Lock everything up, and then unlock only what needs to be unlocked.

However, this is in contrast to OpenSSH‘s defaults for cryptography, which are, “Open most things up so that old clients can connect.”

Combination Lock

Photo by Self

For those who don’t know, OpenSSH is the most widely used SSH (Secure Shell) server – a tool used by sysadmins (and others) to access remote computers. It’s also the foundation of most Git (a version control system for software developers) security systems. It secures up some of the most sensitive parts of our systems: our intellectual property and “root” access.

Now, none of SSH’s choices are truly horrible, but the defaults certainly aren’t the strongest they could be, either. SSH defaults to allowing several less secure algorithms, along with some very strong algorithms. It does this for backwards compatibility.

However, backwards compatibility is not relevant to SSH in many environments.  Do you really need to support older, and somewhat less secure, cryptography algorithms because some admin might be using an ancient version of Putty?  Perhaps it’s time to get that person to upgrade!

So, here’s some quick notes – you can find more elsewhere – on OpenSSH. You might need to loosen some of these settings in your environment, but at least they’ll start fairly secure. I’ll put up another post on Apache at a later date.

For SSH:

Note you may have to alter paths or other items in the below snippets. Also note that I assume you have reasonable defaults from recent versions of OpenSSH – I.E. no version 1 support, no rsh fallback, etc.

In your sshd_config file (typically in /etc/ssh/sshd_config):

HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
# HostKey /etc/ssh/ssh_host_dsa_key
# HostKey /etc/ssh/ssh_host_ecdsa_key

What does this do? First, we comment out the DSA and ECDSA keys. DSA is on the cusp of being insecure (max key length is 1024 bits) while ECDSA uses NIST-supplied curves, which some believe have been backdoored by the NSA.

Next, I enabled two key exchange algorithms. Notably, I didn’t enable the SHA1 versions of the DH algorithms, or the ECDH algorithms with NIST curves (which some believe are backdoored by the NSA). Why use a known-to-be potentially less secure algorithm when there are algorithms that are secure?

For encryption, I picked a subset of ciphers I believe to be secure and re-ordered them more appropriate to my needs (but, again, your needs may differ). The big deal was that I didn’t want 3DES, CAST128, or RC4 (arcfour) in the list – these all have problems and shouldn’t be used if you don’t really need them.

For MACs (this verifies you are talking to the person you think you’re talking to, and someone isn’t changing the ciphertext), I removed all MD5 MACs and any MAC less than 128 bits. MD5 is known to have issues, so why use it? And longer MACs are good in this context.

I also like to use PasswordAuthentication no, assuming I’m in an environment where I can force the use of SSH keys or other non-password authentication choices. Passwords can be guessed, and you can bet you’ll see thousands of attempts to guess them, should your firewall allow people on the internet to try. But of course you need to set this up in advance.

Finally, there are two other things that need to be done – creating a stronger RSA host key and selecting non-standard Diffie Hellman parameters (this makes your system secure against Logjam).

The standard RSA key, at least on my Ubuntu system, was a 2048 bit key. That’s not a bad length, but I wanted something more secure. To do this:

ssh-keygen -b 4096 -t rsa -f /etc/ssh/ssh_host_rsa_key

This generates a 4096 bit RSA key. Note that users that had the old key stored in their .ssh/known_hosts file will have to remove the old key and add the new one (and they are validating signatures, right? As an alternative you might store the fingerprints in a DNSSEC-secured DNS zone).

To generate the non-standard DH paraemters (note this takes several hours on my machine):

ssh-keygen -b 2048 -G moduli.candidates -M 127
ssh-keygen -T moduli.2048 -f moduli.candidates
ssh-keygen -b 4096 -G moduli.candidates -M 127
ssh-keygen -T moduli.4096 -f moduli.candidates
cat moduli.2048 moduli.4096 >/etc/ssh/moduli

Of course you should read and understand what these do – not just take my word for it!

You’ll need to restart sshd after doing this (on Ubuntu, service ssh restart). Make sure you have a way of recovering access if you lock yourself out over SSH!

Finally, the changes you made to your sshd_config, particularly the algorithm choices, can be added to your ssh_config so your clients don’t try to use less secure algorithms. In the “Host *” section, add:


Of course these changes may prevent older clients from connecting to servers, or your client from connecting to older servers. If that’s the case, you need to rework the defaults (for the new client, old server problem, you can use a host-specific override in your ssh_config).

Finally, generate a longer user key pairs if you use SSH key-based authentication (you do this as the user you are generating the key for):

ssh-keygen -b 4096

The default key length is 2048, which is good, but 4096 is a bit better.

Will this keep the NSA out? Probably not, but at least you’re using better-than-default practices now.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s