什麼是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)
}
}