我可以自动添加一个新的主机到known_hosts?

这里是我的情况:我正在设置一个testing工具,从中央客户端启动一些虚拟机实例,然后通过ssh在它们上执行命令。 虚拟机将有以前未使用的主机名和IP地址,因此它们不会位于中央客户机上的~/.ssh/known_hosts文件中。

我遇到的问题是,对新虚拟实例运行的第一个ssh命令总是出现一个交互式提示符:

 The authenticity of host '[hostname] ([IP address])' can't be established. RSA key fingerprint is [key fingerprint]. Are you sure you want to continue connecting (yes/no)? 

有没有一种方法可以绕过这一点,让客户机已经知道新的主机,也许通过使用已经映射到虚拟机映像的公共密钥? 如果可以的话,我真的想避免使用Expect或其他方法来回答交互式提示。

StrictHostKeyChecking选项设置为no ,或者在configuration文件中或通过-o

ssh -o StrictHostKeyChecking=no [email protected]

国际海事组织,这样做的最好方法是:

 ssh-keygen -R [hostname] ssh-keygen -R [ip_address] ssh-keygen -R [hostname],[ip_address] ssh-keyscan -H [hostname],[ip_address] >> ~/.ssh/known_hosts ssh-keyscan -H [ip_address] >> ~/.ssh/known_hosts ssh-keyscan -H [hostname] >> ~/.ssh/known_hosts 

这将确保没有重复的条目,主机名和IP地址都被覆盖,并且也会散列输出,这是一种额外的安全措施。

对于懒惰的人:

 ssh-keyscan <host> >> ~/.ssh/known_hosts 

如前所述,使用键盘扫描是正确和不引人注目的方法。

 ssh-keyscan -t rsa,dsa HOST 2>&1 | sort -u - ~/.ssh/known_hosts > ~/.ssh/tmp_hosts mv ~/.ssh/tmp_hosts ~/.ssh/known_hosts 

如果还没有添加主机,上述操作只能添加一个主机。 这也不是并发安全的; 您不能同时在同一台机器上执行多次,因为tmp_hosts文件可能会被破坏,最终导致known_hosts文件变得臃肿…

您可以使用ssh-keyscan命令来获取公钥并将其附加到您的known_hosts文件中。

这就是你如何将ssh-keyscan整合到你的游戏中:

 --- # ansible playbook that adds ssh fingerprints to known_hosts - hosts: all connection: local gather_facts: no tasks: - command: /usr/bin/ssh-keyscan -T 10 {{ ansible_host }} register: keyscan - lineinfile: name=~/.ssh/known_hosts create=yes line={{ item }} with_items: '{{ keyscan.stdout_lines }}' 

这将是一个完整的解决scheme,首次接受主机密钥

 #!/usr/bin/env ansible-playbook --- - name: accept ssh fingerprint automatically for the first time hosts: all connection: local gather_facts: False tasks: - name: "check if known_hosts contains server's fingerprint" command: ssh-keygen -F {{ inventory_hostname }} register: keygen failed_when: keygen.stderr != '' changed_when: False - name: fetch remote ssh key command: ssh-keyscan -T5 {{ inventory_hostname }} register: keyscan failed_when: keyscan.rc != 0 or keyscan.stdout == '' changed_when: False when: keygen.rc == 1 - name: add ssh-key to local known_hosts lineinfile: name: ~/.ssh/known_hosts create: yes line: "{{ item }}" when: keygen.rc == 1 with_items: '{{ keyscan.stdout_lines|default([]) }}' 

我有一个类似的问题,发现一些提供的答案只能让我成为自动化解决scheme的一部分。 以下是我最终使用,希望它可以帮助:

 ssh -o "StrictHostKeyChecking no" -o PasswordAuthentication=no 10.xxx 

它将关键字添加到known_hosts ,不会提示input密码。

所以,我正在寻找一种世俗的方式来绕过克隆git仓库的未知主机手动交互,如下所示:

 brad@computer:~$ git clone [email protected]:viperks/viperks-api.git Cloning into 'viperks-api'... The authenticity of host 'bitbucket.org (104.192.143.3)' can't be established. RSA key fingerprint is 97:8c:1b:f2:6f:14:6b:5c:3b:ec:aa:46:46:74:7c:40. Are you sure you want to continue connecting (yes/no)? 

请注意RSA密钥指纹…

所以,这是一个SSH的东西,这将适用于通过SSH的SSH和只是SSH相关的东西一般…

 brad@computer:~$ nmap bitbucket.org --script ssh-hostkey Starting Nmap 7.01 ( https://nmap.org ) at 2016-10-05 10:21 EDT Nmap scan report for bitbucket.org (104.192.143.3) Host is up (0.032s latency). Other addresses for bitbucket.org (not scanned): 104.192.143.2 104.192.143.1 2401:1d80:1010::150 Not shown: 997 filtered ports PORT STATE SERVICE 22/tcp open ssh | ssh-hostkey: | 1024 35:ee:d7:b8:ef:d7:79:e2:c6:43:9e:ab:40:6f:50:74 (DSA) |_ 2048 97:8c:1b:f2:6f:14:6b:5c:3b:ec:aa:46:46:74:7c:40 (RSA) 80/tcp open http 443/tcp open https Nmap done: 1 IP address (1 host up) scanned in 42.42 seconds 

首先,在你的日常驱动上安装nmap。 nmap对于某些事情非常有帮助,比如检测开放端口和手动validationSSH指纹。 但是,回到我们正在做的。

好。 我要么在多个地方和我检查过的机器上妥协 – 要么就是发生了什么事情,对于一切正在发生的事情的更合理的解释。

这个“指纹”只是一个string缩短了一个单向algorithm,为了我们的人类方便,可能有多个string分解成相同的指纹。 碰巧,他们被称为碰撞。

无论如何,回到我们可以在下文中看到的原始string。

 brad@computer:~$ ssh-keyscan bitbucket.org # bitbucket.org SSH-2.0-conker_1.0.257-ce87fba app-128 no hostkey alg # bitbucket.org SSH-2.0-conker_1.0.257-ce87fba app-129 bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw== # bitbucket.org SSH-2.0-conker_1.0.257-ce87fba app-123 no hostkey alg 

所以,提前一点,我们有办法从原来的东道主请求一种身份certificate。

在这一点上,我们手动的就像自动化一样脆弱 – string匹配,我们有创build指纹的基础数据,我们可以在将来要求这些基础数据(防止碰撞)。

现在,以防止询问主机真实性的方式使用该string…

在这种情况下known_hosts文件不使用明文条目。 当你看到它们时,你会知道散列条目,它们看起来像随机字符散列,而不是xyz.com或123.45.67.89。

 brad@computer:~$ ssh-keyscan -t rsa -H bitbucket.org # bitbucket.org SSH-2.0-conker_1.0.257-ce87fba app-128 |1|yr6p7i8doyLhDtrrnWDk7m9QVXk=|LuKNg9gypeDhfRo/AvLTAlxnyQw= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw== 

第一条评论线令人愤慨地显示出来 – 但你可以通过“>”或“>>”惯例的简单redirect来摆脱它。

由于我已经尽了最大的努力来获取未被识别的数据来识别“主机”和信任,我将把这个标识添加到我的〜/ .ssh目录下的known_hosts文件中。 既然现在会被认定为已知的东道主,那么当你还是个年轻人的时候,我就不会得到上述的提示。

感谢你的支持,在这里,你走了。 我添加了bitbucket RSA密钥,这样我就可以作为CI工作stream程的一部分,以非交互方式与我的git存储库进行交互,但是无论你做什么都可以。

 #!/bin/bash cp ~/.ssh/known_hosts ~/.ssh/known_hosts.old && echo "|1|yr6p7i8doyLhDtrrnWDk7m9QVXk=|LuKNg9gypeDhfRo/AvLTAlxnyQw= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==" >> ~/.ssh/known_hosts 

所以,这就是你今天如何保持处女。 你可以按照你自己的时间遵循类似的方向,对github做同样的事情。

我看到这么多的堆栈溢出post告诉你以编程方式盲目添encryption钥没有任何forms的检查。 你从不同networking上的不同机器上检查密钥的次数越多,你就越能相信主机就是它所说的 – 而且这是你从这个安全层所能得到的最好结果。

错误 ssh -oStrictHostKeyChecking = no hostname [command]

错误 ssh-keyscan -t rsa -H hostname >>〜/ .ssh / known_hosts

请不要做上面的任何一件事。 您有机会通过中间人的攻击来增加避免窃听您的数据传输的机会 – 请抓住机会。 不同的是,从字面上validation您拥有的RSA密钥是真正的服务器之一,现在您知道如何获取该信息以进行比较,以便您可以信任该连接。 只要记住,来自不同计算机和networking的更多比较通常会增加您信任连接的能力。

为了做到这一点,你真正想要做的是收集虚拟机的主机公钥,并创build它们,并以known_hosts格式将其放入文件中。 然后,您可以使用-o GlobalKnownHostsFile=...指向该文件,以确保您连接到您认为应该连接到的主机。 如何做到这一点取决于你如何设置虚拟机,但是,如果可能的话,从虚拟文件系统读取它,甚至让主机在configuration期间打印/etc/ssh/ssh_host_rsa_key.pub的内容做的伎俩。

也就是说,这可能是不值得的,这取决于你在什么样的环境下工作,以及你的预期对手是谁。 在上面的几个其他答案中描述的做一个简单的“首次连接存储”(通过扫描或者简单地在第一次“真实”连接期间)可能相当容易,并且仍然提供一些小的安全性。 但是,如果您这样做,我强烈build议您将用户已知的主机文件( -o UserKnownHostsFile=... )更改为特定于此特定testing安装的文件; 这将避免污染你的个人已知的主机文件与testing信息,并且可以很容易地清理现在无用的公共密钥,当你删除你的虚拟机。

我做了一个单线程的脚本,有点长,但是对于有多个IP的主机来说这个任务是有用的,用digbash

 (host=github.com; ssh-keyscan -H $host; for ip in $(dig @8.8.8.8 github.com +short); do ssh-keyscan -H $host,$ip; ssh-keyscan -H $ip; done) 2> /dev/null >> .ssh/known_hosts 

以下避免〜/ .ssh / known_hosts中的重复条目:

 if ! grep "$(ssh-keyscan github.com 2>/dev/null)" ~/.ssh/known_hosts > /dev/null; then ssh-keyscan github.com >> ~/.ssh/known_hosts fi 

这整个

  • SSH密钥扫描
  • SSH-copy-id命令
  • ECSDA重要警告

生意不停地烦我,所以我select了

一个脚本来统治他们

这是https://askubuntu.com/a/949731/129227上的一个变体,Amadu Bah的回答是https://serverfault.com/a/858957/162693

示例调用

./sshcheck somedomain site1 site2 site3

该脚本将遍布名称网站和修改.ssh / config和.ssh / known_hosts文件,并根据请求做ssh-copy-id – 对于最后一个function,让sshtesting调用失败,例如通过点击input3次密码请求。

sshcheck脚本

 #!/bin/bash # WF 2017-08-25 # check ssh access to bitplan servers #ansi colors #http://www.csc.uvic.ca/~sae/seng265/fall04/tips/s265s047-tips/bash-using-colors.html blue='\033[0;34m' red='\033[0;31m' green='\033[0;32m' # '\e[1;32m' is too bright for white bg. endColor='\033[0m' # # a colored message # params: # 1: l_color - the color of the message # 2: l_msg - the message to display # color_msg() { local l_color="$1" local l_msg="$2" echo -e "${l_color}$l_msg${endColor}" } # # error # # show an error message and exit # # params: # 1: l_msg - the message to display error() { local l_msg="$1" # use ansi red for error color_msg $red "Error: $l_msg" 1>&2 exit 1 } # # show the usage # usage() { echo "usage: $0 domain sites" exit 1 } # # check known_hosts entry for server # checkknown() { local l_server="$1" #echo $l_server local l_sid="$(ssh-keyscan $l_server 2>/dev/null)" #echo $l_sid if (! grep "$l_sid" $sknown) > /dev/null then color_msg $blue "adding $l_server to $sknown" ssh-keyscan $l_server >> $sknown 2>&1 fi } # # check the given server # checkserver() { local l_server="$1" grep $l_server $sconfig > /dev/null if [ $? -eq 1 ] then color_msg $blue "adding $l_server to $sconfig" today=$(date "+%Y-%m-%d") echo "# added $today by $0" >> $sconfig echo "Host $l_server" >> $sconfig echo " StrictHostKeyChecking no" >> $sconfig echo " userKnownHostsFile=/dev/null" >> $sconfig echo "" >> $sconfig checkknown $l_server else color_msg $green "$l_server found in $sconfig" fi ssh -q $l_server id > /dev/null if [ $? -eq 0 ] then color_msg $green "$l_server accessible via ssh" else color_msg $red "ssh to $l_server failed" color_msg $blue "shall I ssh-copy-id credentials to $l_server?" read answer case $answer in y|yes) ssh-copy-id $l_server esac fi } # # check all servers # checkservers() { me=$(hostname -f) for server in $(echo $* | sort) do os=`uname` case $os in # Mac OS X Darwin*) pingoption=" -t1";; *) ;; esac pingresult=$(ping $pingoption -i0.2 -c1 $server) echo $pingresult | grep 100 > /dev/null if [ $? -eq 1 ] then checkserver $server checkserver $server.$domain else color_msg $red "ping to $server failed" fi done } # # check configuration # checkconfig() { #https://askubuntu.com/questions/87449/how-to-disable-strict-host-key-checking-in-ssh if [ -f $sconfig ] then color_msg $green "$sconfig exists" ls -l $sconfig fi } sconfig=~/.ssh/config sknown=~/.ssh/known_hosts case $# in 0) usage ;; 1) usage ;; *) domain=$1 shift color_msg $blue "checking ssh configuration for domain $domain sites $*" checkconfig checkservers $* #for server in $(echo $* | sort) ##do # checkknown $server #done ;; esac 

你怎么build造这些机器? 你可以运行一个DNS更新脚本? 你可以joinIPA域名吗?

FreeIPA自动执行此操作,但基本上所有您需要的是SSHFP DNS区域上的logging和DNSSEC (freeipa提供了可configuration的选项(默认禁用dnssec))。

您可以通过运行从主机获取现有的SSHFPlogging。

ssh-keygen -r jersey.jacobdevans.com

jersey.jacobdevans.com IN SSHFP 1 1 4d8589de6b1a48e148d8fc9fbb967f1b29f53ebc jersey.jacobdevans.com IN SSHFP 1 2 6503272a11ba6d7fec2518c02dfed88f3d455ac7786ee5dbd72df63307209d55 jersey.jacobdevans.com IN SSHFP 3 1 5a7a1e8ab8f25b86b63c377b303659289b895736> jersey.jacobdevans.com IN SSHFP 3 2 1f50f790117dfedd329dbcf622a7d47551e12ff5913902c66a7da28e47de4f4b

然后一旦发布,你会添加VerifyHostKeyDNS yes到你的ssh_config或〜/ .ssh / config

如果/当谷歌决定在DNSSEC上翻转时,您可以在没有主机密钥提示的情况下ssh。

ssh jersey.jacobdevans.com

但我的域名尚未签名,所以现在你会看到….

debug1:服务器主机密钥:ecdsa-sha2-nistp256 SHA256:H1D3kBF9 / t0ynbz2IqfUdVHhL / WROQLGan2ijkfeT0s

debug1:在DNS中发现4个不安全的指纹

debug1:匹配主机密钥指纹

在DNS中find主机“jersey.jacobdevans.com(2605:6400:10:434 :: 10)”的真实性无法build立。 ECDSA密钥指纹是SHA256:H1D3kBF9 / t0ynbz2IqfUdVHhL / WROQLGan2ijkfeT0s。 匹配在DNS中find的主机密钥指纹。 你确定要继续连接(是/否)吗? 没有