Skip to content

SSH 里的“认证私钥”到底是什么,它认证的是谁?

很多人在看到 SSH 配置中的“认证私钥”时,都会自然地理解成“用户登录时使用的私钥”。但这个理解通常是不对的。

这里的关键在于,SSH 里可能同时出现两类私钥:

  • 服务器自己的私钥
  • 用户自己的私钥

它们都叫“私钥”,但用途并不一样。

如果配置界面中的“认证私钥”指的是 SSH 服务端配置项,那么它通常不是用户登录用的私钥,而是SSH 服务器身份私钥。它的作用不是证明“用户是谁”,而是证明“服务器是谁”。

也就是说,它认证的对象不是用户,而是服务器本身。

理解这一点后,很多常见疑问就会顺过来。比如:

  • 为什么已经开启了账号密码登录,系统里仍然需要这个私钥?
  • 为什么用户用公钥免密登录时,服务器也还是要有自己的私钥?
  • 为什么第一次连接 SSH 时,客户端会提示确认主机指纹?

这些问题,本质上都和“服务器身份认证”有关。

SSH 建立连接时,并不是一上来就先验证用户密码。更常见的流程是,客户端先与服务器完成握手,并验证服务器身份;在此之后,双方建立加密通道;再之后,客户端才会提交用户名和密码,或者使用用户自己的 SSH 密钥完成登录认证。

所以在 SSH 里,至少有两件不同的事需要分开看:

  • 第一件事是确认“我连接的是不是目标服务器”
  • 第二件事是确认“这个用户能不能登录这台服务器”

前者依赖的是服务器身份私钥。 后者依赖的是用户密码或者用户私钥

这也是为什么“认证私钥”和“账号密码”并不是二选一关系。它们分别解决的是不同层面的问题。

如果把整个过程再说得更明确一点,可以这样理解:

当客户端连接 SSH 服务器时,服务器会使用自己的身份私钥参与握手签名。客户端再根据服务器对应的公钥来验证这个签名是否正确。验证通过后,客户端才有理由相信,对面确实持有那把应属于目标服务器的私钥。

在这个阶段,服务器是在证明自己的身份。

只有这一步完成之后,客户端才会继续进行用户认证。例如提交用户名和密码,或者使用用户自己的 SSH 私钥来完成公钥认证。

因此:

  • 服务器身份私钥解决的是“服务器是谁”
  • 账号密码 / 用户 SSH 私钥解决的是“用户是谁”

两者名称相似,但职责完全不同。

这也解释了一个很常见的误区:有些人会认为“既然我已经使用账号密码登录,那服务器端这个私钥就没用了”。实际上并不是这样。即使用户最终采用的是密码登录,服务器仍然需要先完成自己的身份证明。否则,客户端无法可靠确认自己连接的到底是不是预期中的服务器。

第一次连接某台 SSH 服务器时,客户端常常会提示确认主机指纹,原因也在这里。客户端虽然可以验证“对方持有某把私钥”,但在第一次连接时,它还不知道这把私钥是否属于你想连接的那台服务器。因此需要用户手动确认一次。确认之后,客户端会把该服务器的公钥信息记录下来,后续再连接时就可以据此判断主机身份是否发生变化。

如果未来客户端提示主机指纹变化,通常意味着以下几种情况之一:

  • 服务器重装或重新生成了主机密钥
  • 当前连接的并不是原来的那台服务器
  • 存在中间人攻击风险

这也是为什么服务器身份私钥不能被随意替换,更不能泄露。

如果用户使用的不是密码登录,而是 SSH 公钥登录,情况也类似。区别只在于用户认证阶段不再提交密码,而是由用户使用自己的私钥对挑战数据进行签名,再由服务器用登记的公钥进行验证。

但无论用户使用哪种登录方式,前面的服务器身份认证步骤都仍然存在。换句话说:

  • 用户密码可以替换为用户私钥
  • 但服务器身份私钥不能因此消失

如果放到产品配置界面里,更准确的说法其实不应该只是“认证私钥”,而应该写成:

SSH 服务器身份私钥

这样更不容易让用户误解为“登录私钥”或“用户认证私钥”。

所以,这个问题最后可以归纳为一句话:

SSH 里的“认证私钥”如果是服务端配置项,通常认证的是服务器,不是用户。

用户是谁,由账号密码或用户自己的 SSH 私钥来证明。 服务器是谁,则由服务器自己的身份私钥来证明。