Go x/crypto/ssh — How to establish ssh connection to private instance over a bastion node

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

Go x/crypto/ssh -- How to establish ssh connection to private instance over a bastion node

问题

我想实现以下场景:
在AWS上,我有一个VPC,其中部署了一个公共子网和一个私有子网。在公共子网中,我有一个"堡垒机"实例,而在私有子网中,有一个运行一些服务的节点(也称为"服务实例")。
通过使用*nux ssh命令,我可以从我的本地笔记本连接到"服务实例",像这样:

ssh -t -o ProxyCommand="ssh -i <key> ubuntu@<bastion-ip> nc %h %p" -i <key> ubuntu@<service-instance-ip>

我有一个Go程序,想要做以下事情:

  1. 从"本地笔记本"通过"堡垒机"ssh连接到"服务实例"
  2. 使用连接会话运行一些命令(例如"ls -l")
  3. 将文件从"本地笔记本"上传到"服务实例"

我尝试过,但无法实现与以下命令相同的过程:

ssh -t -o ProxyCommand="ssh -i <key> ubuntu@<bastion-ip> nc %h %p" -i <key> ubuntu@<service-instance-ip>

有人可以帮助我提供一个示例吗?
谢谢!

顺便说一下,我找到了这个链接:
https://github.com/golang/go/issues/6223,这意味着肯定可以做到,对吗?

英文:

I want to implement this scenario:
On AWS, I have a VPC, in which it is deployed a public and private subnet. In the public subnet, I have a "bastion" instance, while in private subnet, there is one node running some services(AKA "service instance").
By using *nux ssh command, I can do things like this to connect to the "service instance" from my local laptop:

ssh -t -o ProxyCommand=&quot;ssh -i &lt;key&gt; ubuntu@&lt;bastion-ip&gt; nc %h %p&quot; -i &lt;key&gt; ubuntu@&lt;service-instance-ip&gt;

I have a Go program, and want to do the following things:

> 1. ssh connect to the "service instance" from "local laptop" over the "bastion"
> 2. use the connection session to run some commands (e.g. "ls -l")
> 3. upload files from "local laptop" to "service instance"

I've tried but not able to implement the same process as doing

ssh -t -o ProxyCommand=&quot;ssh -i &lt;key&gt; ubuntu@&lt;bastion-ip&gt; nc %h %p&quot; -i &lt;key&gt; ubuntu@&lt;service-instance-ip&gt;

Could anyone help to show me an example?
Thanks!

BTW, I found this:
https://github.com/golang/go/issues/6223, which means it is definately able to do that, right?

答案1

得分: 22

你可以直接使用"x/crypto/ssh"而不使用nc命令来完成这个操作,因为有一种方法可以从远程主机拨号连接并将其呈现为net.Conn

一旦你拥有一个ssh.Client,你可以使用Dial方法在你和最终主机之间获得一个虚拟的net.Conn。然后,你可以使用ssh.NewClientConn将其转换为一个新的ssh.Conn,并使用ssh.NewClient创建一个新的ssh.Client

// 连接到堡垒主机
bClient, err := ssh.Dial("tcp", bastionAddr, config)
if err != nil {
    log.Fatal(err)
}

// 从堡垒主机拨号连接到服务主机
conn, err := bClient.Dial("tcp", serviceAddr)
if err != nil {
    log.Fatal(err)
}

ncc, chans, reqs, err := ssh.NewClientConn(conn, serviceAddr, config)
if err != nil {
    log.Fatal(err)
}

sClient := ssh.NewClient(ncc, chans, reqs)
// sClient 是通过堡垒主机连接到服务主机的 ssh 客户端
英文:

You can do this even more directly with the "x/crypto/ssh" without the nc command, since there is a method to dial a connection from the remote host and presents it as a net.Conn.

Once you have an ssh.Client, you can use the Dial method to get a virtual net.Conn between you and the final host. You can then turn that into a new ssh.Conn with ssh.NewClientConn, and create a new ssh.Client with ssh.NewClient

// connect to the bastion host
bClient, err := ssh.Dial(&quot;tcp&quot;, bastionAddr, config)
if err != nil {
	log.Fatal(err)
}

// Dial a connection to the service host, from the bastion
conn, err := bClient.Dial(&quot;tcp&quot;, serviceAddr)
if err != nil {
	log.Fatal(err)
}

ncc, chans, reqs, err := ssh.NewClientConn(conn, serviceAddr, config)
if err != nil {
	log.Fatal(err)
}

sClient := ssh.NewClient(ncc, chans, reqs)
// sClient is an ssh client connected to the service host, through the bastion host.

huangapple
  • 本文由 发表于 2016年3月10日 11:23:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/35906991.html
匿名

发表评论

匿名网友

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

确定