Razzi's guide to ssh


ssh (secure shell) is one of the programs I use most frequently. It’s pretty amazing. It’s like a remote desktop for your command line.

But since it’s text-only, you can script it quite easily. For example, to run uptime on another host:

$ ssh razzi@sdf.org uptime
11:56PM  up 20:32, 53 users, load averages: 0.51, 0.46, 0.44

(This is running on the great SDF public access unix system. Create an account for free!)

Note that this guide is highly opinionated and a bit nonstandard. More than anything else I am using this to document my own practices.

Creating an ssh key

I use ed25519 keys since they’re shorter and faster. I guess they’re supposed to be more secure too but the cryptography is a bit over my head to be honest.

I like to name my private key with a .priv extension and my public key with a .pub extension. The .pub extension is standard, but the default is to have the private key simply named id_ed25519 with no extension.

In my opinion this is a bad idea, since you are liable to access the private key by mistake since it is a prefix of the public key. I resolve this by naming them with different extensions, so you’ll see .priv if you’re ever dealing with the private key.

As far as I know there’s no way to tell ssh-keygen to do this for you, so I generate my keys in the following 2-step process:

$ ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519.priv
Generating public/private ed25519 key pair.
Enter passphrase (empty for no passphrase):  
Enter same passphrase again:
Your identification has been saved in /sec/root/.ssh/id_ed25519.priv
Your public key has been saved in /sec/root/.ssh/id_ed25519.priv.pub
The key fingerprint is:
SHA256:DliKsPkfG7us9vnnfKVYSlkkD7l97QyxFBfQd0Z+Es0 root@lsd-GloomSwear
The key's randomart image is:
+--[ED25519 256]--+
|         .  o++=.|
|        + . o..oE|
|.     .  B . +.o+|
| + . +  . + + ...|
|o . o . So . +   |
| .     oo . . o  |
|  . o  ..+ o     |
|  .o * .+ o      |
| ..oOo.oo.       |

$ mv ~/.ssh/id_ed25519{.priv,}.pub

When it prompts for a password, I generate a new one from pass. The system I use for naming is $HOSTNAME-id_ed25519. So for a computer with hostname darkglow my pass entry is named darkglow-id_ed25519.

The mv command takes the .priv out of the public key name, so I’m left with:

$ ls ~/.ssh
id_ed25519.priv  id_ed25519.pub

Then when I want to publish my public key, I copy it like so:

$ fish_clipboard_copy < ~/.ssh/id_ed25519.pub

and then I can paste the public key into the textarea of a service like sourcehut, or a host’s ~/.ssh/authorized_keys file.

Copying an ssh key with ssh-copy-id

ssh-copy-id is a nice convenience for putting your public key on a host that you can log in to using a username and password.

Using a username and password (and allowing it) is less secure, so it’s a good idea to make the first thing you do once you can connect to a host running ssh-copy-id, and then disable password authentication.

Example usage:

$ ssh-copy-id razzi@
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/razzi/.ssh/id_ed25519.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
razzi@'s password:

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'razzi@'"
and check to make sure that only the key(s) you wanted were added.

$ ssh razzi@
Linux 45-79-9-183.ip.linodeusercontent.com 5.10.0-23-amd64 #1 SMP Debian 5.10.179-1 (2023-05-12) x86_64 [...]

If you’re curious, you can see how key installation is implemented by viewing ~/.ssh/authorized_keys.

Disabling password login for ssh

Once your public key is installed, disabling password login will make your system more secure.

Log in to your server and edit /etc/ssh/sshd_config.

$ sudo -e /etc/ssh/sshd_config

Find this config (it has a helpful description):

# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication yes

Like it says, change the yes to no:

PasswordAuthentication no

Reload the sshd config:

$ sudo systemctl reload sshd

And test that password login is off as follows:

$ ssh -o PubkeyAuthentication=no youruser@xx.xx.x.xxx
youruser@xx.xx.x.xxx: Permission denied (publickey).

View the fingerprint of your ssh key

Often when you add a key, it’ll show just a hash of it, which it calls a fingerprint.

To generate a fingerprint for a key (public and private use the same fingerprint, but here I’m using public key since I don’t like to touch my private keys):

$ ssh-keygen -l -f ~/.ssh/id_ed25519.pub
256 SHA256:cN2rCu/BVEtqimzvxbhNIOejocHHMANh4HMrsXuLle0 razzi@DESKTOP-IFJ7AJU (ED25519)

However that’s hard to read, and a lot of places still use the legacy md5 hash function. This is probably a bad thing, seeing as md5 is not resistant to collisions. But checking an md5 hash is better than nothing…

$ ssh-keygen -l -E md5 -f ~/.ssh/id_ed25519.pub
256 MD5:bc:92:c0:8a:8f:6a:b1:8d:ec:8a:45:7f:4d:d9:4f:26 razzi@DESKTOP-IFJ7AJU (ED25519)

There’s one more cool way to identify your keys: randomart. This is displayed when you generate your keys (see above) and can be printed with the following command:

$ ssh-keygen -l -v -f ~/.ssh/id_ed25519.pub
256 SHA256:cN2rCu/BVEtqimzvxbhNIOejocHHMANh4HMrsXuLle0 razzi@DESKTOP-IFJ7AJU (ED25519)
+--[ED25519 256]--+
|+.               |
|o.       . .     |
|.+ .  . . + .    |
| .= .  o + . .   |
| o+.. o S . .    |
| .o*o= O   .     |
| .o+B.* * .      |
|  +=o+ O o       |
| ....E+.=        |

The idea here is that at a glance you can compare randomarts.

You can display the server key randomart with the -o VisualHostKey=yes flag:

$ ssh -o VisualHostKey=yes xx.xx.x.xxx
The authenticity of host 'xx.xx.x.xxx (xx.xx.x.xxx)' can't be established.
ED25519 key fingerprint is SHA256:CirXgebEZ0xENb7SmPJE7xxWmjmSCZ/lmXv0Qu8sFa0.
+--[ED25519 256]--+
|   .o.o          |
|   . . .         |
|  . o o .  .     |
| . B @ O  . .    |
|  * ^ # S  o     |
| + O O B oE      |
|. + o = o.o      |
| o     ..+       |
|         .o      |
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])?

You can set this option persistently in /etc/ssh/ssh_config.