纯粹是突发奇想,有奇葩思路的可以借鉴借鉴,?。
package main
import (
"bytes"
"fmt"
"io/ioutil"
"log"
"golang.org/x/crypto/ssh"
)
type Endpoint struct {
Host string
Port int
}
func (endpoint *Endpoint) String() string {
return fmt.Sprintf("%s:%d", endpoint.Host, endpoint.Port)
}
func publicKeyFile(file string) ssh.AuthMethod {
buffer, err := ioutil.ReadFile(file)
if err != nil {
log.Fatalln(fmt.Sprintf("Cannot read SSH public key file %s", file))
return nil
}
key, err := ssh.ParsePrivateKey(buffer)
if err != nil {
log.Fatalln(fmt.Sprintf("Cannot parse SSH public key file %s", file))
return nil
}
return ssh.PublicKeys(key)
}
// 服务器1(公网),可以理解为跳板机、堡垒机
var serverEndpoint = Endpoint{
Host: "183.2.172.185",
Port: 22,
}
// 服务器2(内网)
var remoteEndpoint = Endpoint{
Host: "192.168.1.100",
Port: 12701,
}
func main() {
//服务器1 的 ssh 连接配置,通过秘钥
sshConfig := &ssh.ClientConfig{
User: "user1",
Auth: []ssh.AuthMethod{
publicKeyFile("./user1_id_rsa"),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
//服务器2 的 ssh 连接配置,通过密码
sshConfig2 := &ssh.ClientConfig{
User: "root",
Auth: []ssh.AuthMethod{
ssh.Password("123456"),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
//连接服务器1
serverConn, err := ssh.Dial("tcp", serverEndpoint.String(), sshConfig)
if err != nil {
log.Fatalln(fmt.Printf("连接服务器1 出错: %s", err))
}
//通过服务器1中转,连接服务器2的ssh端口
listener, err := serverConn.Dial("tcp", remoteEndpoint.String())
if err != nil {
log.Fatalln(fmt.Printf("连接客户机失败: %s", err))
}
defer listener.Close()
//简介服务器2
c, chans, reqs, err := ssh.NewClientConn(listener, remoteEndpoint.String(), sshConfig2)
if err != nil {
log.Fatalln(fmt.Printf("连接服务器2的 SSH 出错: %s", err))
}
client := ssh.NewClient(c, chans, reqs)
defer client.Close()
session, err := client.NewSession()
if err != nil {
log.Fatal("创建 session 出错: ", err)
}
defer session.Close()
var b bytes.Buffer
session.Stdout = &b
if err := session.Run("ls /"); err != nil {
log.Fatal("运行命令失败: " + err.Error())
}
fmt.Println(b.String())
}
本站文章除注明转载/出处外,均为博主 spooking 原创或翻译,转载前请务必署名。