警告 -> 阅读此问题描述时请小心。我在写这个问题时有一些不正确的假设。请务必阅读我的回答,解释我错在哪里!
我在 AWS 中拥有主机 A 作为 EC2 实例。
我有一个嵌入在 .PEM 文件中的私钥,可以使用 SSH 密钥 Z 来托管 A。如果我使用参数将其传递给 ssh 命令-l
,并且如果我使用 关闭严格主机检查,则此方法有效-o StrictHostKeyChecking=no
。
我强烈希望保留严格的主机检查,即使我“知道”这是正确的主机,因为我正在与 AWS 接口交互,从他们那里获取 ip/dns,并且我在自己的小 VPC 世界中。
似乎提供指纹->主机映射的唯一方法是通过在文件中提供它known_hosts
。
那是对的吗?
如果这是正确的,我该如何获取我从 AWS 获取的 .PEM 文件中嵌入的私钥,并为单个指纹->主机映射构建正确的条目,以便known_hosts
我在登录 EC2 实例时可以读取临时文件?
我不想做的事
- 使用
ssh-keyscan
。这一切只是盲目地接受远程客户端的指纹,而不验证它是否与密钥匹配。我认为? - 关闭
StrictHostKeyChecking
。我想尽早建立良好的做法,我现在需要知道如何做到这一点,因为我将需要知道一般如何做到这一点。(this
我的意思是如何根据我拥有的密钥使用 SSH 指纹来验证我所连接的主机的身份。) - 乱七八糟的
ssh-add
。我想将其写入一个易于锁定访问的文件中,而不是将其放入正在运行的进程中。
编辑:奇怪的是,当我尝试从 pem 文件中提取指纹时,它与我连接时看到的指纹不匹配,并且它提示我。
从 PEM 中提取指纹
bash-4.2$ ssh-keygen -l -E md5 -f ./blah.PEM
2048 MD5:be:b1:d7:e1:f0:0f:ce:41:60:fa:97:dc:b8:2c:ed:08 no comment (RSA)
bash-4.2$ ssh-keygen -l -E sha1 -f ./blah.PEM
2048 SHA1:g2PDmIcw19Z/v7HTco6xRWxQ88c no comment (RSA)
SSH 提示期间显示指纹
bash-4.2$ ssh -i ./blah.PEM [email protected]
The authenticity of host 'ip-172-31-6-91.us-east-2.compute.internal (172.31.6.91)' can't be established.
ECDSA key fingerprint is SHA256:ibwhkrF5oMapJla4cKuXgePT5lHmg08L7yMp6auCpgo.
ECDSA key fingerprint is MD5:ba:82:53:ee:89:22:26:63:26:11:21:93:63:1f:1d:d1.
为什么指纹不同,但钥匙仍然允许我连接?
答案1
您有 2 个密钥对:
- 服务器的私钥/公钥。
服务器上的 ssh 守护进程创建了一组私钥,并存储在/etc/ssh/
文件夹中
您从服务器获取的 RSA 指纹来自与私钥相对应的/etc/ssh/ssh_host_rsa_key
公钥
- 用户的私钥/公钥。
这是您拥有的密钥对。私钥应安全地存储在您的计算机上,并用于向服务器进行身份验证。公钥位于服务器上,位于您的个人资料的 authorized_keys 文件中:~/.ssh/authorized_keys
因此有 2 个不同的公钥,并且它们的指纹不会匹配,除非您使用与服务器上相同的私钥,但这种情况不太可能发生。
要消除警告,请按照要求进行操作:将服务器的指纹放入/var/lib/jenkins/.ssh/known_hosts
文件中。
答案2
如果我理解正确的话,私钥文件就在你手中,你想获取它的指纹,以便将其添加到你的known_hosts
文件中。如果这是正确的,那么你可以这样做:
$ ssh-keygen -yf /path_to_private_key/key_file_name
这将输出类似以下内容的内容:
ssh-rsa AAAAB3NzaC....
最后,在其前面加上您要通过 SSH 连接的 IP 地址,这样您就得到了以下内容:
10.200.25.5 ssh-rsa AAAAB3NzaC....
您可以将其作为一行添加到您的known_hosts
文件中。
答案3
我最困惑的是,我以为我拥有与服务器完全相同的私钥和公钥对。而实际情况是,当我创建密钥对并将其分配给新的 EC2 实例时,EC2 实例会将该密钥对的公钥放入其 authorized_keys 中,这样我就可以使用在 AWS 中创建密钥对时下载的私钥连接到它。
我可以使用 AWS 附带的指纹识别命令,但它只能用于验证我拥有的私钥是否与他们存储的公钥匹配,并将其放入 authorized_keys 中。
每次出现新的 EC2 实例时,它都会为不同的算法(如 RSA 和 DSA)生成自己的私钥/公钥集合。我现在必须抓取日志以获取这些密钥的指纹,以便验证它们是否与我连接的主机匹配。
步骤就是这样。
- 生成EC2实例,保留获得的密钥。
- 将步骤 1 中的密钥提供给 Jenkins,以便它可以连接到主机。
使用 get-console-output 命令从日志中抓取密钥的指纹。- 尝试使用步骤 1 中的密钥连接到远程实例。使用该错误消息中的密钥指纹来验证您在步骤 3 中抓取的指纹。
- 一旦验证通过,您就知道添加远程主机是安全的。
- 利润!!!
请记住,这里的关键问题是您不能相信您连接的主机不是中间人攻击。如果您盲目接受密钥而不在步骤 4 中验证其指纹,则您可能无法连接到您期望的服务器。通过在步骤 4 中进行验证,您知道您的连接是安全的(因为 SSH 的加密技术),但至关重要的是,您还知道您连接到了谁,因为只有一个人会拥有与您期望的匹配的密钥对指纹。
编辑:get-console-output 命令对于自动化来说并不可靠。它仅用于临时故障排除。核心问题是 AWS 会任意剪切日志的部分内容,和/或以您必须等待很长时间才能看到完整条目的方式对其进行缓冲。
相反,我尝试上传用户数据脚本中的密钥,关闭系统,清除用户数据脚本,使其无法访问(因为其中有一个私钥),然后重新启动实例。无论如何我都需要重新启动它,因为更新的软件包可能需要重新启动,所以我可以一举两得。