Home Tell ssh client to use a specific private key from ssh-agent key list
Post
Cancel

Tell ssh client to use a specific private key from ssh-agent key list

Trying to connect using ssh using ssh-agent’s exposed private keys stored at KeePassXC

I store multiple private/public keys at KeePassXC. I use the KeePassXC<=> ssh-agent integration to expose the keys to applications like ssh. I found out that if you have many keys added to the ssh-agent and try to use the ssh client with the keys I may encounter an error:

Too many authentication failures

First I have decided to check my private key list with ssh-add -l(-L). I found out that the required key is correctly listed. Next I have decided to double-check if the server has its the public key. I found out it was correctly placed in the .ssh/authorized_keys. So what the heck is going on?

How to find out what is going on?

I need to get more information what is happening when the ssh client is trying to connect to the server. Running the ssh -v will show me more details. There I found out that the ssh client is actually running all the stored keys sequentially (top to bottom). This means that if the private ssh key I’m using is at the bottom of the list it will exhaust the maximum retry limit at the sshd server.

I have tried to confirm my hypothesis by setting the MaxAuthTries sshd configuration /etc/ssh/sshd_config limit to a number larger than I have keys present at ssh-agent(in my case it was 30). When I have restarted the daemon I can now always connect to the sshd server without getting the error message. This confirms the hypothesis and I know what is causing the error.

How to permanently solve it without raising the MaxAuthTries value? That is an ugly, insecure, and a non-permanent solution as the number of private keys will only grow in the future.

The solution

The solution is hidden in the ssh client documentation. The excerpt of rather cryptic ssh man text for the -i option:

…If no certificates have been explicitly specified by the CertificateFile directive, ssh will also try to load certificate information from the filename obtained by appending -cert.pub to identity filenames.

Which apparently means that if the private key is not found and I can specify the public key which will be used to identify the private key in the ssh-agent key list.

In addition to the -i option you need to specify the ssh IdentitiesOnly option. This will be used when multiple different identities are offered by ssh-agent. Here is a text from the ssh_config man pages:

IdentitiesOnly

Specifies that ssh(1) should only use the configured authentication identity and certificate files (either the default files, or those explicitly configured in the ssh_config files or passed on the ssh(1) command-line), even if ssh-agent(1) or a PKCS11Provider or SecurityKeyProvider offers more identities. The argument to this keyword must be yes or no (the default). This option is intended for situations where ssh-agent offers many different identities.

The manual way

The ssh connection from shell to sshd server using the identified key will look like this (the private key is stored at ssh-agent and loaded from KeePassXC):

ssh -i server.pub -o IdentitiesOnly=yes server

The ssh config way (preferred by me)

If you do not want to type all the parameters all the time and remember which public key belongs to the correct private key, you can use the ~/.ssh/config file to store the connection details with options like this:

1
2
3
4
5
6
7
8
Host <alias>
    HostName <ip> or <hostname>
    User <user>
    Port <used port>
    IdentitiesOnly=yes
    IdentityFile ~/.ssh/server.pub
    LogLevel INFO
    Compression yes
This post is licensed under CC BY 4.0 by the author.