Go 中的 SSH:无法进行身份验证,已尝试方法 [无],不存在支持的方法

问题描述 投票:0回答:2

我尝试使用 SSH 和 Go 连接到我的一台虚拟机。 如果我这样做的话,它通过命令行工作得非常好:

ssh root@my_host

我输入密码,一切正常。 我尝试在 Go 中执行此操作,这是我的代码:

package main

import (
    "golang.org/x/crypto/ssh"
    "fmt"
)

func connectViaSsh(user, host string, password string) (*ssh.Client, *ssh.Session) {
    config := &ssh.ClientConfig{
        User: user,
        Auth: []ssh.AuthMethod{ssh.Password(password)},
        HostKeyCallback: ssh.InsecureIgnoreHostKey(),
    }

    client, err := ssh.Dial("tcp", host, config)
    fmt.Println(err)

    session, err := client.NewSession()
    fmt.Println(err)

    return client, session
}


func main() {
    client, _ := connectViaSsh("root", "host:22", "password")
    client.Close()
}

如果我运行它,它会返回错误:

ssh: handshake failed: ssh: unable to authenticate, attempted methods [none], no supported methods remain

有谁知道什么可能会导致这样的错误。在 Python 和 shell 中使用 paramiko 工作得很好,但在 Go 中却失败了。我有什么遗漏的吗?

go ssh
2个回答
16
投票

正如 @JimB 和 @putu 所指出的,我的服务器没有启用密码身份验证。

为了验证我是否使用详细选项运行 ssh,它返回了所有支持的身份验证方法。 就我而言,结果如下:

debug1 : Authentications that can continue: publickey,keyboard-interactive,hostbased

所以我有两个选择,要么在服务器上启用密码身份验证,要么使用其他方法进行身份验证。

要启用密码身份验证,请连接到您的服务器并打开 sshd 配置文件,如下所示:

vi /etc/ssh/sshd_config

找到行:PasswordAuthentication no

将其更改为 yes,保存更改并重新启动 sshd 服务:

service ssh restart

密码验证方法开始按预期工作。

也可以使用其他方法,我决定尝试键盘交互,这是用户使用 ssh 通过终端连接时通常使用的一种方法。

这是执行此操作的代码片段,在远程服务器询问密码问题后发送密码:

package main
import (
    "bytes"
    "golang.org/x/crypto/ssh"
    "fmt"
)

func connectViaSsh(user, host string, password string) (*ssh.Client, *ssh.Session) {
    config := &ssh.ClientConfig{
        User: user,
        Auth: []ssh.AuthMethod{
            ssh.KeyboardInteractive(SshInteractive),
        },
        HostKeyCallback: ssh.InsecureIgnoreHostKey(),
    }
    client, err := ssh.Dial("tcp", host, config)
    fmt.Println(err)
    session, err := client.NewSession()
    fmt.Println(err)

    return client, session
}

func SshInteractive(user, instruction string, questions []string, echos []bool) (answers []string, err error) {
    answers = make([]string, len(questions))
    // The second parameter is unused
    for n, _ := range questions {
        answers[n] = "your_password"
    }

    return answers, nil
}

func main() {
    var b bytes.Buffer
    client, session := connectViaSsh("root", "host:22", "password")

    session.Stdout = &b
    session.Run("ls")
    fmt.Println(b.String())

    client.Close()
}

在我的例子中,服务器只询问一个问题,即密码,如果您的服务器询问更多问题,您将需要构建一整串答案来反馈。


0
投票

如果您在 Mac 上本地运行,并且由于 Go 的 ssh 握手不断失败而感到摸不着头脑,请使用 ssh 代理将您的密钥添加到钥匙串:

ssh-add --apple-use-keychain /path/to/ssh_key

如果您使用的不是 Mac,则只需删除“--apple-use-keychain”即可(只要您使用的是某些 Linux 发行版)。

这是问题的解释,供那些可以通过 ssh-add 解决问题的人使用。

在部署到您的环境时,请记住,您需要一个 ssh 代理才能使其工作,但此答案的目的是为任何有此准时设置/问题的人指出正确的方向。

© www.soinside.com 2019 - 2024. All rights reserved.