SSH в Go: невозможно проверить подлинность, попытаться методы [none], поддерживаемые методы не сохраняются

Я попытался подключиться к одной из моих виртуальных машин, используя SSH и Go. Он отлично работает через командную строку, если я делаю это так:

ssh [email protected]_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

Кто-нибудь знает, что может вызвать такую ​​ошибку. Он отлично работает с использованием paramiko в Python и в оболочке, но не работает в Go. Есть что-то, чего я не хватает?

Ответы

Ответ 1

Как указано @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 (
    "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))
    for n, q := 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()
}

В моем случае сервер запрашивает только один вопрос, который является паролем, если ваш сервер запрашивает больше, чем вам потребуется построить целую цепочку ответов для обратной связи.