尝试通过SSH连接远程主机时出现错误。

4
我正在尝试连接到远程主机以发出命令,但在运行代码时出现以下错误消息:
ssh: 握手失败:ssh:密钥交换没有共同算法;客户端提供:[curve25519-sha256@libssh.org ecdh-sha2-nistp256 ecdh-sha2-nistp384 ecdh-sha2-nistp521 diffie-hellman-group14-sha1],服务器提供:[diffie-hellman-group1-sha1]panic: 运行时错误:无效的内存地址或nil指针解引用[信号SIGSEGV:分段违规code=0x1 addr=0x10 pc=0x759836]
这是我使用的代码:
func (SSHClient *SSH) Connect(mode int) {
    var SSHConfig *ssh.ClientConfig
    var auth []ssh.AuthMethod

    if mode == CERT_PUBLIC_KEY_FILE {
        auth = []ssh.AuthMethod{SSHClient.readPublicKeyFile(SSHClient.Cert)}
    }

    SSHConfig = &ssh.ClientConfig{
        User:            SSHClient.User,
        Auth:            auth,
        HostKeyCallback: ssh.InsecureIgnoreHostKey(),
        Timeout:         time.Second * DEFAULT_TIMEOUT,
    }

    SSHConfig.Config.Ciphers = append(SSHConfig.Config.Ciphers, "diffie-hellman-group1-sha1")

    client, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", SSHClient.IP, SSHClient.Port), SSHConfig)

    if err != nil {
        fmt.Printf("ERROR - While trying to Dial to the host %s with error: %s", SSHClient.IP, err.Error())
        return
    }

    session, err := client.NewSession()
    if err != nil {
        fmt.Printf("ERROR - While trying to create a new session on host %s with error: %s", SSHClient.IP, err.Error())
        client.Close()
        return
    }

    SSHClient.session = session
    SSHClient.client = client
}

有解决这个问题的想法吗?

提前致谢。


从错误来看,似乎是密码不匹配,即diffie-hellman-group14-sha1diffie-hellman-group1-sha1之间的不匹配。尽管所有错误都已经处理完毕,但我不确定为什么你会在那里遇到panic - Azeem
如果涉及编程和开发的SSH问题,请加上+1 - jww
@happugopher问题已经解决了吗? - Sreenath
3个回答

3
问题是......服务器只愿意使用diffie-hellman-group1-sha1进行通信。
而:
- golang/go issue 2903:ssh:添加diffie-hellman-group1-sha1,已在6天前关闭。 - golang/go/issue 17230:建议:x/crypto/ssh:支持RFC 4419中的Diffie-Hellman Group Exchange,正在实现中。

因此,您需要为客户提供一个 golang.org/x/crypto/ssh 的分支,例如 bored-engineer/ssh,其中 commit 39a91bcommit fe5e4ff 添加了对 diffie-hellman-group1-sha1 的支持。
或者安装最新版本的 golang/crypto,其中包括 commit 57b3e21


非常感谢VonC,我将安装最新的golang/crypto并查看是否解决了这个问题,我会在明天发布更新,希望能带来一些好消息! :) - happygopher
@happygopher 你正在使用哪个版本的Go? - VonC
@happygopher 你能试试 Go 1.13.3 吗? - VonC
我也尝试使用版本go version go1.13.1 linux/amd64,但是我得到了相同的错误信息。 - happygopher
[signal SIGSEGV: segmentation violation code=0x1 addr=0x10 pc=0x7a4fb6]``` - happygopher
显示剩余6条评论

2
Diffie-hellman-group1-sha1 是一种密钥交换算法。在 Config 结构体中应该使用 KeyExchanges 而不是 Ciphers。
SSHConfig.Config.KeyExchanges = append(SSHConfig.Config.KeyExchanges, "diffie-hellman-group1-sha1")

代替

SSHConfig.Config.Ciphers = append(SSHConfig.Config.Ciphers, "diffie-hellman-group1-sha1")

如果未指定KeyExchanges,则可以在ssh/common.go中找到使用的默认算法。
// preferredKexAlgos specifies the default preference for key-exchange algorithms
// in preference order.
var preferredKexAlgos = []string{
    kexAlgoCurve25519SHA256,
    kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521,
    kexAlgoDH14SHA1,
}

正如您所看到的,目前未列出kexAlgoDH1SHA1或diffie-hellman-group1-sha1。

2
恐慌有点奇怪。很明显,当无法达成任何密钥交换算法时,会出现问题。正如 VonC指出的,迪菲-赫尔曼(Diffie-Hellman)密钥交换最近才被添加(6月3日)。由于您的服务器只提供该算法,因此您无法在没有它的情况下开始。
这不是恐慌的原因(似乎发生在ssh.Dial 内部),但我要注意一下,当您执行以下操作时:
SSHConfig.Config.Ciphers = append(SSHConfig.Config.Ciphers, "diffie-hellman-group1-sha1")

您最终会告诉Go代码仅使用diffie-hellman-group1-sha1作为通道加密。这里不需要添加任何内容。原因是SSHConfig.Config.Ciphers最初为空。因此,您可以写成:

SSHConfig.Config.Ciphers = []string{"diffie-hellman-group1-sha1"}

要达到相同的效果,即:事情不起作用。
您可以调用SetDefaults,以使列表在添加到列表之前非空,但如果没有此模式的实现,则添加到列表是无效的-即使是使用新提交,也不允许除密钥交换本身之外的Diffie-Hellman。请注意,ssh.Dial调用ssh.NewClientConn,它在这里开始,并且从以下内容开始:
fullConf := *config
fullConf.SetDefaults()

SetDefaults 依次在这里,其中包含:

if c.Ciphers == nil {
    c.Ciphers = preferredCiphers
}
var ciphers []string
for _, c := range c.Ciphers {
    if cipherModes[c] != nil {
        // reject the cipher if we have no cipherModes definition
        ciphers = append(ciphers, c)
    }
}
c.Ciphers = ciphers

首先,如果配置的Ciphers未设置,则应使用默认值,然后立即在此之后过滤掉不在cipherModes中的任何字符串。这又在这里定义,并以以下注释开头:
// cipherModes documents properties of supported ciphers. Ciphers not included
// are not supported and will not be negotiated, even if explicitly requested in
// ClientConfig.Crypto.Ciphers.

这个短语没有在文档中出现,但它应该出现!未包含的密码不受支持,即使在ClientConfig.Crypto.Ciphers明确请求,也不会进行协商。请参见上面的链接以获取支持的密码集合(请注意,此列表随时间而增长)。

1
嗨Torek,感谢您的回复和解释,正如我所说,我将尝试VonC的建议安装最新的golang/crypto并查看是否解决了我的问题,明天会发布更新。谢谢你们两个 :) - happygopher

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