如何解决即使服务器的主机密钥存在于 known_hosts 文件中,JSch 连接也会因 UnknownHostKey 失败
我正在使用 JSch 在多个 VPS 上部署各种文件。我能够在关闭 StrictHostKeyChecking
的情况下获得一个工作原型。我现在想重新启用主机密钥检查,这样我就不容易受到 MITM 攻击。目前,客户端是连接到运行 Debian 的 VPS 的 Windows 机器。这是我到目前为止所做的:
- 使用
"ssh-keyscan -t rsa <serverIp> >> ~/.ssh/known_hosts"
在我的本地机器(Windows 客户端)上添加远程 IP 地址 - 将我的
known_hosts
文件的路径传递给我的应用程序中的JSch.setKnownHosts
。
尝试建立连接时,结果是
com.jcraft.jsch.JSchException: UnknownHostKey: 。 RSA 密钥指纹是
这显然是由于我对主机密钥的工作原理或与此相关的密码学缺乏了解。根据我的基本理解,known_hosts
文件包含一个密钥。该密钥用于确保我们连接到的远程 IP 是他们所说的人,从而防止任何人试图“欺骗”自己作为服务器。
我的 known_hosts
文件看起来像
184.154.70.174 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDNv4m+tOZUipp8UDGrd+kbtsM5R+tu3ZYZi3p7OTRWUX/Wqy74pONlLqI+/WGu77EHnOfdssJfclgo37vKLRFKneXZNAMXE7FUu5yUNOHlpPwzmvYUT/sp1k9CeNrtJAbkm05pOBIDqDQQGfQ+IAw9zqqo/sqJ6c8NKiVFAt4Ud0msvedb559dhYgcjwb52ABbsJ0mZ8FnU7LKG1592/ZTtYxam+M3qMhtJacrh5gpfZjjx2lGhqpOgvM+xwWeK6DQVn0QyIJd474G3gcm4M43ErRfzXOum3p/0wOw+hL1ora9eWSz2Wf9WuDXf86xkbZPD7Gy6ER5LBhquy331p7X
我的代码是(SSH
是 JSch 的一个实例):
try {
SSH.setKnownHosts(new FileInputStream("C:/Users/nvulc/.ssh/known_hosts"));
SSH.addIdentity(keyPath,keyPass);
Session session = SSH.getSession("root","184.154.70.174",22);
session.connect();
} catch (Exception e) {
e.printStackTrace();
}
结果:
com.jcraft.jsch.JSchException: UnknownHostKey: 184.154.70.174. RSA key fingerprint is b4:79:5a:58:d3:15:ad:a9:c7:af:cc:d7:09:f5:40:62
at com.jcraft.jsch.Session.checkHost(Session.java:805)
at com.jcraft.jsch.Session.connect(Session.java:345)
at com.jcraft.jsch.Session.connect(Session.java:183)
at Main.main(Main.java:40)
解决方法
您的方法是正确的,如果操作正确,应该会起作用。尽管仅供参考,它并不能完全防止 MitM -- ssh-keyscan
本身使用未经验证的连接并且容易受到 MitM 的攻击,尽管如果该连接是合法的,但检查密钥可以防止伪造 稍后 连接。这是 SSH 常见的“ToFU”(首次使用信任)安全模型的一种形式/变体。
根据我的基本理解,known_hosts 文件包含一个密钥。 ...
通常,known_hosts
包含从主机身份(名称和/或 IP 地址)到密钥的映射。但是,如果您的文件只是按照您显示的方式创建的,那么它只有一个包含一个键的映射条目。
-
确保您将正确的路径传递给
setKnownHosts
,和以正确的(相同)用户身份运行。如果您指定的路径无法打开(不存在或不允许访问),Jsch 不会抛出任何错误,它只会返回而不加载任何内容。您可以改为自己使用new FileInputStream(pathstring)
打开文件并传递给setKnownHosts(InputStream)
重载,因此如果打开失败,您会收到异常。 -
确保您使用相同的主机身份。如果例如一个主机有多个名称(就像云服务器经常做的那样),您在
ssh-keyscan
中使用一个,但在JSch
中使用一个不同的名称,那么即使这实际上是相同的主机和密钥,它也不会匹配。但是,如果您实际上在两个地方都使用 IP 地址,至少如果您指的是 IPv4,则这种情况不太可能发生,因为当今很少有机器拥有多个公共 IPv4 地址。 (在过去,这更常见,称为多宿主。)IPv6 更有可能;大多数 IPv6 机器都有临时和永久公共地址(以及本地/私有地址),而且通常有多个临时地址。
你的代码对我有用 - https://www.browxy.com/#ALIEN_137442 - 它以 "JSchException: Auth fail" 结尾 - 这意味着它通过了主机密钥验证。
确保 known_hosts
文件是纯 ASCII 编码(或 UTF-8 没有 BOM,对于此类内容,它应该与 ASCII 相同)。但不是 UTF-8 with BOM,只让 UTF-16 或更糟。
也试试 Unix 行尾。虽然行尾应该不是问题。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。