/
connect.go
122 lines (107 loc) · 3.07 KB
/
connect.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package sshutil
import (
"fmt"
"github.com/sealyun/cloud-kernel-rootfs/pkg/logger"
"golang.org/x/crypto/ssh"
"io/ioutil"
"os"
"strings"
"time"
)
/**
这里主要是做连接ssh操作的
*/
func (ss *SSH) connect(host string) (*ssh.Client, error) {
auth := ss.sshAuthMethod(ss.Password, ss.PkFile, ss.PkPassword)
config := ssh.Config{
Ciphers: []string{"aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com", "arcfour256", "arcfour128", "aes128-cbc", "3des-cbc", "aes192-cbc", "aes256-cbc"},
}
DefaultTimeout := time.Duration(1) * time.Minute
if ss.Timeout == nil {
ss.Timeout = &DefaultTimeout
}
clientConfig := &ssh.ClientConfig{
User: ss.User,
Auth: auth,
Timeout: *ss.Timeout,
Config: config,
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
addr := ss.addrReformat(host)
return ssh.Dial("tcp", addr, clientConfig)
}
func (ss *SSH) Connect(host string) (*ssh.Session, error) {
client, err := ss.connect(host)
if err != nil {
return nil, err
}
session, err := client.NewSession()
if err != nil {
return nil, err
}
modes := ssh.TerminalModes{
ssh.ECHO: 0, // disable echoing
ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
}
if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
return nil, err
}
return session, nil
}
func (ss *SSH) sshAuthMethod(passwd, pkFile, pkPasswd string) (auth []ssh.AuthMethod) {
// pkfile存在, 就进行密钥验证, 如果不存在,则跳过密钥验证。
if fileExist(pkFile) {
am, err := ss.sshPrivateKeyMethod(pkFile, pkPasswd)
// 获取到密钥验证就添加, 没获取到就直接跳过。
if err == nil {
auth = append(auth, am)
}
}
// 密码不为空, 则添加密码验证。
if passwd != "" {
auth = append(auth, ss.sshPasswordMethod(passwd))
}
return auth
}
func fileExist(path string) bool {
_, err := os.Stat(path)
return err == nil || os.IsExist(err)
}
// 使用 pk认证, pk路径为 "$HOME/.ssh/id_rsa", pk有密码和无密码在这里面验证
func (ss *SSH) sshPrivateKeyMethod(pkFile, pkPassword string) (am ssh.AuthMethod, err error) {
pkData := ss.readFile(pkFile)
var pk ssh.Signer
if pkPassword == "" {
pk, err = ssh.ParsePrivateKey(pkData)
if err != nil {
return nil, err
}
} else {
bufPwd := []byte(pkPassword)
pk, err = ssh.ParsePrivateKeyWithPassphrase(pkData, bufPwd)
if err != nil {
return nil, err
}
}
return ssh.PublicKeys(pk), nil
}
func (ss *SSH) sshPasswordMethod(passwd string) ssh.AuthMethod {
return ssh.Password(passwd)
}
// readFile 从文件读取privateKey, 并返回[]byte 无需返回string。
// 直接返回[]byte, 避免重复 []byte -> string -> []byte
func (ss *SSH) readFile(name string) []byte {
content, err := ioutil.ReadFile(name)
if err != nil {
logger.Error("[globals] read %s file err is : %s", name, err)
os.Exit(1)
}
return content
}
func (ss *SSH) addrReformat(host string) string {
if strings.Index(host, ":") == -1 {
host = fmt.Sprintf("%s:22", host)
}
return host
}