How to Prevent SSH Client from Offering All Public Keys During Authentication


2 views

As a sysadmin working with multiple servers, I maintain separate SSH keys for different hosts in my ~/.ssh/ directory. However, this creates an authentication challenge when connecting to a new host for the first time using password authentication.

The OpenSSH client's default behavior is to offer all available public keys during the authentication process. You can observe this by running:

ssh -v user@hostname

The verbose output will show lines like:

debug1: Offering public key: /home/user/.ssh/id_rsa RSA SHA256:...
debug1: Offering public key: /home/user/.ssh/id_ed25519 ED25519 SHA256:...

When you have numerous keys (in my case, about a dozen), the server may disconnect you after several failed authentication attempts before you even get to password authentication. This happens because:

  • Each key offer counts as an authentication attempt
  • Servers often limit consecutive failed attempts (typically 5-6)
  • The process never reaches password authentication phase

OpenSSH provides several ways to control which keys are presented during authentication:

Method 1: Using -o IdentitiesOnly=yes

The most straightforward solution is to use the IdentitiesOnly option:

ssh -o IdentitiesOnly=yes user@hostname

This tells SSH to only use keys explicitly specified in the command or configuration file.

Method 2: Specifying a Single Key

You can combine IdentitiesOnly with the -i flag to specify exactly one key:

ssh -o IdentitiesOnly=yes -i ~/.ssh/specific_key user@hostname

Method 3: Permanent Configuration

For regular hosts, add this to your ~/.ssh/config:

Host specific-host
    HostName host.example.com
    User username
    IdentitiesOnly yes
    IdentityFile ~/.ssh/specific_key

For more complex scenarios, you can create a wrapper script that dynamically selects keys based on the host:

#!/bin/bash

host=$1
keyfile=""

case $host in
    *.prod.example.com) keyfile="~/.ssh/prod_key" ;;
    *.dev.example.com)  keyfile="~/.ssh/dev_key" ;;
    *)                  keyfile="" ;;
esac

if [ -n "$keyfile" ]; then
    ssh -o IdentitiesOnly=yes -i "$keyfile" "$host"
else
    ssh -o IdentitiesOnly=yes "$host"
fi

If you're still having issues, these commands help diagnose authentication flow:

# Check which keys are being offered
ssh -v user@hostname 2>&1 | grep "Offering public key"

# Test password authentication directly
ssh -o PreferredAuthentications=password user@hostname

Remember that server-side settings in /etc/ssh/sshd_config like MaxAuthTries and PubkeyAuthentication can also affect this behavior.


When working with multiple SSH keys (a common practice among security-conscious sysadmins), you might encounter this frustrating scenario:

debug1: Offering public key: /home/user/.ssh/id_rsa_host1 RSA SHA256:...
debug1: Offering public key: /home/user/.ssh/id_rsa_host2 RSA SHA256:...
debug1: Offering public key: /home/user/.ssh/id_rsa_host3 RSA SHA256:...
...
Received disconnect from 192.168.1.100 port 22:2: Too many authentication failures

By default, OpenSSH client (ssh) will try all identity files in ~/.ssh/ that match id_*.pub patterns when attempting authentication. This behavior becomes problematic when:

  • You have numerous SSH keys
  • Server has MaxAuthTries set to a low value
  • You specifically want password authentication

1. Temporary Solution: Single Command Flag

For one-time password authentication:

ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no user@host

2. Permanent Configuration

Add this to your ~/.ssh/config for specific hosts:

Host legacy-server
    HostName 192.168.1.100
    User admin
    PreferredAuthentications password
    PubkeyAuthentication no

3. Selective Key Presentation

If you still want to offer some keys but not all:

Host github.com
    IdentityFile ~/.ssh/github_key
    IdentitiesOnly yes

Match Blocks for Conditional Logic

Match host *.example.com user admin
    PasswordAuthentication yes
    PubkeyAuthentication no

SSH Agent Control

When using ssh-agent, you can remove all keys temporarily:

ssh-add -D  # Remove all keys from agent
ssh user@host  # Now will only prompt for password
ssh-add ~/.ssh/your_key  # Restore specific key afterward

Always verify your configuration with:

ssh -G hostname | grep -i authentication

And remember that server-side settings in /etc/ssh/sshd_config like MaxAuthTries can affect this behavior.