将 www.github.com 添加到 known_hosts 文件的 secure/correct 方法是什么?

What is the secure/correct way of adding www.github.com to the known_hosts file?

我想通过 ssh 访问我的 github 存储库。当我第一次访问存储库时,系统会询问我是否要将 github ssh 服务器添加到我的 known_hosts 文件中,这工作正常。该请求还向我显示了该服务器的 RSA 密钥指纹,我可以手动验证它是否与 github here.

提供的相同

These are the SHA256 hashes shown in OpenSSH 6.8 and newer (in base64 format):

SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8 (RSA)
SHA256:br9IjFspm1vxR3iA35FWE+4VTyz1hYVLIE2t1/CeyWQ (DSA)

问题是我想通过添加 public 键来阻止该请求 在我第一次访问我的 git 存储库之前到我的 known_hosts 文件。这可以通过使用 ssh-keyscan -t rsa www.github.com 命令来完成,该命令将以 known_hosts 文件所需的格式给我一个 public 密钥。但是人们反复提到,这不安全并且容易受到中间人攻击。他们没有提到的是如何正确地做。

那么如何使用github页面提供的RSA指纹安全获取ssh服务器的public主机密钥呢?我或多或少正在寻找 ssh-keyscan 命令的选项,它允许我添加预期的 rsa 指纹,并在主机指纹与给定指纹不匹配时导致命令失败。

感谢您的宝贵时间!

在那种情况下我会使用ssh-keyscan。
相反,我会通过将其指纹与 GitHub.

提供的指纹进行比较来使用它 and double-check 结果

然后继续 SSH GitHub test,检查我是否得到:

Hi username! You've successfully authenticated, but GitHub does not
provide shell access.

所以,as recommended here,对于手动过程:

ssh-keyscan github.com >> githubKey

生成指纹:

ssh-keygen -lf githubKey

与GitHub

提供的对比

最后,将 githubKey 内容复制到您的 ~/.ssh/known_hosts 文件。


您可以使用 wercker/step-add-to-known_hosts: it is a wercker step 自动执行该过程(仍然包括指纹步骤检查),但可以推断为它自己的独立脚本。

- add-to-known_hosts:
    hostname: github.com
    fingerprint: 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48
    type: rsa

但这将缺少针对 help.github.com/articles/github-s-ssh-key-fingerprints 的检查:见下文。


使用nmap does not help much, as explained here:

using nmap to get the SSH host key fingerprint and then comparing it to what ssh-keyscan says the fingerprint: In both cases, the fingerprint comes from the same place.
It's just as vulnerable to MITM as any other of these automated solutions.

The only secure and valid way to verify an SSH public key is over some trusted out-of-band channel. (Or set up some kind of key-signing infrastructure.)

在这里,help.github.com/articles/github-s-ssh-key-fingerprints 仍然是 "trusted out-of-band channel"。

根据VonC的回答,下面的脚本可以自动验证和添加密钥。像这样使用它:

$ ./add-key.sh github.com nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8

告诉你是否成功验证并保存了指纹。
有关使用信息,请使用 ./add-key.sh --help

脚本:

#!/usr/bin/env bash

# Settings
knownhosts="$HOME/.ssh/known_hosts"

if [ "x" == "x-h" ] || [ "x" == "x--help" ] || [ ${#1} == 0 ]; then
    echo "Usage: [=11=] <host> <fingerprint> [<port>]"
    echo "Example: [=11=] github.com nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8"
    echo "The default port is 22."
    echo "The script will download the ssh keys from <host>, check if any match"
    echo "the <fingerprint>, and add that one to $knownhosts."
    exit 1
fi

# Argument handling
host=
fingerprint=
port=$(if [ -n "" ]; then echo ""; else echo 22; fi)

# Download the actual key (you cannot convert a fingerprint to the original key)
keys="$(ssh-keyscan -p $port $host |& grep -v ^\#)";
echo "$keys" | grep -v "^$host" # Show any errors
keys="$(echo "$keys" | grep "^$host")"; # Remove errors from the variable
if [ ${#keys} -lt 20 ]; then echo Error downloading keys; exit 2; fi

# Find which line contains the key matching this fingerprint
line=$(ssh-keygen -lf <(echo "$keys") | grep -n "$fingerprint" | cut -b 1-1)

if [ ${#line} -gt 0 ]; then  # If there was a matching fingerprint (todo: shouldn't this be -ge or so?)
    # Take that line
    key=$(head -$line <(echo "$keys") | tail -1)
    # Check if the key part (column 3) of that line is already in $knownhosts
    if [ -n "$(grep "$(echo "$key" | awk '{print }')" $knownhosts)" ]; then
        echo "Key already in $knownhosts."
        exit 3
    else
        # Add it to known hosts
        echo "$key" >> $knownhosts
        # And tell the user what kind of key they just added
        keytype=$(echo "$key" | awk '{print }')
        echo Fingerprint verified and $keytype key added to $knownhosts
    fi
else  # If there was no matching fingerprint
    echo MITM? These are the received fingerprints:
    ssh-keygen -lf <(echo "$keys")
    echo Generated from these received keys:
    echo "$keys"
    exit 1
fi

我的一行允许在失败时报告错误:

touch ~/.ssh/known_hosts && if [ $(grep -c 'github.com ssh-rsa' ~/.ssh/known_hosts) -lt 1 ]; then KEYS=$(KEYS=$(ssh-keyscan github.com 2>&1 | grep -v '#'); ssh-keygen -lf <(echo $KEYS) || echo $KEYS); if [[ $KEYS =~ '(RSA)' ]]; then if [ $(curl -s https://help.github.com/en/github/authenticating-to-github/githubs-ssh-key-fingerprints | grep -c $(echo $KEYS | awk '{print }')) -gt 0 ]; then echo '[GitHub key successfully verified]' && ssh-keyscan github.com 1>~/.ssh/known_hosts; fi; else echo \"ssh-keygen -lf failed:\n$KEYS\"; exit 1; fi; unset KEYS; fi