2016-11-18 59 views
1

我打算實施一個golang版本的ssh客戶端,通過堡壘連接到目標服務器。但不幸的是,我在替換nc proxy時失敗了。golang ssh replacement ssh ProxyCommand by 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(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

我發現我的代碼是正確的。以前,我在當地的pem文件中感到困惑。在我的服務器配置中,堡壘和dest服務器,pem是完全不同的。因此,目前代碼已經可以使用了。我可以通過使用golang ssh登錄到目標服務器來執行命令。

1

試試這個包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", 
    }, 
}