使用Golang使用SSH和pem/key连接到服务器。

huangapple go评论80阅读模式
英文:

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.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)
}

// 或者直接从私钥文件获取签名者
// 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)

huangapple
  • 本文由 发表于 2014年6月27日 02:37:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/24437809.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定