Go中的SSH:无法进行身份验证,尝试的方法[无],不支持任何受支持的方法

mid*_*ori 15 ssh go

我尝试使用SSH和Go连接到我的一台虚拟机.如果我这样做,它通过命令行完美地工作:

ssh root@my_host
Run Code Online (Sandbox Code Playgroud)

我输入密码,它一切都很好.我试着去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()
}
Run Code Online (Sandbox Code Playgroud)

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

ssh: handshake failed: ssh: unable to authenticate, attempted methods [none], no supported methods remain
Run Code Online (Sandbox Code Playgroud)

有谁知道什么可能导致这样的错误.它在Python中使用paramiko并且在shell中运行得很好但在Go中失败.有什么我想念的吗?

mid*_*ori 11

正如@JimB和@putu指出的那样,我的服务器没有启用密码验证.要验证我使用详细选项运行ssh,它会返回所有支持的身份验证方法.在我的情况下,它结果如下:

debug1: Authentications that can continue: publickey,keyboard-interactive,hostbased
Run Code Online (Sandbox Code Playgroud)

所以我有2个选项,要么在服务器上启用密码验证,要么使用其他方法进行验证.

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

vi/etc/ssh/sshd_config
Run Code Online (Sandbox Code Playgroud)

查找行说:PasswordAuthentication no

将其更改为是,保存更改并重新启动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()
}
Run Code Online (Sandbox Code Playgroud)

在我的情况下,服务器只询问一个密码问题,如果您的服务器要求的数量超过您需要构建一整套回答的问题.