SSH Security: Certificate Only & No Root Login (Debian)

SSH Security: Certificate Only & No Root Login (Debian)
Photo by Javardh / Unsplash

Hehe... the photo is of a shell. Get it? Like Secure SHell? It was funnier in my head.

Anyway, the two most common ways to access a remote computer CLI via SSH is using a username and password, or using certificates. Certificates are far more secure, and not nearly as difficult to set up as you might have been led to believe. Let's take a crack at it.

First let's generate an SSH Key using the script below (You can run this on pretty much any linux computer, it doesn't have to be the machine you're trying to access.):

#!/bin/bash
read -p 'Hostname: ' sshhost
read -p 'Username: ' sshuser
ssh-keygen -t ecdsa -b 521 -C "$sshuser@$sshhost" -f ~/$sshhost-key-ecdsa
cat ~/$sshhost-key-ecdsa.pub

This will first ask for a hostname and username. These are just for comments for the keys; They do not really affect functionality.
Then it will attempt to generate an SSH key and dump it in the working directory. It will use ECDSA 521 bit which is pretty much the gold standard. (There are plenty more options though, if you want to poke around: https://www.ssh.com/academy/ssh/keygen)
It will prompt you to enter a passphrase (password), twice. The password is optional, and is used to encrypt the keyfile so that whenever you want to use it, you must first enter the password. Using a passphrase is good practice, and akin to using 2FA. I recommend doing so and saving the passphrase in a good password manager, like BitWarden.
Then it will output the public key to the console so you can copy it.

Upon running the script, output will look something like this:

The bottom line there, that starts with ecdsa-sha2-nistp521 and ends with user@host, that's the public key. It is not sensitive information. It's saved in ~/host-key-ecdsa.pub
You are going to need this in a bit, so copy it into your clipboard or paste it into a text editor or something.

Take the two generated files and put them somewhere safe. Remember, you will need them in order to access your server.

Now we need to add the public key to the server's authorized_keys file.
Again, don't make the mistake of adding this to your workstation's authorized_keys. That won't help you much.
Where this file is depends on which account you want to use to log on with the key you generated. If it isn't root (and it probably shouldn't be root) it'll be here:
/home/USERNAME/.ssh/authorized_keys
If you are using the root account, it'll be here:
/root/.ssh/authorized_keys
Go ahead and edit the appropriate authorized_keys file on the server you intend to access, and paste in the public key you copied earlier.

Now the key is authorized, but we still have some config to do. Luckily this script makes short work of things. This will move your existing SSH config, and replace it with a new one with all the standard options as well as a few we've tweaked. Then it restarts the SSH server service. After this, you'll only be able to log in via SSH using certificates.

#!/bin/bash
mv /etc/ssh/sshd_config /etc/ssh/sshd_config_bak

touch /etc/ssh/sshd_config
echo "Include /etc/ssh/sshd_config.d/*.conf" >> /etc/ssh/sshd_config
echo "UsePAM yes" >> /etc/ssh/sshd_config
echo "PrintMotd no" >> /etc/ssh/sshd_config
echo "AcceptEnv LANG LC_*" >> /etc/ssh/sshd_config
echo "Subsystem sftp internal-sftp" >> /etc/ssh/sshd_config
echo "PermitRootLogin prohibit-password" >> /etc/ssh/sshd_config
# echo "PermitRootLogin no" >> /etc/ssh/sshd_config
echo "KbdInteractiveAuthentication no" >> /etc/ssh/sshd_config
echo "PasswordAuthentication no" >> /etc/ssh/sshd_config
echo "ChallengeResponseAuthentication no" >> /etc/ssh/sshd_config
echo "PubkeyAuthentication yes" >> /etc/ssh/sshd_config
echo "X11Forwarding no" >> /etc/ssh/sshd_config

systemctl restart ssh

If you'd like to block SSH using the root account altogether, remove the PermitRootLogin prohibit-password and uncomment the PermitRootLogin no line.
Do NOT disable root login if you are running Proxmox or Proxmox backup server. Both are pretty heavily dependent on the root account, and doing so can cause issues.

That's it. You're done. Great Job.

Oh wait... How do I access the server? Easy...

ssh USER@SERVER -i ./host-key-ecdsa

Replace USER with the username you plan to connect as, replace SERVER with the IP or hostname of your server, replace ./host-key-ecdsa with the location of your private key file. If you set a passphrase for the keyfile you'll be prompted to enter it.