什么是ssh?
SSH是一種網絡協議,用於計算機之間的加密登錄.
如果一個用戶從本地計算機,使用SSH協議登錄另一台遠程計算機,我們就可以認為,這種登錄是安全的,即使被中途截獲,密碼也不會泄露.
互聯網通信早期都是明文通信,一旦被截獲,內容就暴露無疑. 1995年,芬蘭學者Tatu Ylonen設計了SSH協議,將登錄信息全部加密,成為互聯網安全的一個基本解決方案,迅速在全世界獲得推廣, 目前已經成為Linux系統的標准配置.
Go實現ssh執行遠端命令
package main
import (
"fmt"
"golang.org/x/crypto/ssh"
"log"
"time"
)
func main(){
sshHost := ""
sshUser := "root"
sshPassword := ""
sshType := "password"
sshPort := 22
//創建sshp登陸配置
config := &ssh.ClientConfig{
Timeout: time.Second,//ssh 連接time out 時間一秒鍾, 如果ssh驗證錯誤 會在一秒內返回
User: sshUser,
HostKeyCallback: ssh.InsecureIgnoreHostKey(), //這個可以, 但是不夠安全
//HostKeyCallback: hostKeyCallBackFunc(h.Host),
}
if sshType == "password" {
config.Auth = []ssh.AuthMethod{ssh.Password(sshPassword)}
}
//dial 獲取ssh client
addr := fmt.Sprintf("%s:%d", sshHost, sshPort)
sshClient, err := ssh.Dial("tcp", addr, config)
if err != nil {
log.Fatal("創建ssh client 失敗",err)
}
defer sshClient.Close()
//創建ssh-session
session, err := sshClient.NewSession()
if err != nil {
log.Fatal("創建ssh session 失敗",err)
}
defer session.Close()
//執行遠程命令
combo,err := session.CombinedOutput("whoami; cd /; ls -al;echo https://github.com/libragen/felix")
if err != nil {
log.Fatal("遠程執行cmd 失敗",err)
}
log.Println("命令輸出:",string(combo))
}
Go實現一個遠程終端
package main
import (
"fmt"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/terminal"
"io"
"log"
"net"
"os"
"time"
)
type Cli struct {
IP string
Username string
Password string
Port int
client *ssh.Client
LastResult string
}
func New(ip string, username string, password string, port ...int) *Cli {
cli := new(Cli)
cli.IP = ip
cli.Username = username
cli.Password = password
switch {
case len(port) <= 0:
cli.Port = 22
case len(port) > 0:
cli.Port = port[0]
}
return cli
}
func (c *Cli) connect() error {
config := ssh.ClientConfig{
User: c.Username,
Auth: []ssh.AuthMethod{ssh.Password(c.Password)},
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
return nil
},
Timeout: 10 * time.Second,
}
addr := fmt.Sprintf("%s:%d", c.IP,c.Port)
sshClient, err := ssh.Dial("tcp",addr,&config)
if err != nil {
return err
}
c.client = sshClient
return nil
}
func (c *Cli) RunTerminal(stdout, stderr io.Writer) error {
if c.client == nil {
if err := c.connect(); err != nil {
return err
}
}
session, err := c.client.NewSession()
if err != nil {
return err
}
defer session.Close()
fd := int(os.Stdin.Fd())
oldState,err := terminal.MakeRaw(fd)
if err != nil {
panic(err)
}
defer terminal.Restore(fd,oldState)
session.Stdout = stdout
session.Stderr = stderr
session.Stdin = os.Stdin
termWidth, termHeight, err := terminal.GetSize(fd)
if err != nil {
panic(err)
}
modes := ssh.TerminalModes{
ssh.ECHO: 1,
ssh.TTY_OP_ISPEED: 14400,
ssh.TTY_OP_OSPEED: 14400,
}
if err := session.RequestPty("xterm-256color", termHeight,termWidth,modes); err != nil {
return err
}
session.Shell()
session.Wait()
return nil
}
func main() {
cli := New("IP","用戶名","密碼",22)
err := cli.RunTerminal( os.Stdout, os.Stdin)
if err != nil {
log.Fatal(err)
}
}
1