题 我可以自动将新主机添加到known_hosts吗?


这是我的情况:我正在设置一个测试工具,从中央客户端启动一些虚拟机实例,然后通过它们执行命令 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或其他什么来回答交互式提示。


217
2018-04-16 04:15




对于自包含且物理安全的测试环境,自动密钥接受可以正常工作。但是,在生产环境或不受信任的网络(例如Internet)中自动接受公钥会完全绕过对SSH可能提供的中间人攻击的任何保护。该 只要 确保您对MITM攻击安全的有效方法是通过一些带外可信通道验证主机的公钥。没有设置适度复杂的密钥签名基础设施,就没有安全的方法来实现自动化。 - Eil


答案:


设置 StrictHostKeyChecking 选项 no,无论是在配置文件中还是通过 -o :

ssh -o StrictHostKeyChecking=no username@hostname.com


126
2018-04-16 04:34



这让你在中间攻击中对人开放,可能不是一个好主意。 - JasperWallace
@JasperWallace虽然这通常是很好的建议,但具体的用例(部署测试虚拟机并向其发送命令)应该足够安全。 - Massimo
这给了一个 Warning: Permanently added 'hostname,1.2.3.4' (RSA) to the list of known hosts. 为了避免警告,并避免将条目添加到任何known_hosts文件,我做: ssh -o StrictHostKeyChecking=no -o LogLevel=ERROR -o UserKnownHostsFile=/dev/null username@hostname.com - Peter V. Mørch
Downvoting,因为这不回答问题,并打开严重的安全漏洞。 - marcv81
@Mnebuerquo:如果你担心安全性,那么你就不会有任何关于这个问题的事情了。您将拥有正确的主机密钥,从您想要连接的系统的控制台收集,并在首次连接时手动验证它。你肯定不会“自动”做任何事情。 - Ignacio Vazquez-Abrams


IMO,最好的方法是:

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地址都包含在内,并且还会对输出进行哈希处理,这是一项额外的安全措施。


209
2017-09-27 20:51



为什么你需要所有3个ssh-keyscan?你不能只用第一个,因为它适用于主机名和IP? - Robert
您能确定回复ssh-keyscan请求的机器真的是您要与之交谈的机器吗?如果不是,你已经向中间人攻​​击了一个人。 - JasperWallace
@JasperWallace是的,因为你需要至少指纹或更好的公钥,在这种情况下你可以直接将它添加到known_hosts,这个问题没有实际意义。如果您只有指纹,则必须编写一个额外的步骤,用指纹验证下载的公钥...
打电话给 ssh-keyscan 因为我的目标主机不支持默认版本1密钥类型而失败了。添加 -t rsa,dsa 修复此命令。 - phasetwenty
这可能是一个坏主意。您可以通过更新这些密钥来打开自己的中间人攻击。为避免重复输入,请检查返回状态 ssh-keygen -F [address] 代替。 medium.com/@wblankenship/... - retrohacker


对于懒惰的人:

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

78
2017-09-25 10:03



被指控罪名为+1。谢谢。 - SaxDaddy
易受MITM攻击。你没有检查密钥指纹。 - Mnebuerquo
@Mnebuerquo你说要做什么但不怎么做,这会有所帮助。 - Jim
@jameshfisher是的,它很容易受到MITM攻击,但你有没有比较过手动执行此操作时显示给你的RSA指纹与实际服务器的指纹?没有?所以这个答案就是为你做这件事的方法。如果是,您不应该使用此答案并手动执行或实施其他安全措施...... - fivef
@Mnebuerquo如果你还让我们知道一个更好的方法来解决这个问题,当我们需要使用没有参加的批处理脚本克隆一个repo并且我们想绕过这个提示时,我会很高兴。如果您认为这不是正确的解决方案,请详细说明真正的解决方案! - Waqas Shah


如上所述,使用按键扫描将是正确且不显眼的方式。

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文件变得臃肿......


38
2018-03-06 09:00



有没有办法检查密钥是否在known_hosts中 之前  ssh-keyscan?原因是它需要一些时间和额外的网络连接。 - utapyngo
这个文件的原始海报版本有 cat ~/.ssh/tmp_hosts > ~/.ssh/known_hosts,但随后的编辑将其更改为 >>。运用 >> 是一个错误。它违背了第一行中唯一性的目的,并使其转储新条目 known_hosts每次运行。 (刚刚发布了一个编辑以将其更改回来。) - paulmelnikow
这与其他人一样受到MITM攻击。 - Mnebuerquo
@utapyngo ssh-keygen -F将为您提供当前指纹。如果它返回空白,返回代码为1,那么你没有它。如果它打印出某些内容并且返回代码为0,则它​​已经存在。 - Rich L
如果您非常关心MITM,请部署DNSSEC和SSHFP记录或使用其他一些安全的方式来分发密钥,这种kludge解决方案将无关紧要。 - Zart


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


18
2018-04-16 05:09



确保检查指纹以确保它是正确的密钥。否则你会打开自己的MITM攻击。 - Mnebuerquo
@Mnebuer在一般情况下公平点,但为什么有人会尝试以编程方式收集密钥,如果他们已经知道正确的密钥是什么? - Brian Cline
这不是这样做的方法。 MITM。 - jameshfisher


这就是你如何融入的 SSH-键扫描 进入你的游戏:

---
# 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 }}'

6
2018-02-03 03:12



您是在上传已知的有效known_hosts文件,还是正在执行ssh-keyscan并将输出转储到known_hosts而不验证指纹? - Mnebuerquo
这只是转储键扫描的输出,是的。所以实际上它与StrictHostKeyChecking = no相同,只是使用静默的known_hosts更新而不用摆弄ssh选项。此解决方案也无法正常工作,因为ssh-keys可以返回多行,导致此任务始终标记为“已更改” - Zart
这不是这样做的方法。 MITM。 - jameshfisher
@jameshfisher如果你还让我们知道一个更好的方法来解决这个问题,当我们需要使用没有参加的批处理脚本克隆一个repo而我们想要绕过这个提示时,我会很高兴。如果您认为这不是正确的解决方案,请详细说明真正的解决方案!如果您认为这不是正确的方法,请告诉我们“如何”做到这一点! - Waqas Shah


我有一个类似的问题,发现一些提供的答案只让我对自动化解决方案有所帮助。以下是我最终使用的内容,希望它有所帮助:

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

它增加了关键 known_hosts 并且不会提示输入密码。


5
2017-10-21 17:27



易受MITM攻击。你没有检查指纹。 - Mnebuerquo
没有人检查指纹。 - Brendan Byrd
这不是这样做的方法。 MITM。 - jameshfisher


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

#!/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([]) }}'

5
2017-11-23 13:51



这不是这样做的方法。 MITM。 - jameshfisher


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

brad@computer:~$ git clone git@bitbucket.org: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的git和一般的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对某些事情非常有帮助,比如检测开放端口和这个 - 手动验证SSH指纹。但是,回到我们正在做的事情。

好。我要么在多个地方受到损害,要么我已经检查了机器 - 或者更为合理的解释一切都是正在发生的事情。

这个'指纹'只是一个字符串缩短了单向算法,为了我们人类的方便而存在多个字符串解析成相同指纹的风险。它发生了,它们被称为碰撞。

无论如何,回到我们在下面的上下文中可以看到的原始字符串。

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

所以,提前,我们有办法要求原始主机提供一种身份证明。

此时我们手动像自动一样易受攻击 - 字符串匹配,我们有创建指纹的基础数据,我们可以在将来要求提供基础数据(防止冲突)。

现在以一种阻止询问主机真实性的方式使用该字符串...

在这种情况下,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==

愤怒地显示第一条评论线 - 但你可以通过“>”或“>>”惯例通过简单的重定向来摆脱它。

由于我已尽力获取用于识别“主机”和信任的无污染数据,因此我将此标识添加到〜/ .ssh目录中的known_hosts文件中。由于它现在将被识别为已知主机,因此当您还是一名年轻人时,我不会得到上述提示。

谢谢你坚持我,你走了。我正在添加bitbucket RSA密钥,以便我可以以非交互方式与我的git存储库进行交互,作为CI工作流程的一部分,但无论你做什么都想做。

#!/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执行相同的操作。

我看到很多堆栈溢出帖子告诉你以编程方式盲目地添加密钥而不进行任何检查。您从不同网络上的不同计算机检查密钥的次数越多,您可以拥有的信任就越多,主机就是它所说的那个 - 这是您可以从这一层安全性中获得的最佳信息。

错误 ssh -oStrictHostKeyChecking =没有主机名[command]

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

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


4
2017-10-05 21:18



我认为这是解决这个问题的最佳方法。但是,在像Amazon EC2这样的东西上使用Nmap时要非常小心,我收到了关于Nmap端口扫描的警告!在进行端口扫描之前填写表格! - Waqas Shah
......好吧,是的。我不知道你为什么要从EC2进行端口扫描。如果您已登录到您的帐户,则可以从实际计算机获取密钥。这更适用于您无法控制的机器。我认为您将使用不受AWS端口扫描限制的本地计算机。但是,如果您处于必须使用AWS运行nmap的边缘情况,我认为此警告会有所帮助。 - BradChesney79
使用nmap从工作站读取SSH主机密钥,然后信任该值与通过SSH连接并关闭StructHostKeyChecking没有什么不同。它同样容易受到中间人攻击。 - Micah R Ledbetter
... @ MicahRLedbetter这就是为什么我建议“来自不同计算机和网络的更多比较通常会增加你信任连接的能力”。但是,这是我的观点。如果您只从一组环境条件中检查目标主机,那么您如何知道任何差异?你有什么更好的建议吗? - BradChesney79
这是安全剧院。做一些复杂的事情来创造更高安全性的外观。使用多少种不同的方法来询问主机的密钥并不重要。就像你可以信任他们一样多次询问同一个人(也许你打电话,发电子邮件,发短信和蜗牛邮件)。他们总是会说是,但如果你问错了人,那也没关系。 - vastlysuperiorman