Long-held is the belief that root
should never be allowed to login directly into a remote terminal, but should instead come from elevation from an unprivileged user. Nowadays, there are enough methods to allow root
login without increasing your attack surface, thanks to cryptographic keys.
The most common keys are RSA
keys, but others exist which are readily accepted by modern sshd
daemons.
The following command generates a ed25519
key, similar to, but more modern (and recommended) than RSA
. You can generate an RSA
key instead by simply replacing ed25519
with rsa
.
$ ssh-keygen -t ed25519 -C "for root@mineos" -f ~/.ssh/mineos
Generating public/private ed25519 key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/user/.ssh/mineos
Your public key has been saved in /home/user/.ssh/mineos.pub
The key fingerprint is:
SHA256:Maq2bflTz+vmKCRHcDcFM2o0IoXw41UnrYZSU4ZEju8 for root@mineos
...
$
In this example -f ~/.ssh/mineos
is the filename of the private key to be generated. If this is omitted, it will default to ~/.ssh/id_ed25519
; using this default is often preferred, as it obviates the need to specify the -i
identity file on subsequent steps.
It is very possible your default installation of sshd
already is allowing this kind of direct root
login. We can verify on the destination server:
# grep -b2 -n "Root" /etc/ssh/sshd_config
30-753-
31-754-#LoginGraceTime 2m
32:773:#PermitRootLogin prohibit-password
33-808-#StrictModes yes
34-825-#MaxAuthTries 6
--
78-2113-# PasswordAuthentication. Depending on your PAM configuration,
79-2177-# PAM authentication via ChallengeResponseAuthentication may bypass
80:2245:# the setting of "PermitRootLogin without-password".
81-2298-# If you just want the PAM account and session checks to run without
82-2367-# PAM authentication, then enable this but set PasswordAuthentication
--
137-3538-Banner /root/.ssh/banner
138-3563-Match user *
139:3576:PermitRootLogin prohibit-password
Line 32 shows #PermitRootLogin
, which is actually a comment and therefore has no effect. A standard convention of configuration files is to indicate the default value if unspecified, as a comment. This entry signifies that plaintext passwords are already prohibited for root
login, but cryptographic keys are accepted.
Line 139 actually shows that for a user match of the user root
connecting to this host, explicitly disallow plaintext passwords for root
login. Either of these prohibit-password
s will work for this case, but the latter takes precedence.
Restart the sshd
daemon according to your distribution. Depending on your install, it could be service sshd restart
or systemctl restart sshd
(or others).
Back on your client machine, connect to your SSH host with the key:
$ ssh-copy-id -i ~/.ssh/mineos root@10.137.0.12
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/user/.ssh/mineos.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@10.137.0.12's password:
Received disconnect from 10.137.0.12 port 22:2: Too many authentication failures
Disconnected from 10.137.0.12 port 22
Note, it is asking for root
’s password, not your chosen passphrase. This is because while the identify file is being passed through, the ssh
host is not aware of this key. Normally, we rectify this with ssh-copy-id
. However, root
doesn’t have a password, so it’s a catch-22 of how to get passwordless access without ever setting a password. Setting a password for root
, enabling plaintext passwords, restarting the daemon, and copying the key is possible–but suboptimal, in terms of security best practices, and more error-prone. This document will only cover the process copying the key via a secondary user, designated as mc
.
Remember the design of a private key/public key system: only the private key is delicate–the public key is just that, freely-sharable. In fact, any user that tries to misuse your public key can really only provide access rather than steal access.
With this in mind, let’s copy the public key to the new host, then ultimately put the key in the correct location: /root/.ssh/authorized_keys
.
$ ssh-copy-id -i ~/.ssh/mineos mc@10.137.0.12
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/user/.ssh/mineos.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
mc@10.137.0.12's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'mc@10.137.0.12'"
and check to make sure that only the key(s) you wanted were added.
And now test it with the command:
$ ssh -i ~/.ssh/mineos.pub mc@10.137.0.12
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/home/user/.ssh/mineos.pub' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "/home/user/.ssh/mineos.pub": bad permissions
mc@10.137.0.12's password:
Set the private and public key to read-only and access is granted. Remember, passphrases are separate from the user’s password–if you did not use a passphrase in the previous step, you will be brought directly to the shell prompt.
$ chmod 400 ~/.ssh/mineos*
$ ssh -i ~/.ssh/mineos mc@10.137.0.12
Enter passphrase for key '/home/user/.ssh/mineos':
Welcome to Mineos-tkldev, TurnKey GNU/Linux 14.0 / TurnKey 9.13 Stretch
Linux mineos-tkldev 4.9.0-16-amd64 #1 SMP Debian 4.9.272-1 (2021-06-21) x86_64
Last login: Fri Jul 2 19:34:59 2021 from 10.137.0.14
mc@mineos-tkldev ~$ cat .ssh/authorized_keys
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEymEwH4hVASNVwxOhmDZF2dmhZPY/kfv8NV5X+rt/p1 for root@mineos
mc@mineos-tkldev ~$ ll .ssh/authorized_keys
-rw-------. 1 mc mc 97 Jul 2 19:35 .ssh/authorized_keys
Because in the previous step we are able to confirm that there is only one authorized_key
–and it matches the key we just generated–we can take a shortcut. On a more mature system, you will need to manually move the one, newly-added key from /home/mc/.ssh/authorized_keys
to /root/.ssh/authorized_keys
.
As the superuser root
on the destination machine:
# rsync -av --chown=root:root /home/mc/.ssh /root/
The reason this is a shortcut is it fully duplicates all authorized users for mc
to root
. Any and all keys that would permit mc
access would now do the same for root
. If this does not match your intended userset, edit /root/.ssh/authorized_keys
to remove unwanted entries. Additional steps this command also accomplishes includes changing the owner and group to match root:root
, as well as match the proper rwx
permissions (that we executed in the previous step).
/.ssh
should be 700
and authorized_keys
should be 400
or 600
.
# ll .ssh/
total 12
drwx------. 2 root root 4096 Jul 2 19:35 ./
drwx------. 10 root root 4096 Jul 2 20:00 ../
-rw-------. 1 root root 97 Jul 2 19:35 authorized_keys
$ ssh -i ~/.ssh/mineos root@10.137.0.12
Enter passphrase for key '/home/user/.ssh/mineos':
Welcome to Mineos-tkldev, TurnKey GNU/Linux 14.0 / TurnKey 9.13 Stretch
Last login: Fri Jul 2 20:01:30 2021 from 10.137.0.14
root@mineos-tkldev ~#
It is attractive to omit the passphrase for truly instant, passwordless login. Establish your own threat model and decide what is best for your system and needs.
If cryptographic keys completely replace your user passwords for system login, you can further harden your server by disallowing passwords:
# To disable tunneled clear text passwords, change to no here!
#PasswordAuthentication yes
#PermitEmptyPasswords no
TO:
# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no
#PermitEmptyPasswords no
As a convenience when using passphrases, you can use an SSH-AGENT to save you from repetitive passphrase entry. Notice this login (and all subsequent logins until reboot) will automatically handle the passphrase prompt for you.
# ssh-add ~/.ssh/mineos
Enter passphrase for .ssh/mineos:
Identity added: .ssh/mineos (for root@mineos)
$ ssh -i ~/.ssh/mineos root@10.137.0.12
Welcome to Mineos-tkldev, TurnKey GNU/Linux 14.0 / TurnKey 9.13 Stretch
Linux mineos-tkldev 4.9.0-16-amd64 #1 SMP Debian 4.9.272-1 (2021-06-21) x86_64
You have new mail.
Last login: Fri Jul 2 20:06:55 2021 from 10.137.0.14
Finally, you can simplify the connection process by making all attempts to a host always use a given identity file. Add the following content (adjust as necessary) to ~/.ssh/config
:
Host 10.137.0.12
User root
IdentityFile ~/.ssh/mineos
Port 22
Now, login with only the IP and notice it automatically uses your config to determine the identify file and intended user root
:
$ ssh 10.137.0.12
Welcome to Mineos-tkldev, TurnKey GNU/Linux 14.0 / TurnKey 9.13 Stretch
Linux mineos-tkldev 4.9.0-16-amd64 #1 SMP Debian 4.9.272-1 (2021-06-21) x86_64
You have new mail.
Last login: Fri Jul 2 20:16:57 2021 from 10.137.0.14
root@mineos-tkldev ~#
Cryptographic keys help reduce danger by eliminating the need to type passwords on foreign, potentially compromised-hosts. It also greatly reduces attack surface by making unauthorized logins nearly impossible. In conjunction with other sshd
security functions and firewalls, sshd
can live peacefully and securely on your host.