英文:
Connect to a server using SSH and a pem / key with golang
问题
我正在尝试使用Go编程语言的ssh包连接到一个使用密钥的Amazon AWS Linux服务器。然而,该包的文档有点晦涩和令人困惑。有人知道如何使用密钥连接到ssh,或者至少知道是否可能吗?让我困扰的是,在Dial的示例中,它说:
// An SSH client is represented with a ClientConn. Currently only
// the "password" authentication method is supported.
我基本上想模仿ssh -i x.pem root@server.com的行为,并在服务器内执行一个命令(例如whoami
)。
英文:
I'm trying to connect to an amazon AWS linux server with a key using the ssh package of Go programming language. However the package documentation is a bit cryptic/confusing. Does anyone know how to connect through ssh using a key or at least if it's possible ? What bothers me is that in the Dial example it says
// An SSH client is represented with a ClientConn. Currently only
// the "password" authentication method is supported.
I basically want to mimic the ssh -i x.pem root@server.com behavior and execute a command inside the server ( e.g. whoami
)
答案1
得分: 24
你需要使用ssh.PublicKeys
将ssh.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)
}
// 或者直接从私钥文件获取签名者
// 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!")
...
希望对你有帮助!
英文:
You need to use ssh.PublicKeys
to turn a list of ssh.Signers
into an ssh.AuthMethod
. You can use ssh.ParsePrivateKey
to get a Signer
from the pem bytes, or if you need to use an rsa, dsa or ecdsa private key, you can give those to ssh.NewSignerFromKey
.
Here's an example fleshed out a bit with Agent support too (since using an agent is usually the next step after simply using a key file).
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!")
...
答案2
得分: 15
这是一个使用你的“普通私钥文件”远程运行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("解析密钥失败:%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("连接失败:%v", err)
}
defer conn.Close()
session, err := conn.NewSession()
if err != nil {
log.Fatalf("创建会话失败:%v", err)
}
defer session.Close()
var stdoutBuf bytes.Buffer
session.Stdout = &stdoutBuf
err = session.Run("ls -l")
if err != nil {
log.Fatalf("运行命令失败:%v", err)
}
log.Printf(">%s", stdoutBuf)
希望对你有帮助!
英文:
Here is an example to run ls remotely using your "plain private key file".
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)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论