How to Verify SSH Host Key Fingerprints via Command Line in OpenSSH


10 views

When automating SSH connections or scripting deployments, you often need to verify server identities without interactive prompts or pre-populated known_hosts files. While tools like WinSCP offer -hostkey parameters, OpenSSH's native client requires a different approach.

OpenSSH doesn't provide direct command-line fingerprint specification like some GUI clients. Instead, we use these methods:

# Method 1: Pre-populate known_hosts
ssh-keyscan -H your.server.com >> ~/.ssh/known_hosts

# Method 2: Strict hostkey checking with fingerprint verification
ssh -o "StrictHostKeyChecking=accept-new" \
    -o "HostKeyAlias=server-alias" \
    user@host

For strict production environments, consider these patterns:

#!/bin/bash
EXPECTED_FINGERPRINT="SHA256:AbCdEf123..."
ACTUAL_FINGERPRINT=$(ssh-keyscan -p 22 host.example.com 2>/dev/null | ssh-keygen -lf -)

if [ "$EXPECTED_FINGERPRINT" = "$ACTUAL_FINGERPRINT" ]; then
    ssh -o "StrictHostKeyChecking=yes" user@host.example.com
else
    echo "Fingerprint verification failed!" >&2
    exit 1
fi

When direct fingerprint verification isn't possible:

  • Use SSH certificates instead of host keys
  • Deploy via configuration management tools (Ansible/Puppet)
  • Create temporary known_hosts files for batch operations

When connecting to a remote server via SSH, OpenSSH automatically checks the server's host key against the ~/.ssh/known_hosts file. This security feature prevents man-in-the-middle attacks, but presents challenges in automation scenarios where:

  • You can't modify the user's known_hosts file
  • You don't want to blindly accept new keys (StrictHostKeyChecking=no)
  • You need to specify the expected fingerprint programmatically

While OpenSSH doesn't offer a direct command-line parameter like WinSCP's -hostkey, you can achieve similar security through these methods:

Method 1: Using SSH-keyscan with Verification

# First, get the actual fingerprint
ACTUAL_FP=$(ssh-keyscan -t rsa HOSTNAME 2>/dev/null | ssh-keygen -lf -)

# Compare with expected fingerprint
EXPECTED_FP="SHA256:ABC123...xyz"
if [ "$ACTUAL_FP" != "$EXPECTED_FP" ]; then
    echo "Host key verification failed!"
    exit 1
fi

# Proceed with connection
ssh user@HOSTNAME

Method 2: Temporary known_hosts File

# Create temporary known_hosts with your fingerprint
echo "HOSTNAME ssh-rsa AAAAB3NzaC1yc2E..." > /tmp/known_hosts

# Connect with custom known_hosts
ssh -o UserKnownHostsFile=/tmp/known_hosts \
    -o StrictHostKeyChecking=yes \
    user@HOSTNAME

For complex scenarios, create an SSH config entry:

Host myserver
    HostName server.example.com
    User myuser
    Match exec "grep -q '^server.example.com' ~/approved_hosts"
    StrictHostKeyChecking yes
    UserKnownHostsFile ~/approved_hosts

When implementing these solutions:

  • Always use SHA256 fingerprints (more secure than MD5)
  • Store expected fingerprints securely (not in scripts)
  • Consider certificate-based authentication for large deployments
  • Never disable host key checking completely