我打算实现一个golang版本的ssh客户端,通过堡垒连接到目标服务器。但不幸的是,我在更换nc代理时失败了。
在我当地的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"
我的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(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)
}
但是我得到了堡垒服务器的主机名而不是我的目的地,我错过了引导destionation服务器的输入/输出,我不知道我的代码哪里出错了,有人可以给我一些方向。
非常感谢。
答案 0 :(得分: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",
},
}
答案 1 :(得分:1)
我发现我的代码是对的。以前,我对本地的pem文件感到困惑。在我的服务器配置中,堡垒和目标服务器,pem是完全不同的。所以目前代码还可以。我可以通过golang ssh登录到目标服务器来执行命令。