如何通过SSH.NET在无需认证的情况下获取远程主机指纹?
无需凭证获取SSH远程主机指纹的实现方案
嘿,这个问题我之前也踩过坑!答案是完全可以——SSH协议的握手流程里,主机密钥(也就是指纹的来源)是在用户认证之前就会发送的,所以根本不需要提供有效的凭证,甚至连真实的用户名都不用。
针对你提到的SSH.NET的限制(SshClient和ConnectionInfo都要求用户名),其实有个很简单的 workaround:随便填一个无效的用户名就行,比如dummy,因为在主机密钥交换阶段,服务器还不会验证你的身份,这个用户名只是个占位符,完全不影响我们获取指纹。
下面是我实测有效的代码示例,用SSH.NET实现无凭证获取主机指纹:
using Renci.SshNet; using Renci.SshNet.Common; public string FetchHostFingerprint(string targetHost, int port = 22) { // 随便填一个占位用户名,不需要真实存在 var placeholderUser = "dummy-user"; // 使用None认证方法,不需要任何凭证 var authMethod = new NoneAuthenticationMethod(placeholderUser); var connectionInfo = new ConnectionInfo(targetHost, port, placeholderUser, authMethod); try { using var sshClient = new SshClient(connectionInfo); // 监听HostKeyReceived事件,这是我们获取指纹的关键节点 sshClient.HostKeyReceived += (sender, e) => { // 提取主机密钥的指纹 var fingerprintBytes = e.HostKey.GetFingerprint(); // 标记信任该密钥(只是为了跳过后续的信任提示) e.CanTrust = true; // 立即取消后续的连接流程,因为我们只需要指纹,不需要认证 e.Cancel = true; }; // 触发连接流程,虽然会因为我们取消而抛出异常,但指纹已经拿到了 sshClient.Connect(); } catch (SshConnectionException) { // 这个异常是我们主动取消连接导致的,直接忽略即可 } // 将指纹字节转换成常用的冒号分隔格式返回 return BitConverter.ToString(connectionInfo.HostKey.GetFingerprint()).Replace("-", ":"); }
关键细节说明:
NoneAuthenticationMethod:这是SSH.NET专门提供的无认证方法,刚好匹配我们不需要凭证的场景HostKeyReceived事件:这个事件会在服务器发送主机密钥后立刻触发,此时还没到用户认证环节,所以我们能轻松拿到指纹- 主动取消连接:拿到指纹后直接取消后续流程,避免不必要的认证尝试,也节省资源
本质上,我们是利用了SSH协议的握手顺序:主机密钥交换 → 用户认证 → 会话建立。我们只需要走到第一步就停下来,完全不需要涉及后续的认证步骤。
内容的提问来源于stack exchange,提问作者Brian Mitchell
相关产品推荐
相关产品推荐

