Securely add a host (e.g. GitHub) to the SSH known_hosts file

Solution 1:

The most important part of "securely" adding a key to the known_hosts file is to get the key fingerprint from the server administrator. The key fingerprint should look something like this:

2048 SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8 github.com (RSA)

In the case of GitHub, normally we can't talk directly to an administrator. However, they put the key on their web pages so we can recover the information from there.

Manual key installation

1) Take a copy of the key from the server and get its fingerprint. N.B.: Do this before checking the fingerprint.

$ ssh-keyscan -t rsa github.com | tee github-key-temp | ssh-keygen -lf -
# github.com:22 SSH-2.0-babeld-f3847d63
2048 SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8 github.com (RSA)

2) Get a copy of the key fingerprint from the server administrator - in this case navigate to the page with the information on github.com

  1. Go to github.com
  2. Go to the help page (on the menu on the right if logged in; at the bottom of the homepage otherwise).
  3. In the Getting Started section go to Connecting to GitHub with SSH
  4. Go to Testing your SSH connection
  5. Copy the SHA256 fingerprint from that page into your text editor for later use.

3) Compare the keys from the two sources

By placing them directly one above the other in a text editor, it is easy to see if something has changed

2048 SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8 github.com (RSA) #key recovered from github website
2048 SHA256:nThbg6kXUpJ3Gl7E1InsaspRomtxdcArLviKaEsTGY8 github.com (RSA) #key recovered with keyscan

(Note that the second key has been manipulated, but it looks quite similar to the original - if something like this happens you are under serious attack and should contact a trusted security expert.)

If the keys are different abort the procedure and get in touch with a security expert

4) If the keys compare correctly then you should install the key you already downloaded

cat github-key-temp >> ~/.ssh/known_hosts

Or to install for all users on a system (as root):

cat github-key-temp >> /etc/ssh/ssh_known_hosts

Automated key installation

If you need to add a key during a build process then you should follow steps 1-3 of the manual process above.

Having done that, examine the contents of your github-key-temp file and make a script to add those contents to your known hosts file.

if ! grep github.com ~/.ssh/known_hosts > /dev/null
then
     echo "github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==" >> ~/.ssh/known_hosts
fi

You should now get rid of any ssh commands which have StrictHostKeyChecking disabled.

Solution 2:

You can mix hashed/unhashed entries in your known_hosts file.

So if you want to add github key, you can just do :

ssh-keyscan github.com >> ~/.ssh/known_hosts

If you want it hashed, add -H

ssh-keyscan -H github.com >> ~/.ssh/known_hosts


Solution 3:

The easiest way is to manually fetch the keys using ssh-keyscan, verify them manually:

$ ssh-keyscan -t rsa github.com | ssh-keygen -lf -
# github.com:22 SSH-2.0-libssh-0.7.0
2048 SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8 github.com (RSA)

And add them to your script, which will then carry the "authoritative" public key.


Solution 4:

I've wrote simple script (add_to_known_hosts) to handle this:

It won't create duplicate entries in known_hosts, and it will check if if fingerprint matches one provided as second argument.

#!/usr/bin/env bash
# First argument should be hostname (or IP)
# Second argument should be referential fingerprint
# Example: add_to_known_hosts github.com SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8

host=$1
fingerprint=$2

ip=$(getent hosts $1 | awk '{ print $1 }')
echo $ip

keys=$(ssh-keyscan -t rsa $host $ip)

# Iterate over keys (host and ip)
while IFS= read -r key; do
    # Extract Host name (or IP)
    key_host=$(echo $key | awk '{ print $1 }')

    # Extracting fingerprint of key
    key_fingerprint=$(echo $key | ssh-keygen -lf - | awk '{ print $2 }')

    # Check that fingerprint matches one provided as second parameter
    if [[ $fingerprint != $key_fingerprint ]]; then
      echo "Fingerprint match failed: '$fingerprint' (expected) != '$key_fingerprint' (got)";
      exit 1;
    fi

    # Add key to known_hosts if it doesn't exist
    if ! grep $key_host ~/.ssh/known_hosts > /dev/null
    then
       echo "Adding fingerprint $key_fingerprint for $key_host to ~/.ssh/known_hosts"
       echo $key >> ~/.ssh/known_hosts
    fi
done <<< "$keys"

Tags:

Ssh