The following, originally written 2019-07-24, was updated on 2020-04-20 to reflect more recent security requirements.
OpenSSH is one of the host heavily-trafficked tools that there is among Linux systems engineers. It is used to hop around, onto and off of servers, to copy files, and even to run commands remotely. It can also be used as a poor man’s VPN. It might be a good idea, then, to pay attention to how we configure it. We might want to lock it down as much as we can.
In this post, we’re going to look at some best practices for using openssh, or just “ssh” from now on. We’re going to look at whether we should allow passwords, how to set up public/private keys, some suggested ciphers and MACs to use, and some other things that relate to ssh. This stuff has been tested on CentOS 7 and 8. Sweet, let’s do it!
Numero uno is going to be setting up public/private key pairs.
SSH Public/Private Key Pairs
I will be talking about two systems here. System A is the system from which you are connecting. System B is the system to which you are connecting. For our purposes, both of these systems are going to be Linux.
I’m not going to cover setting up public/private keys for Windows/putty here (that’s ok because it’s covered in detail many other places). However, if you’re using cygwin on Windows, this process would pretty much still work (the only difference is that the binaries end in “.exe” where they don’t on Linux).
The first thing we are going to do is hop onto System A (this might be your desktop, for example). We will open a terminal and create our ssh key.
Note: Before you do this, understand that if you already have a public/private ssh key pair created, this command will overwrite them. So if you have some that you don’t want to lose, back up ~/.ssh/id_rsa and ~/.ssh/id_rsa.pub.
Now that we are ready to create our key, we’ll run the following command as the user for which you want to create the key:
ssh-keygen -t rsa -b 4096
What does this do? Well, “ssh-keygen” is what’s used to generate the key. We use the “-t” flag to specify the type of key we want to generate. In this case, it’s an RSA key. From the fine manual, we learn that other “possible values are ‘rsa1’ for protocol version 1 and ‘dsa’, ‘ecdsa’, ‘ed25519’, or ‘rsa’ for protocol version 2.” The “-b” flag is used to specify how many bits long we want the key to be. I like to go for a nice, long one. For most situations, 2048 is the usual minimum acceptable length. Going bigger doesn’t hurt anything, though.
When asked for a passphrase, it’s up to you. We like to have as many layers of security as we can. That way, in case one fails, we have other layers that will hopefully save us. Putting a passphrase on your key will give you another layer of security.
Generating a public/private key pair looks something like this:
$ ssh-keygen -t rsa -b 4096 Generating public/private rsa key pair. Enter file in which to save the key (/home/user/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/user/.ssh/id_rsa. Your public key has been saved in /home/user/.ssh/id_rsa.pub. The key fingerprint is: SHA256:zOi7ubCIAg2gorLXYilay263N71VDwwXSWLY01A24Pg firstname.lastname@example.org The key's randomart image is: +---[RSA 4096]----+ | o=**. | |. .+oooo | |o . o.. | |+ + . + | |oo . S E + | |+ . . . o | |o..o. .. . . | |++*ooooo.. | |=*=ooo=+.. | +----[SHA256]-----+
Take note of where your key pair has been placed: /home/user/.ssh/id_rsa is your private key and /home/user/.ssh/id_rsa.pub is your public key. Great, we have a key pair. Now what do we do with it? Well, we’re going to put it on System B to allow us to log in.
The easiest way to do this is with a sweet little utility called “ssh-id-copy.” The reason this util rocks is because it sets all of the correct modes on the directory and files once they’re copied to System B. It can totally be done manually, but we’ll look at the automated way, first.
Ok, awesome. We’re going to assume that System B’s hostname is “systemb.”
The automated way is done with this command:
It will prompt you for your password and then copy everything over. After that, it will set the modes for the ~/.ssh/ folder and the file that has been copied into it. At this point, you should be able to ssh from System A to System B using your ssh key and optional passphrase.
Now, let’s walk through the manual steps so you get a better understanding of what is happening.
First, we’ll copy your ~/.ssh/id_rsa.pub file over to ‘systemb’:
scp ~/.ssh/id_rsa.pub systemb:
Great, our public key is there. Now, we need to head over to System B and place the file in the appropriate location and set some modes.
Head over to System B with:
Type in your password when prompted. Sweet, we’re on System B, now. Make sure the ~/.ssh/ folder exists:
mkdir -p ~/.ssh/
Then, change the mode of that folder to 700:
chmod 0700 ~/.ssh/
Now, we’re going to put the public key into the ~/.ssh/authorized_keys file:
cat id_rsa.pub >> ~/.ssh/authorized_keys
And the final step is to change the mode of the ~/.ssh/authorized_keys file to 600:
chmod 0600 ~/.ssh/authorized_keys
You can go ahead and remove ~/id_rsa.pub, now:
Now, log out of System B so that you’re back on System A. Let’s test everything. Try to ssh from System A to System B:
If you set a passphrase on your key, it will prompt you for that. If not, it should just dump you into a command prompt on System B.
We have now learned how to generate a public/private key pair. We’ve also learned how to place our public key onto other servers so that we can use it to ssh in to said servers. Nice work.
Now, let’s take a look at ways we can lock down the actual ssh daemon running on System B.
Locking Down SSHd
We are going to go over two things here. First, we will disable the use of passwords to log into the system. Then, we’ll lock down the ciphers that are acceptable to use.
Disable Password Authentication
Hop on System B, whether physically, or over ssh (since we can now do that because we’re just cool that way). We’re going to modify the following file:
First, back it up in case you screw it up and need to revert. Way easier to copy a file back over than try and figure out what it used to be when it worked. Once you have done that and not before, open this file up in your favorite text editor (bonus points if it’s vim). Find the line that starts with:
If it says “yes” out to the right, change it to “no”. Save, quit, and restart the ssh service:
systemctl restart sshd
service sshd restart
Why disable passwords? Passwords are vulnerable to brute force attacks in a way that our public/private keys are not. Turning off the ability to use passwords, mitigates this avenue of attack. We set up our public/private keys and turn off password authentication, and we should be pretty well off.
Strong Ciphers Only
Now, we’re going to check our ciphers to ensure that we’re only using the strongest ones. In this example, we’re going to make sure that we are not using ‘arcfour’ or ‘cbc’ ciphers.
Open up your /etc/sshd/sshd_config file again. This time, go all the way to the bottom. Add the following lines:
These lines flow onto multiple lines here on my blog. However, in the sshd_conf file, they should each be on a single line.
Once you’ve added those lines, you can save and quit. You are now safe from the dreaded arcfour and cbc ciphers. If you’d like to read more about this, take a look at these pages:
There’s a lot more great detail on those pages about ciphers and some other very useful stuff.
Before you disconnect, let’s make sure you can reconnect. While still connected, estart your SSHd:
systemctl restart sshd
Now, before closing your existing connection, try and ssh into that system again, in a new window. Everything should work just fine. 🙂
Once you are back in, you can actually log back out of both sessions. Now, we’re going to do a quick check to make sure the ciphers we want to use are actually being used.
We need a way to run nmap against ‘systemb’, the box we’ve just been working on. So, on a computer that is not systemb, (maybe System A, from above?) install nmap. If you’re on a RedHat-based machine, this will be done easily with:
yum -y install nmap
If you’re on another distro, hit up Google for some instructions on installing nmap.
So now we have nmap installed on System A and we’re going to do a quick scan against our ultra-hardened System B. Run the following command:
nmap -vv –script=ssh2-enum-algos.nse systemb
You will get a bunch of output. But there in the middle of the output, it tells you all about the different algorithms. If you see something like this, you’re good:
PORT STATE SERVICE
22/tcp open ssh
| kex_algorithms (5)
| server_host_key_algorithms (5)
| encryption_algorithms (6)
| mac_algorithms (6)
| compression_algorithms (2)
You can see all of the settings have taken place. No arcfour or cbc ciphers in the list of encryption algorithms. Alrighty, we’re in good shape. Next!
No security guide would really be complete without talking about firewall rules. What you should do here is set up a rule that denies everyone access to the sshd port, 22. Then, only add rules to allow connections from machines you trust. Again, it’s another layer of our security. If one fails, we have others to keep us safe.
Speeding Up the Initial Handshake
Here is one more thing I like to set. When ssh connections seem slow, it may be because the sshd on the remote end is trying to do a DNS lookup on the machine connecting to it. Fortunately, we can turn this action off. This can speed up the initial connection negotiation.
Hop into Server B again. Edit your /etc/ssh/sshd_config file. We’re going to look for and set the following directives to the values I have here:
UseDNS no GSSAPIAuthentication no
If they’re commented out, uncomment them and set them to these values. Save and restart your ssh daemon.
Disconnect, and then re-connect. Your connection should be nice and snappy.
Well, there are some ways you can lock down your ssh and tune it a bit. Follow these suggestions and you should be in good shape. Peace out.