Coming into this article I’m expecting you to have a a machine with SSH access authenticated using passwords.
Disable Root Login Via SSH
To disable root login you’ll need to open the SSH config file and make a small change. Shelled into the machine open the SSH config file:
sudo nano /etc/ssh/sshd_config
Scroll down until you find a line that says PermitRootLogin yes
# Authentication: #LoginGraceTime 2m PermitRootLogin yes #StrictModes yes #MaxAuthTries 6 #MaxSessions 10
Change the yes to a no
# Authentication: #LoginGraceTime 2m PermitRootLogin no #StrictModes yes #MaxAuthTries 6 #MaxSessions 10
Save the file and exit. You’ll now need to restart the SSH daemon (or optionally the whole machine).
sudo systemctl restart ssh
If you try to login as root now you should find you get a permission denied message. Optionally you can go one step further and completely deny root login even locally with this command:
sudo passwd root -ld
This locks the account and removes the password. I’m not convinced this is really necessary if the machine is physically secure.
Setup Key Based SSH Login
If you are using a complex password then password based login will probably keep you secure but key based logins are a significantly better option. When using key based logins you need to make a couple of decisions about how paranoid you want to be, the play-off is between convenience and security. The choices are: do you use separate keys for separate sites and do you use passwords on your keys.
The separate keys for separate sites means that if your private key for one site becomes compromised you only need to change keys for that one site. However, if your private key for one site has become compromised there’s a fair chance all the others have been compromised too. For what it’s worth, SSH sort of expects a single key being used everywhere.
Using a password with your key definitely improves security as it means no one can use the private key until they have decrypted it with the password. The downside is that every time you want to use the key you need to enter the password which make it feel like you’re using password based login (from a security view point it’s quite different, though) – but see the section about adding keys for KeePassXC later. The choice is yours, I used to be quite paranoid and used a different key for each site but I’ve since come to feel this adds unnecessary complexity. There’s a good discussion of this topic here.
Generate a Key Pair
On the local machine while logged in with your account run the command:
ssh-keygen -t ed25519
An example of running this command would look like this (note, this key isn’t used anywhere), I added a comment which is good practice:
$ ssh-keygen -t ed25519 -C some_comment Generating public/private ed25519 key pair. Enter file in which to save the key (/home/foo/.ssh/id_ed25519): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/foo/.ssh/id_ed25519 Your public key has been saved in /home/foo/.ssh/id_ed25519.pub The key fingerprint is: SHA256:R/p9mnOcuiW/SIZi5sgq8aQPsO2GMDNBdg67Gb9fsCU some comment The key's randomart image is: +--[ED25519 256]--+ | | | + . | |o = . | |.o . o | |..= E .S . | |=*... = o o | |o=o=.. .+ o =.o. | |..+o...= . o.O+ | | ..o+oo . *=o. | +----[SHA256]-----+
This uses the ed25519 key type which is the preferred standard on all modern systems. Compared to RSA it produces a shorter key and is generally faster overall. There is some argument over whether RSA is still entirely safe, short keys should certainly be avoided with RSA.
Copy the Public Key to the Remote Machine
You now need to copy the public key to the remote machine. The remote machine will use the public key to verify that you are holding the private key which is what allows you access. Since this is something that’s done quite commonly the SSH suite comes with a quick command to get this done.
ssh-copy-id example.com
Assuming your local user account has the same name as the remote account and you’re using the default key then that’s all you need. If you are using separate keys for different sites than you need to specify the identity to use. If you have different account names on different machine you need to specify the name of the remote account. Overall that would make the command look like this:
ssh-copy-id -i ~/.ssh/foo_key [email protected]
Now test that you can log into the remote machine using your key. With default keys and matching account names that’s as simple as:
ssh example.com
Adding or Changing a Password to a Key
If you created a key without a password and change your mind about that or if you just want to change the password for a key you can do so without creating a new key. Simply run the command:
ssh-keygen -p -f ~/.ssh/key_file
You will be prompted for the old password (if there is one) and the new password. Don’t lose or forget the password as there is no recovery mechanism!
Regenerate the Public Key
If for some reason you have misplaced all copies of your public key you can regenerate it from the private key with this command:
ssh-keygen -f ~/.ssh/key -y > ~/.ssh/key.pub
Turn off Password Login
Now that keys can be used for logins you should turn off password based logins. This improves the security as a good key is effectively impossible to crack. Open up your SSH config file again.
sudo nano /etc/ssh/sshd_config
Change the following three settings from yes to no:
PasswordAuthentication no KbdInteractiveAuthentication no UsePAM no
On Debian 12 system is seems only the UsePAM
setting is set to yes by default. Now restart SSH:
sudo systemctl restart ssh
Before exiting your existing session open a new terminal window and check you can login using your key. Also check that you can’t login with a password:
ssh -o PubkeyAuthentication=no -o PreferredAuthentications=password example.com
The above command should give you a Permission denied (publickey)
warning message, if you get a password prompt see below.
Wait a Minute, I Can Still Login With My Password
If you find that you can still login with your password the first place to check is /etc/ssh/sshd_config.d
as by default the .conf
files here will be imported into the SSH configuration. One server I installed unhelpfully created a file here that turned password logins on. Any settings here override any found in main configuration file.
Set up Fail2Ban
This is a fairly large topic so it got broken out into it’s own article here.
Add Keys to KeypassXC
The popular password management application KeePassXC is able to store keys within it’s database and populate the OpenSSH agent to which in turn provides details to the SSH client. To test whether you have the agent installed run the command ssh-add -l
as long as it doesn’t return something that looks like an error message you should be good to go (it’ll probably report The agent has no identities
on a new machine).
Enable SSH Agent Integration in KeePassXC
By default the SSH Agent integration is switched off in KeePassXC but it’s easy to turn on and configure. Within KeePassXC, open Tools > Settings
. In the left hand toolbar select SSH Agent. Simply enable the agent and check that SSH_AUTH_SOCK is populated. If the SSH_AUTH_SOCK path is not populated the integration won’t work. My value for this setting was /run/flatpak/ssh-auth
since I use KeePassXC as a Flatpak. Under Windows the set up is a little more complex – see the user manual.
Add Keys to KeyPassXC
- Create a new entry or edit an existing entry, give the entry a useful name such as “YourName SSH Key”.
- Set the password whatever is used for the key file (you set a password on the key, didn’t you!).
- Switch to the Advanced page for the entry and attach at least the private portion of your key.
- Select SSH Agent from the left hand menu. Under the private key area select Attachment and pick the key you’ve just attached.
- Set the options for using this key. I like
Add key to agent when database is opened
andRemove key from agent when database is closed
. - Press Ok to commit the KeePassXC entry.
In order to load the key(s) you’ll need to close KeyPassXC and reopen it. If you run the command ssh-add -l
now it should show you the key you’ve just added.
The big test to see if this set up is working is to remove the key you’ve added to KeePassXC from the ~/.ssh directory and check if you can still log in. I wouldn’t immediately delete the key just in case something is wrong but it’s stored in KeePassXC anyway so it’s not the end of the world.
Note: just like with SSH the identity associated with the key is the name in the attachment not the name in the KeePassXC username field. As far as I can tell you could have anything you like in the username field and it’ll still work. E.g. if the username field was bar and you had and attached key called foo_ed25519 the command ssh [email protected]
would work just fine and connect to the foo account.
Note: if you want to access the stored files (because you lets say need to recreate the public key) you can select the attachment and save it to disk.
Monitoring
The command:
sudo journalctl -t sshd
Will give you a full rundown of what is going on with SSH but it’s almost certainly going to give you more information that you can handle.
References
This is a list of some of the references I used when writing this page.
- Forcing password based authentication – Linux StackExchange
- How to disable password login in SSH
- General server setup, SSH page – good but doesn’t cover the topic in much detail
- KeePassXC User Guide
- Changing the password on a key