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.