GoLang SSH:设置为nil但仍出现“必须指定HosKeyCallback”错误。

12

我正在尝试使用GoLang连接到远程服务器。在客户端配置中,除了用户名和密码外,我将HostKeyCallback设置为nil,以便它接受每个主机。

config := &ssh.ClientConfig{

        User: user,

        HostKeyCallback: nil,

        Auth: []ssh.AuthMethod{

        publicKey,
    },
}

但是我一直收到这个错误。

Failed to dial: ssh: must specify HostKeyCallback

我该如何解决这个问题?

2个回答

25

谢谢您的回答。但是在执行此操作时,我看到以下错误:ssh:密钥交换没有公共算法;客户端提供:[xxxxxxxxxxx],服务器提供:[xxxxxxxx] - user1851006
你可能需要在这里记录的KeyExchanges中指定 https://godoc.org/golang.org/x/crypto/ssh#Config,因为它使用的默认值可能不包括服务器想要使用的任何值。 - Chris Cherry

9
请注意 ssh.InsecureIgnoreHostKey 警告中所提到的内容:

... 它不应该用于生产代码。

因此,考虑强制实施SSH密钥验证,这并不是很难实现:

// create human-readable SSH-key strings
func keyString(k ssh.PublicKey) string {
    return k.Type() + " " + base64.StdEncoding.EncodeToString(k.Marshal()) // e.g. "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTY...."
}


func trustedHostKeyCallback(trustedKey string) ssh.HostKeyCallback {

    if trustedKey == "" {
        return func(_ string, _ net.Addr, k ssh.PublicKey) error {
            log.Printf("WARNING: SSH-key verification is *NOT* in effect: to fix, add this trustedKey: %q", keyString(k))
            return nil
        }
    }

    return func(_ string, _ net.Addr, k ssh.PublicKey) error {
        ks := keyString(k)
        if trustedKey != ks {
            return fmt.Errorf("SSH-key verification: expected %q but got %q", trustedKey, ks)
        }

        return nil
    }
}

使用方法:

// where `conf` is the main app config
sc := &ssh.ClientConfig{
    User:            conf.Username,
    Auth:            []ssh.AuthMethod{ssh.Password(conf.Password)},
    HostKeyCallback: trustedHostKeyCallback(conf.HostKey), // <- server-key goes here
    Timeout:         conf.Timeout,
}

如果conf.HostKey为空 - 它仍然可以工作 - 但是会记录一个警告并显示需要填写的密钥字符串以启用SSH密钥验证。

由于这是基于SSH密钥的身份验证过程,为什么&ssh.ClientConfig{}会设置基于密码的身份验证方法[]ssh.AuthMethod{ssh.Password(conf.Password)}, - pkaramol
1
@pkaramol 这个问题和答案与 SSH 客户端 验证 服务器 的身份有关(而不是服务器验证客户端凭据)。HostKeyCallback 机制可以防止 MITM 攻击,从而避免凭据被泄露,相当于 ssh 命令的 ~/.ssh/known_hosts 文件。在我上面的示例中,我使用基于密码的凭据登录到服务器,但可以使用任何支持的 ssh.AuthMethod - colm.anseo
有一个问题,return func(_ string, remoteAdd net.Addr, k ssh.PublicKey) 中的 remoteAdd 和 k 是如何传递的?我查看了 dial 函数的代码,但没有找到它们是如何传递的。 - michael
@michael,ssh.Dial 调用将根据 addr string 参数查找 net.Addr。密钥 k 是通过拨号 SSH 握手返回的服务器端 ssh-key。回调函数仅验证返回(服务器端)公钥是否与我们期望的匹配,并避免任何 MITM 攻击。 - colm.anseo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接