英文:
golang ssh replacement ssh ProxyCommand by nc
问题
我计划实现一个使用Golang编写的SSH客户端,通过堡垒机连接到目标服务器。但不幸的是,我在替换nc代理时失败了。
我的本地SSH配置如下:
Host bastion
HostName xxx.xxx.xxx.xxx
User ec2-user
IdentityFile ~/.ssh/xxx-bastion.pem
Host 10.0.*.*
User ec2-user
IdentityFile ~/.ssh/xxx-dest.pem
ProxyCommand ssh -q bastion "nc -w 3600 %h %p"
我的Golang实现如下:
var (
Bastion = "xxx.xxx.xxx.xxx:22"
Target = "xxx.xxx.xxx.xxx:22"
BastionPem = "/Users/me/.ssh/xxx-bastion.pem"
DestPem = "/Users/me/.ssh/xxx-dest.pem"
Timeout = 30 * time.Second
)
func BastionConfig() (*ssh.ClientConfig, error) {
pemBytes, err := ioutil.ReadFile(BastionPem)
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: "ec2-user",
Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)},
Timeout: Timeout,
}
return config, err
}
func DestConfig() (*ssh.ClientConfig, error) {
pemBytes, err := ioutil.ReadFile(DestPem)
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: "ec2-user",
Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)},
Timeout: Timeout,
}
return config, err
}
func Connect() {
config, _ := BastionConfig()
bClient, err := ssh.Dial("tcp", Bastion, config)
if err != nil {
log.Fatal("dial bastion error:", err)
}
log.Println("dial bastion ok...")
// Dial a connection to the service host, from the bastion
conn, err := bClient.Dial("tcp", Target)
if err != nil {
log.Fatal("dial target error", err)
}
targetConfig, _ := DestConfig()
ncc, chans, reqs, err := ssh.NewClientConn(conn, Target, targetConfig)
if err != nil {
log.Fatal("new target conn error:", err)
}
log.Printf("target conn[%s] ok\n", Target)
targetClient := ssh.NewClient(ncc, chans, reqs)
if err != nil {
log.Fatalf("target ssh error:%v", err)
}
session, err := targetClient.NewSession()
if err != nil {
log.Fatalf("session failed:%v", err)
}
defer session.Close()
var stdoutBuf bytes.Buffer
session.Stdout = &stdoutBuf
err = session.Run("hostname")
if err != nil {
log.Fatalf("Run failed:%v", err)
}
log.Printf(">%s", stdoutBuf)
}
但是我得到的是堡垒机服务器的主机名,而不是目标服务器的主机名。我是否遗漏了目标服务器的输入/输出,或者其他地方出错了?有人可以给我一些指导吗?
非常感谢。
英文:
I'm planning to implement a golang version ssh client to connect to destination server by a bastion.But unfortunately,I failed at the replacement for nc proxy.
At my local ssh config:
Host bastion
HostName xxx.xxx.xxx.xxx
User ec2-user
IdentityFile ~/.ssh/xxx-bastion.pem
Host 10.0.*.*
User ec2-user
IdentityFile ~/.ssh/xxx-dest.pem
ProxyCommand ssh -q bastion "nc -w 3600 %h %p"
my golang implementation is like the following:
<!-- language: go-->
var(
Bastion="xxx.xxx.xxx.xxx:22"
Target="xxx.xxx.xxx.xxx:22"
BastionPem ="/Users/me/.ssh/xxx-bastion.pem"
DestPem ="/Users/me/.ssh/xxx-dest.pem"
Timeout=30*time.Second
)
func BastionConfig() (*ssh.ClientConfig,error){
pemBytes, err := ioutil.ReadFile(BastionPem)
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: "ec2-user",
Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)},
Timeout:Timeout,
}
return config,err
}
func DestConfig() (*ssh.ClientConfig,error){
pemBytes, err := ioutil.ReadFile(TargetPem)
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: "ec2-user",
Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)},
Timeout:Timeout,
}
return config,err
}
func Connect(){
config,_:= BastionConfig()
bClient, err := ssh.Dial("tcp", Bastion, config)
if err != nil {
log.Fatal("dial bastion error:",err)
}
log.Println("dial bastion ok...")
// Dial a connection to the service host, from the bastion
conn, err := bClient.Dial("tcp", Target)
if err != nil {
log.Fatal("dial target error",err)
}
targetConfig,_:= DestConfig()
ncc, chans, reqs, err := ssh.NewClientConn(conn, Target, targetConfig)
if err != nil {
log.Fatal("new target conn error:",err)
}
log.Printf("target conn[%s] ok\n",Target)
targetClient := ssh.NewClient(ncc, chans, reqs)
if err != nil {
log.Fatalf("target ssh error:%v",err)
}
session,err:=targetClient.NewSession()
if err!=nil{
log.Fatalf("session failed:%v",err)
}
defer session.Close()
var stdoutBuf bytes.Buffer
session.Stdout = &stdoutBuf
err = session.Run("hostname")
if err != nil {
log.Fatalf("Run failed:%v", err)
}
log.Printf(">%s", stdoutBuf)
}
But I got the hostname of the bastion server not my destination one,did I miss to lead the input/output of the destionation server or something, I don't know where is wrong for my code,Can anybody give me some directions.
thanks a lot.
答案1
得分: 2
尝试使用这个包 https://github.com/appleboy/easyssh-proxy
ssh := &easyssh.MakeConfig{
User: "drone-scp",
Server: "localhost",
Port: "22",
KeyPath: "./tests/.ssh/id_rsa",
Proxy: easyssh.DefaultConfig{
User: "drone-scp",
Server: "localhost",
Port: "22",
KeyPath: "./tests/.ssh/id_rsa",
},
}
英文:
Try this package https://github.com/appleboy/easyssh-proxy
ssh := &easyssh.MakeConfig{
User: "drone-scp",
Server: "localhost",
Port: "22",
KeyPath: "./tests/.ssh/id_rsa",
Proxy: easyssh.DefaultConfig{
User: "drone-scp",
Server: "localhost",
Port: "22",
KeyPath: "./tests/.ssh/id_rsa",
},
}
答案2
得分: 1
我发现我的代码是正确的。之前,我在本地对pem文件感到困惑。在我的服务器配置中,堡垒机和目标服务器的pem文件是非常不同的。所以目前,代码是正常的。我可以使用golang ssh登录到目标服务器并执行命令。
英文:
I've found my code is right. previously ,I was confused by the pem file locally. In my server configuration, the bastion and dest server ,the pem is quite different.so currently, the code is ok now. I can execute commands by logging into the target server with golang ssh.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论