JMM’s notes on

SSH

Get the fingerprint of the current machine

Sometimes you get the following warning when trying to connect to a machine:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ED25519 key sent by the remote host is
SHA256:░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░.

If you have physical access to that machine, you may wonder, “What is the fingerprint of this machine?”. If it has a /etc/ssh/ssh_host_ed25519_key.pub (for example) you’d run:

$ ssh-keygen -E sha256 -lf /etc/ssh/ssh_host_ed25519_key.pub
256 SHA256:░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ root@░░░░░ (ED25519)

Add the -v flag if you want the visual ASCII art fingerprint.

SSH Agent

Add an identity, but only for 8 hours:

ssh-add -t 8h ~/.ssh/id_rsa

SSH agent things to check out

  • You can limit where SSH agent allows keys to be used, see the “-h” option in man ssh-add.

GNOME Keyring

GNOME Keyring loads its own SSH agent that automatically loads all files in ~/.ssh/ (see this article on GNOME Wiki). I kinda don’t like this behavior and would prefer only loading certain keys explicitly. The reason being I’ve got a lot of keys, and if SSH tries everything I end up getting authentication failures for trying too many keys.

I think SSH agent is getting split out of GNOME keyring in the future (a commit from October 2023 shows ssh agent being disabled by default in builds of gnome-keyring).

Running commands on remote host

Here’s an example of running pg_dump to make a backup of the data in a PostgreSQL table:

ssh somehost pg_dump --format=plain --table=public.sometable --dbname=somedb --data-only --inserts --on-conflict-do-nothing > mybackup.sql

Running a restricted single-user SSH daemon

I wanted to rsync some files on my server that were under a system user. I probably should have just added a way to log in to this user, but instead I thought I’d run SSH with CAP_DAC_READ_SEARCH capabilities so I could read everything. I’m sure this is pretty insecure, so don’t do this yourself.

Anyway, here’s some code to do this:

SOMEUSER=$(whoami)
sudo mkdir /var/lib/ssh2
sudo chown $SOMEUSER /var/lib/ssh2
mkdir /var/lib/ssh2/authorized_keys.d/

ssh-keygen -f /var/lib/ssh2/ssh_host_ed25519_key -N '' -t ed25519

# Copy your ssh key into /var/lib/ssh2/authorized_keys.d/$SOMEUSER

cat <<EOF > /var/lib/ssh2/config
HostKey /var/lib/ssh2/ssh_host_ed25519_key
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AuthorizedKeysFile /var/lib/ssh2/authorized_keys.d/%u
PermitEmptyPasswords no
ChallengeResponseAuthentication no
UsePAM no
StrictModes no
PidFile none
LogLevel VERBOSE
EOF

And here are a couple ways of running the SSH daemon:

# Here we use -d to debug a single connection
systemd-run --wait -t -p User=$SOMEUSER sshd -D -d -p 2222 -f /var/lib/ssh2/config -e

# WARNING: CAP_DAC_READ_SEARCH lets the user read basically anything.
systemd-run --wait -t -p User=$SOMEUSER -p ProtectHome=read-only -p AmbientCapabilities=CAP_DAC_READ_SEARCH sshd -D -p 2222 -f /var/lib/ssh2/config -e

Then on your local machine (or wherever you want to receive files):

rsync -Phazrv -e "ssh -p 2222" --ignore-existing some-server:/var/lib/whatever/ ~/backups/whatever/

Misc commands

In case I forget. Which I will.

# Remove a host key from known_hosts
ssh-keygen -R 192.168.0.108

# Connect using password
ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no nixos@192.168.0.108

# Add a key
ssh-copy-id -i ~/.ssh/id_rsa.pub  -o PreferredAuthentications=password -o PubkeyAuthentication=no nixos@192.168.0.108