我试图连接到远程主机以发出命令,但是在运行代码时出现以下错误消息:
ssh:握手失败:ssh:没有通用的密钥交换算法;提供的客户端:[curve25519-sha256@libssh.org ecdh-sha2-nistp256 ecdh-sha2-nistp384 ecdh-sha2-nistp521 diffie-hellman-group14-sha1],服务器提供的:[diffie-hellman-group1-sha1]应急:运行时错误:无效的内存地址或nil指针取消引用 [信号SIGSEGV:细分违规代码= 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
}
关于如何解决此问题的任何想法?
谢谢。
答案 0 :(得分:2)
问题是...。服务器只愿意通过diffie-hellman-group1-sha1进行通话
并且:
x/crypto/ssh
:支持RFC 4419中的Diffie-Hellman Group Exchange,目前正在实施中。因此,您的客户需要golang.org/x/crypto/ssh
的分支,例如bored-engineer/ssh,其中commit 39a91b和commit fe5e4ff确实增加了对diffie-hellman-group1-sha1的支持。
或安装最新的golang/crypto
,其中包括commit 57b3e21。
答案 1 :(得分:0)
恐慌有些奇怪。显然,如果无法商定密钥交换算法,就会出问题。作为VonC notes,Diffie-Helman <密钥交换只是最近才添加的(6月3日)。由于您的服务器仅提供该算法,因此,没有它就无法上手。
这不是引起恐慌的原因(它似乎发生在ssh.Dial
内部),但是我会注意到,当您这样做时:
SSHConfig.Config.Ciphers = append(SSHConfig.Config.Ciphers, "diffie-hellman-group1-sha1")
您最终告诉Go代码仅 使用diffie-helman-group1-sha1作为通道加密。您没有在此处添加任何内容。原因是SSHConfig.Config.Ciphers
最初是nil。因此,您最好写:
SSHConfig.Config.Ciphers = []string{"diffie-hellman-group1-sha1"}
要获得相同的效果,那就是:事情不起作用。
您可以调用SetDefaults
,以使列表在添加到列表之前为非空,但是如果没有该模式的实现,即使添加了新的提交Diffie-,添加到列表也无效。除密钥交换本身外,Helman不允许进行任何其他操作。请注意,ssh.Dial
调用here的ssh.NewClientConn
,其开头为:
fullConf := *config
fullConf.SetDefaults()
SetDefaults
依次为here,其中包含:
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
中的字符串。依次定义为here,并以以下注释开头:
// 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
中明确要求,也不会进行协商。
(有关支持 的一组密码,请参阅上面的最后一个链接。请注意,此列表随着时间的推移而增长。)
答案 2 :(得分:0)
Diffie-hellman-group1-sha1是密钥交换算法。应该是KeyExchange,而不是Config结构中的密码
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