SSH 的 authorized_keys 和 known_hosts 文件有什么区别?

信息安全 验证 linux SSH
2021-09-01 22:21:13

我正在学习 SSH 协议的基础知识。我对以下两个文件的内容感到困惑:

  1. ~/.ssh/authorized_keys:保存服务器的授权公钥列表。当客户端连接到服务器时,服务器通过检查存储在此文件中的签名公钥来验证客户端

  2. ~/.ssh/known_hosts:包含用户访问的 SSH 服务器的 DSA 主机密钥。该文件对于确保 SSH 客户端连接正确的 SSH 服务器非常重要。

我不确定这意味着什么。请帮忙。

4个回答

known_hosts文件允许客户端对服务器进行身份验证,以检查它是否未连接到模拟者。authorized_keys文件允许服务器对用户进行身份验证。

服务器认证

建立 SSH 连接时发生的第一件事是服务器将其公钥发送给客户端,并向客户端证明(感谢公钥加密)它知道相关的私钥。这对服务器进行身份验证:如果这部分协议成功,则客户端知道服务器就是它声称的那个人。

客户端可能会检查服务器是否为已知服务器,而不是某个试图冒充正确服务器的流氓服务器。SSH 仅提供一种简单的机制来验证服务器的合法性:它在客户端计算机上的文件中记住您已经连接到~/.ssh/known_hosts的服务器(还有一个系统范围的文件/etc/ssh/known_hosts)。首次连接服务器时,需要通过其他方式检查服务器提供的公钥是否真的是您要连接的服务器的公钥。如果您有要连接的服务器的公钥,您可以~/.ssh/known_hosts手动将其添加到客户端。

顺便说一句,known_hosts可以包含 SSH 实现支持的任何类型的公钥,而不仅仅是 DSA(还有 RSA 和 ECDSA)。

在向服务器发送任何机密数据之前,必须先对服务器进行身份验证。特别是,如果用户身份验证涉及密码,则不得将密码发送到未经身份验证的服务器。

用户认证

如果该用户可以证明他们有权访问该帐户,则服务器仅允许远程用户登录。根据服务器的配置和用户的选择,用户可能会提供几种形式的凭据之一(下面的列表并不详尽)。

  • 用户可以出示他尝试登录的帐户的密码;然后服务器验证密码是否正确。
  • 用户可以出示公钥并证明他拥有与该公钥相关联的私钥。这与用于验证服务器的方法完全相同,但现在用户正在尝试证明其身份,而服务器正在验证它。如果用户证明他知道私钥并且公钥在帐户的授权列表中(~/.ssh/authorized_keys在服务器上),则接受登录尝试。
  • 另一种方法涉及将验证用户的部分工作委托给客户端机器。这发生在企业等受控环境中,当许多机器共享相同的帐户时。服务器通过与相反方式使用的相同机制对客户端机器进行身份验证,然后依赖客户端对用户进行身份验证。

这两个文件都被SSH使用,但用途完全不同,这很容易解释你的困惑。

授权密钥

默认情况下,SSH 使用由主机操作系统管理的用户帐户和密码。(嗯,实际上由PAM管理,但这种区别在这里可能不太有用。)这意味着当您尝试使用用户名“bob”和一些密码连接到 SSH 时,SSH 服务器程序将询问操作系统“我有个叫'bob'的人告诉我他的密码是'wonka'。我可以让他进来吗?” 如果答案是肯定的,那么 SSH 允许您进行身份验证,然后您就可以愉快地继续前进了。

除了密码之外,SSH 还允许您使用所谓的公钥密码术来识别您的身份。具体的加密算法可能会有所不同,但通常是 RSA 或DSA,或者最近的ECDSA在任何情况下,当您使用该程序设置密钥时ssh-keygen,您都会创建两个文件。一个是你的私钥,一个是你的公钥。这些名称是不言自明的。通过设计,公钥可以像蒲公英种子一样随风散播,而不会损害您的利益。私钥应始终严格保密。

所以你要做的就是把你的公钥放在authorized_keys文件中。然后,当您尝试使用用户名“bob”和您的私钥连接到 SSH 时,它会询问操作系统“我得到了这个人的名字 'bob',可以在这里吗?” 如果答案是肯定的,那么 SSH 将检查您的私钥并验证authorized_keys文件中的公钥是否是它的对。如果两个答案都是肯定的,那么你就可以进去了。

已知主机

authorized_keys文件用于验证用户的方式非常相似,该文件known_hosts用于验证服务器。每当在新服务器上配置 SSH 时,它总是会为服务器生成公钥和私钥,就像您为用户所做的那样。每次您连接到 SSH 服务器时,它都会向您显示它的公钥,以及它拥有相应私钥的证明。如果您没有它的公钥,那么您的计算机将要求它并将其添加到known_hosts文件中。如果您有密钥并且它匹配,那么您可以立即连接。如果键不匹配,那么你会得到一个严重的警告。这就是事情变得有趣的地方。密钥不匹配通常发生的 3 种情况是:

  1. 服务器上的密钥已更改。这可能来自重新安装操作系统或在某些操作系统上更新 SSH 时重新创建密钥。
  2. 您连接的主机名或 IP 地址曾经属于不同的服务器。这可能是地址重新分配、DHCP或类似的东西。
  3. 恶意中间人攻击正在发生。这是密钥检查试图保护您免受的最重要的事情。

在这两种情况下,known_hostsSSHauthorized_keys程序都使用公钥加密来识别客户端或服务器。

关于包含公钥的安全文件

为了帮助您了解“known_hosts”和“authorized_keys”的不同之处,这里有一些上下文解释了这些文件如何适合“ssh”。这是过于简单化了;“ssh”的功能和复杂性比这里提到的要多得多。

关联在受信任的来源中

虽然有人说公钥值“可以像风中的种子一样安全地散布”,但请记住,决定哪些种子在花园中生长的是园丁,而不是种子荚。尽管公钥不是秘密的,但需要严格的保护来保持密钥与密钥正在验证的事物之间的可信关联。受托建立这种关联的地方包括“known_hosts”、“authorized_keys”和“Certificate Authority”列表。

“ssh”使用的可信来源

对于与“ssh”相关的公钥,必须提前注册密钥,并将其存储在适当的安全文件中。(这个普遍事实有一个重要的例外,稍后将讨论。)服务器和客户端都有自己的、安全存储的公钥列表;只有当每一方都向另一方注册时,登录才会成功。

  • “known_hosts”驻留在客户端
  • “authorized_keys”驻留在服务器上

客户端的安全文件称为“known_hosts”,服务器的安全文件称为“authorized_keys”。这些文件的相似之处在于,每个文件都有每行一个公钥的文本,但它们在格式和用法上有细微的差别。

密钥对用于身份验证

公私密钥对用于执行“非对称加密”。“ssh”程序可以使用非对称加密进行身份验证,其中实体必须回答挑战以证明其身份。挑战是通过用一个键编码创建的,并通过用另一个键解码来回答。(请注意,非对称加密仅在登录阶段使用;然后“ssh”(TSL/SSL)切换到另一种加密形式来处理数据流。)

一个密钥对用于服务器,另一个用于客户端

在“ssh”中,双方(客户端和服务器)都怀疑对方;这是对“ssh”前身“telnet”的改进。使用“telnet”,客户端需要提供密码,但服务器没有经过审查。缺乏审查导致“中间人”攻击发生,给安全带来灾难性后果。相比之下,在“ssh”过程中,客户端在服务器第一次回答挑战之前不提供任何信息。

“ssh”认证的步骤

在共享任何登录信息之前,“ssh”客户端首先通过挑战服务器来证明“你真的是我想的那个人吗?”从而消除了中间人攻击的机会。为了进行这个挑战,客户端需要知道与目标服务器关联的公钥。客户端必须在“known_hosts”文件中找到服务器的名称;关联的公钥在同一行,在服务器名称之后。server-name 和 public-key 之间的关联必须保持不可侵犯;因此“known_hosts”文件的权限必须为 600——其他人不能写(也不能读)。

一旦服务器通过身份验证,它就有机会挑战客户端。身份验证将涉及在“authorized_keys”中找到的公钥之一。(当这些密钥都不起作用时,“sshd”进程将退回到密码式身份验证。)

文件格式

因此,对于“ssh”,与任何登录过程一样,都有“朋友”列表,并且只有列表中的人才能尝试通过挑战。对于客户端,“known_hosts”文件是可以充当服务器(主机)的好友列表;这些按名称列出。对于服务器来说,等价的好友列表是“authorized_keys”文件;但是该文件中没有名称,因为公钥本身就像标识符一样。(服务器不关心登录的来源,只关心登录的去向。客户端尝试访问特定帐户,在调用“ssh”时将帐户名指定为参数。请记住,“authorized_keys " 文件特定于该帐户,因为该文件位于该帐户的主目录下。)

尽管可以在配置条目中表达许多功能,但基本的、最常见的用法具有以下参数。请注意,参数由空格字符分隔。

对于“known_hosts”:

{server-id} ssh-rsa {public-key-string} {comment}

对于“授权密钥”:

ssh-rsa {public-key-string} {comment}

请注意,令牌ssh-rsa表示用于编码的算法是“rsa”。其他有效算法包括“dsa”和“ecdsa”。因此,不同的令牌可能会代替ssh-rsa此处显示的内容。

让“ssh”自动配置“known_hosts”条目

在这两种情况下,如果在安全文件中找不到公钥,则不会发生非对称加密。如前所述,这条规则有一个例外。允许用户通过登录到用户的“known_hosts”文件中未列出的服务器来故意选择冒中间人攻击的风险。“ssh”程序会警告用户,但如果用户选择继续,“ssh”客户端会允许它“仅此一次”。为了确保它只发生一次,“ssh”进程通过向服务器询问公钥,然后将其写入“known_hosts”文件,自动为“known_hosts”文件配置所需的信息。此异常允许攻击者提供服务器名称与公钥的关联,从而完全破坏了安全性。这种安全风险是允许的,因为它让很多人的事情变得容易多了。当然,正确和安全的方法是让用户在尝试登录服务器之前手动将带有服务器名称和公钥的行插入“known_hosts”文件。(但对于低风险情况,额外的工作可能毫无意义。)

一对多关系

客户端的“known_hosts”文件中的条目具有服务器的名称和适用于服务器机器的公钥。服务器有一个用于回答所有挑战的私钥,并且客户端的“known_hosts”条目必须具有匹配的公钥。因此,所有访问特定服务器的客户端都将在其“known_hosts”文件中具有相同的公钥条目。1:N 关系是服务器的公钥可以出现在许多客户端的“known_hosts”文件中。

“authorized_keys”文件中的条目标识允许友好的客户访问该帐户。朋友可能会使用相同的公钥-私钥对来访问多个不同的服务器。这允许单个密钥对对曾经联系过的所有服务器进行身份验证。每个目标服务器帐户都将在其“authorized_keys”文件中具有相同的公钥条目。1:N 关系是一个客户端的公钥可以出现在多个服务器上多个帐户的“authorized_keys”文件中。

有时,在多台客户端机器上工作的用户会复制相同的密钥对;通常这是在用户在台式机和笔记本电脑上工作时完成的。因为客户端机器使用相同的密钥进行身份验证,所以它们将匹配服务器的“authorized_keys”中的相同条目。

私钥的位置

对于服务器端,系统进程或守护进程处理所有传入的“ssh”登录请求。守护进程名为“sshd”。私钥的位置取决于 SSL 安装,例如 Apple 将其放置在/System/Library/OpenSSL,但在安装您自己的 OpenSSL 版本后,位置将是/opt/local/etc/openssl

对于客户端,您可以在需要时调用“ssh”(或“scp”)。您的命令行将包含各种参数,其中一个可以选择指定要使用的私钥。默认情况下,客户端密钥对通常称为$HOME/.ssh/id_rsa$HOME/.ssh/id_rsa.pub

概括

底线是“known_hosts”和“authorized_keys”都包含公钥,但是......

  • known_hosts -- 客户端检查主机是否为正版
  • authorized_keys -- 主机检查是否允许客户端登录

一点也不真实。

known_hosts 文件包含主机的指纹。它不是远程主机的公钥或私钥。

它是从他们的密钥生成的 - 但它强调不是密钥本身。

如果您 SFTP 到可能解析为多个(不同)主机(负载平衡等)的地址,则必须添加来自所有可能端点的指纹,否则它最初会工作,然后在路由到第二个(或后续) 主持人。