将www.github.com添加到known_hosts文件的安全/正确方法是什么?

时间:2018-04-05 10:39:30

标签: github ssh openssh

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

  

这些是OpenSSH 6.8及更新版本(以base64格式)显示的SHA256哈希:

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

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

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

感谢您的时间!

3 个答案:

答案 0 :(得分:6)

在这种情况下,我会使用ssh-keyscan 相反,我会使用通过将其指纹与GitHub提供的指纹进行比较来仔细检查结果。

然后继续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自动执行该过程(仍然包括指纹步骤检查):它是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 并没有多大帮助,因为explained here

  

使用nmap获取SSH主机密钥指纹,然后将其与ssh-keyscan所述指纹进行比较:在这两种情况下,指纹都来自相同的位置。
  它与其他任何自动化解决方案一样容易受到MITM的攻击。

     

验证SSH公钥的唯一安全且有效的方法是通过某些受信任的带外通道。 (或者设置某种密钥签名基础设施。)

此处,help.github.com/articles/github-s-ssh-key-fingerprints仍然是“受信任的带外频道”。

答案 1 :(得分:2)

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

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

它还显示有关./add-key.sh --help

的帮助

它输出如下内容:

# If the fingerprint matched: 
Fingerprint verified and ecdsa-sha2-nistp256 key added to /home/user/.ssh/known_hosts

# If the fingerprint did not match:
MITM? These are the received fingerprints:
[...]

这是脚本:

#!/usr/bin/env bash

# Settings
knownhosts=$HOME/.ssh/known_hosts

if [ "x$1" == "x-h" ] || [ "x$1" == "x--help" ] || [ ${#1} == 0 ]; then
    echo "Usage: $0 <host> <fingerprint> [<port>]"
    echo "Example: $0 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=$1
fingerprint=$2
port=$(if [ -n "$3" ]; then echo "$3"; else echo 22; fi)

# Download the actual key (you cannot convert a fingerprint to the original key)
keys=$(ssh-keyscan -p $port $host 2> /dev/null);
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
    # 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 $3}')" $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 $2}')
        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

答案 2 :(得分:2)

我的一言以蔽之是允许对故障进行错误报告:

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 $2}')) -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