Подключение к серверу с помощью SSH и pem / ключа с помощью golang

#ssh #go

#ssh #Вперед

Вопрос:

Я пытаюсь подключиться к серверу Amazon AWS Linux с помощью ключа, используя пакет [ssh] [1] языка программирования Go. Однако документация по пакету немного загадочная / запутанная. Кто-нибудь знает, как подключиться через ssh с помощью ключа или, по крайней мере, если это возможно? Что меня беспокоит, так это то, что в примере [Dial] [3] говорится

 // An SSH client is represented with a ClientConn. Currently only
// the "password" authentication method is supported.
  

Я в основном хочу имитировать ssh -i x.pem root@server.com поведение и выполнить команду внутри сервера ( например whoami )

Комментарии:

1. паника означает, что вы где-то игнорируете ошибку (или устанавливаете отсрочку перед проверкой ошибки). нам нужен некоторый код, чтобы знать, что вы делаете.

2. @JimB Я добавил немного кода. Я думаю, что я проверил все ошибки. Задержка для закрытия сеанса была установлена после проверки ошибок

3. ваша паника вызвана тем, что вы вызываете defer session.Close() там, где сеанс равен нулю. t.Error(err) не возвращается раньше.

Ответ №1:

Вам нужно использовать ssh.PublicKeys , чтобы превратить список ssh.Signers в ssh.AuthMethod . Вы можете использовать ssh.ParsePrivateKey для получения a Signer из байтов pem, или, если вам нужно использовать закрытый ключ rsa, dsa или ecdsa, вы можете передать их ssh.NewSignerFromKey .

Вот пример, немного дополненный поддержкой агента (поскольку использование агента обычно является следующим шагом после простого использования ключевого файла).

 sock, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK"))
if err != nil {
    log.Fatal(err)
}

agent := agent.NewClient(sock)

signers, err := agent.Signers()
if err != nil {
    log.Fatal(err)
}

// or get the signer from your private key file directly
// signer, err := ssh.ParsePrivateKey(pemBytes)
// if err != nil {
//     log.Fatal(err)
// }

auths := []ssh.AuthMethod{ssh.PublicKeys(signers...)}

cfg := amp;ssh.ClientConfig{
    User: "username",
    Auth: auths,
}
cfg.SetDefaults()

client, err := ssh.Dial("tcp", "aws-hostname:22", cfg)
if err != nil {
    log.Fatal(err)
}

session, err = client.NewSession()
if err != nil {
    log.Fatal(err)
}

log.Println("we have a session!")

...
  

Комментарии:

1. Я не уверен, что понимаю код. Как мне передать файл ключа (например, mykey.pem ) или содержимое ключа? Подписывающий, похоже, является интерфейсом. У меня есть ключи, хранящиеся в базе данных

2. Я добавил заметку об использовании ParsePrivateKey для получения подписчика из байтов pem.

3. зачем мне это нужно agent ? кажется, он объявлен, но не используется так, как я использую signers, err := ssh.ParsePrivateKey(cl.Key)

4. вам не нужно использовать агент в вашей программе, но поскольку вы должны использовать его вообще (все ваши ключи надежно зашифрованы, верно?), Обычно это следующий запрос «как» после использования простого файла закрытого ключа.

5. @Melardev, нет, при аутентификации используется только закрытый ключ; но поскольку открытый ключ может быть получен из закрытого ключа, это не имеет значения.

Ответ №2:

Вот пример удаленного запуска ls с использованием вашего «простого файла закрытого ключа».

     pemBytes, err := ioutil.ReadFile("/location/to/YOUR.pem")
    if err != nil {
        log.Fatal(err)
    }
    signer, err := ssh.ParsePrivateKey(pemBytes)
    if err != nil {
        log.Fatalf("parse key failed:%v", err)
    }
    config := amp;ssh.ClientConfig{
        User: "ubuntu",
        Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)},
        HostKeyCallback: ssh.InsecureIgnoreHostKey(),
    }
    conn, err := ssh.Dial("tcp", "yourhost.com:22", config)
    if err != nil {
        log.Fatalf("dial failed:%v", err)
    }
    defer conn.Close()
    session, err := conn.NewSession()
    if err != nil {
        log.Fatalf("session failed:%v", err)
    }
    defer session.Close()
    var stdoutBuf bytes.Buffer
    session.Stdout = amp;stdoutBuf
    err = session.Run("ls -l")
    if err != nil {
        log.Fatalf("Run failed:%v", err)
    }
    log.Printf(">%s", stdoutBuf)
  

Комментарии:

1. любая идея, почему может возникнуть сбой набора номера: ssh: необходимо указать HostKeyCallback