How to Debug OpenSSH Public Key Authentication Failures with Detailed Logging


2 views

When your SSH server silently falls back to password authentication despite having properly configured keys, you're witnessing one of the most frustrating OpenSSH behaviors. The default logging won't tell you why the key was rejected - just that it happened. Here's how to extract the real reasons.

First, ensure your /etc/ssh/sshd_config contains these critical settings:

# Minimum required for debugging:
LogLevel VERBOSE
PubkeyAuthentication yes
AuthenticationMethods publickey,password

# Additional debug options:
ChallengeResponseAuthentication no
PasswordAuthentication yes # Temporarily enable for testing

Restart sshd with sudo systemctl restart sshd after changes.

The Failed publickey log entry you see is just the symptom. To get the root cause, we need additional logging parameters. Add this to your sshd_config:

# Extended debug logging
LogLevel DEBUG3
StrictModes yes

Here are typical failure modes and how to identify them:

# 1. Permission issues (most common)
Nov  1 10:15:22 server sshd[12345]: Authentication refused: bad ownership or modes for directory /home/user/.ssh

# Solution:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R user:user ~/.ssh
# 2. SELinux context problems
Nov  1 10:17:45 server sshd[12346]: fatal: bad ownership or modes for context user_u:object_r:ssh_home_t:s0

# Solution:
restorecon -R -v ~/.ssh

Enable verbose output on the client:

ssh -vvv user@host

Key things to check in client output:

debug1: Server accepts key: pkalg ssh-rsa blen 279
debug2: input_userauth_pk_ok: fp SHA256:xxxxxx
debug3: sign_and_send_pubkey: RSA SHA256:xxxxxx
debug1: Authentication succeeded (publickey)

For temporary deep debugging without config changes:

sudo /usr/sbin/sshd -d -p 2222

Then connect with:

ssh -p 2222 user@host

The -d flag makes sshd run in foreground with maximum debug output.

Here's a quick script to verify all permission requirements:

#!/bin/bash
check_ssh_perms() {
  local dir="$1"
  [ "$(stat -c %a "$dir")" == "700" ] || echo "Bad .ssh permissions"
  [ "$(stat -c %a "$dir/authorized_keys")" == "600" ] || echo "Bad authorized_keys permissions"
  [ "$(stat -c %U:%G "$dir")" == "$USER:$USER" ] || echo "Bad ownership"
}
check_ssh_perms ~/.ssh

Remember that SSH is extremely sensitive to file permissions and ownership. Even subtle differences can cause silent failures.


When troubleshooting SSH public key authentication failures, the default OpenSSH logging often leaves us with frustratingly vague messages like "Failed publickey" without revealing the underlying cause. Let's explore how to extract meaningful diagnostics from sshd.

First, ensure your /etc/ssh/sshd_config contains these critical settings:

# Minimum required for detailed logging
LogLevel VERBOSE
SyslogFacility AUTH

# For extreme debugging (temporary use only!)
#LogLevel DEBUG3
#AuthenticationMethods publickey,password

SSH is notoriously strict about file permissions. Here's how to verify them:

# On the server:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod 755 ~

# On the client:
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub

For deeper inspection, run sshd in debug mode:

sudo /usr/sbin/sshd -d -p 2222

Then connect with:

ssh -vvv -p 2222 user@host

Here are typical rejection reasons and their solutions:

# 1. Key format mismatch
sshd[1234]: userauth_pubkey: key type ssh-rsa not in PubkeyAcceptedKeyTypes

# Fix: Update sshd_config with:
PubkeyAcceptedKeyTypes ssh-rsa,rsa-sha2-256,rsa-sha2-512

# 2. SELinux context issue
sshd[1234]: Authentication refused: bad ownership or modes

# Fix:
restorecon -Rv ~/.ssh

Use this grep command to extract meaningful authentication attempts:

grep -E "sshd.*(Failed|Accepted|Invalid|Did not|Found)" /var/log/auth.log

Always combine server logs with client-side verbosity:

ssh -vvv user@host 2>&1 | grep -A10 "Offering public key"

Create this validation script on your server:

#!/bin/bash
KEY=$(ssh-keygen -lf $1 | awk '{print $2}')
grep "$KEY" ~/.ssh/authorized_keys || echo "Key not found"
stat -c "%a %U:%G %n" ~/.ssh ~/.ssh/authorized_keys ~