golang实现ssh远程操作

golang实现ssh远程操作

场景

配合flag加几个参数方便在镜像里远程执行脚本命令,好多基础docker镜像里不含ssh

go语言实现ssh操作,可以自定义ssh端口

package main

import (
	"fmt"
	"golang.org/x/crypto/ssh"
	"log"
)

func main() {
	// 远程服务器的连接信息
	sshConfig := &ssh.ClientConfig{
		User: "root",                  // 远程服务器的用户名
		Auth: []ssh.AuthMethod{
			ssh.Password("Server2008!"),       // 远程服务器的密码
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
	}

	// 远程服务器的地址
	sshAddress := "172.20.51.110:22"      // 远程服务器的IP地址或主机名和SSH端口号

	// 要执行的远程命令
	remoteCommand := "ip a"

	// SSH 连接远程服务器
	sshClient, err := ssh.Dial("tcp", sshAddress, sshConfig)
	if err != nil {
		log.Fatal(err)
	}
	defer sshClient.Close()

	// 创建会话
	session, err := sshClient.NewSession()
	if err != nil {
		log.Fatal(err)
	}
	defer session.Close()

	// 执行远程命令
	output, err := session.CombinedOutput(remoteCommand)
	if err != nil {
		log.Fatal(err)
	}

	// 输出命令执行结果
	fmt.Println(string(output))
}

使用key认证

package main

import (
	"fmt"
	"golang.org/x/crypto/ssh"
	"io/ioutil"
	"log"
	"os"
)

func main() {
	// 远程服务器的SSH连接信息
	sshUser := "username"                  // 远程服务器的用户名
	sshPrivateKeyPath := "/path/to/key"    // SSH私钥文件的路径
	sshServer := "remote_server"           // 远程服务器的IP地址或主机名

	// SSH连接配置
	sshConfig := &ssh.ClientConfig{
		User: sshUser,
		Auth: []ssh.AuthMethod{
			publicKeyFile(sshPrivateKeyPath),
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
	}

	// 连接远程服务器
	sshClient, err := ssh.Dial("tcp", sshServer+":22", sshConfig)
	if err != nil {
		log.Fatal(err)
	}
	defer sshClient.Close()

	// 创建会话
	session, err := sshClient.NewSession()
	if err != nil {
		log.Fatal(err)
	}
	defer session.Close()

	// 执行Shell命令
	output, err := session.CombinedOutput("ls -l")
	if err != nil {
		log.Fatal(err)
	}

	// 输出结果
	fmt.Println(string(output))
}

// 从私钥文件中获取公钥
func publicKeyFile(file string) ssh.AuthMethod {
	buffer, err := ioutil.ReadFile(file)
	if err != nil {
		log.Fatal(err)
	}

	key, err := ssh.ParsePrivateKey(buffer)
	if err != nil {
		log.Fatal(err)
	}

	return ssh.PublicKeys(key)
}

使用Golang SSH如果想本地脚本远程执行

package main

import (
	"flag"
	"fmt"
	"golang.org/x/crypto/ssh"
	"io/ioutil"
	"log"
	// "os"
)

func main() {

	var sshUser, sshPrivateKeyPath, sshServer, localScriptPath string
	flag.StringVar(&sshUser, "u", "root", "远程服务器的用户名.")
	flag.StringVar(&sshPrivateKeyPath, "k", "/root/.ssh/id_rsa", "SSH私钥文件的路径.")
	flag.StringVar(&sshServer, "s", "127.0.0.1", "远程服务器的IP地址或主机名.")
	flag.StringVar(&localScriptPath, "f", "", "本地脚本文件的路径.")
	flag.Parse()

	// 远程服务器的SSH连接信息
	// sshUser :=  root                 // 远程服务器的用户名
	// sshPrivateKeyPath := "/root/.ssh/id_rsa"    // SSH私钥文件的路径
	// sshServer := "127.0.0.1"           // 远程服务器的IP地址或主机名

	// 本地脚本文件路径
	// localScriptPath := "/data/test-go/ssh/666.sh" // 本地脚本文件的路径

	// 读取本地脚本文件内容
	scriptBytes, err := ioutil.ReadFile(localScriptPath)
	if err != nil {
		log.Fatal(err)
	}

	// SSH连接配置
	sshConfig := &ssh.ClientConfig{
		User: sshUser,
		Auth: []ssh.AuthMethod{
			publicKeyFile(sshPrivateKeyPath),
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
	}

	// 连接远程服务器
	sshClient, err := ssh.Dial("tcp", sshServer+":22", sshConfig)
	if err != nil {
		log.Fatal(err)
	}
	defer sshClient.Close()

	// 创建会话
	session, err := sshClient.NewSession()
	if err != nil {
		log.Fatal(err)
	}
	defer session.Close()

	// 执行远程脚本
	output, err := session.CombinedOutput(string(scriptBytes))
	if err != nil {
		log.Fatal(err)
	}

	// 输出结果
	fmt.Println(string(output))
}

// 从私钥文件中获取公钥
func publicKeyFile(file string) ssh.AuthMethod {
	buffer, err := ioutil.ReadFile(file)
	if err != nil {
		log.Fatal(err)
	}

	key, err := ssh.ParsePrivateKey(buffer)
	if err != nil {
		log.Fatal(err)
	}

	return ssh.PublicKeys(key)
}

参考

t-openai-c-111988f8-d99c-4b03-a44c-81f7de88a1a0-2023-05-22-18_13_57