【问题标题】:Connect to a server using SSH and a pem / key with golang使用 SSH 和使用 golang 的 pem / 密钥连接到服务器
【发布时间】:2022-01-30 03:12:07
【问题描述】:

我正在尝试使用 Go 编程语言的 [ssh][1] 包通过密钥连接到亚马逊 AWS linux 服务器。但是,包文档有点神秘/令人困惑。有谁知道如何使用密钥或至少在可能的情况下通过 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

【问题讨论】:

  • 恐慌意味着您忽略了某处的错误(或在检查错误之前设置了延迟)。我们需要一些代码来知道你在做什么。
  • @JimB 我添加了一些代码。我想我已经检查了所有的错误。错误检查后设置延迟关闭会话
  • 您的恐慌是因为您在 session 为 nil 的位置调用 defer session.Close()t.Error(err) 不会提前回来。

标签: ssh go


【解决方案1】:

您需要使用ssh.PublicKeysssh.Signers 列表转换为ssh.AuthMethod。您可以使用 ssh.ParsePrivateKey 从 pem 字节中获取 Signer,或者如果您需要使用 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 := &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!")

...

【讨论】:

  • 我不确定我是否理解代码。如何传递密钥文件(例如 mykey.pem)或密钥内容?签名者似乎是一个接口。我将密钥存储在数据库中
  • 我添加了一条关于使用 ParsePrivateKey 从 pem 字节中获取签名者的注释。
  • 为什么我需要agent?它似乎已声明但未使用,因为我使用 signers, err := ssh.ParsePrivateKey(cl.Key)
  • 你不需要在你的程序中使用代理,但是因为你应该在一般情况下使用一个代理(你的密钥都是安全的加密的,对吗?),通常是使用普通私钥文件后的下一个“如何”请求。
  • @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 := &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 = &stdoutBuf
    err = session.Run("ls -l")
    if err != nil {
        log.Fatalf("Run failed:%v", err)
    }
    log.Printf(">%s", stdoutBuf)

【讨论】:

  • 知道为什么拨号失败:ssh:必须指定 HostKeyCallback
猜你喜欢
  • 1970-01-01
  • 2012-11-26
  • 1970-01-01
  • 1970-01-01
  • 2014-12-15
  • 2021-03-09
  • 2011-05-21
  • 2022-07-11
  • 1970-01-01
相关资源
最近更新 更多