我想通过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指纹,并且如果主机指纹与给定的指纹不匹配,则导致命令失败。
感谢您的时间!
答案 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