ssh/client.go

163 lines
3.8 KiB
Go
Raw Permalink Normal View History

2018-10-30 17:45:30 +08:00
package ssh
import (
"errors"
"net"
"strconv"
"time"
"github.com/pkg/sftp"
"golang.org/x/crypto/ssh"
)
const DefaultTimeout = 30 * time.Second
type Client struct {
*Config
SSHClient *ssh.Client
2018-12-19 14:33:31 +08:00
SSHSession *ssh.Session
2018-10-30 17:45:30 +08:00
SFTPClient *sftp.Client
}
2019-03-12 17:12:42 +08:00
func NewDSN() (client *Client) {
return nil
}
func Connect(cnf *Config) (client *Client, err error) {
return nil, nil
}
func (cnf *Config) Connect() (client *Client, err error) {
return nil, nil
}
// Close the underlying SSH connection
func (c *Client) Close() {
c.SFTPClient.Close()
c.SSHClient.Close()
c.SSHSession.Close()
}
2018-10-30 17:45:30 +08:00
// New 创建SSH client
2018-11-06 15:37:35 +08:00
func New(cnf *Config) (client *Client, err error) {
2018-10-30 17:45:30 +08:00
clientConfig := &ssh.ClientConfig{
2018-11-06 15:37:35 +08:00
User: cnf.User,
2018-10-30 17:45:30 +08:00
Timeout: DefaultTimeout,
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
2018-11-06 15:37:35 +08:00
if cnf.Port == 0 {
cnf.Port = 22
2018-10-30 17:45:30 +08:00
}
2018-11-06 15:37:35 +08:00
// 1. privite key file
2019-03-12 17:12:42 +08:00
if len(cnf.KeyFiles) != 0 {
if auth, err := AuthWithPrivateKeys(cnf.KeyFiles, cnf.Passphrase); err == nil {
2018-10-30 17:45:30 +08:00
clientConfig.Auth = append(clientConfig.Auth, auth)
}
2019-03-12 17:12:42 +08:00
2018-10-30 17:45:30 +08:00
} else {
2019-03-12 17:12:42 +08:00
keypath := KeyFile()
if FileExist(keypath) {
if auth, err := AuthWithPrivateKey(keypath, cnf.Passphrase); err == nil {
clientConfig.Auth = append(clientConfig.Auth, auth)
}
2018-10-30 17:45:30 +08:00
}
2019-03-12 17:12:42 +08:00
2018-10-30 17:45:30 +08:00
}
2018-11-06 15:37:35 +08:00
// 2. 密码方式 放在key之后,这样密钥失败之后可以使用Password方式
if cnf.Password != "" {
clientConfig.Auth = append(clientConfig.Auth, ssh.Password(cnf.Password))
2018-10-30 17:45:30 +08:00
}
2018-11-06 15:37:35 +08:00
// 3. agent 模式放在最后,这样当前两者都不能使用时可以采用Agent模式
2018-11-13 17:42:29 +08:00
if auth, err := AuthWithAgent(); err == nil {
2018-11-06 15:37:35 +08:00
clientConfig.Auth = append(clientConfig.Auth, auth)
2018-10-30 17:45:30 +08:00
}
2018-11-06 15:37:35 +08:00
2018-10-30 17:45:30 +08:00
// hostPort := config.Host + ":" + strconv.Itoa(config.Port)
2018-11-06 15:37:35 +08:00
sshClient, err := ssh.Dial("tcp", net.JoinHostPort(cnf.Host, strconv.Itoa(cnf.Port)), clientConfig)
2018-10-30 17:45:30 +08:00
if err != nil {
return client, errors.New("Failed to dial ssh: " + err.Error())
}
// create sftp client
var sftpClient *sftp.Client
if sftpClient, err = sftp.NewClient(sshClient); err != nil {
return client, errors.New("Failed to conn sftp: " + err.Error())
}
2018-12-19 14:33:31 +08:00
session, err := sshClient.NewSession()
if err != nil {
return nil, err
}
// defer session.Close()
return &Client{SSHClient: sshClient, SFTPClient: sftpClient, SSHSession: session}, nil
2018-10-30 17:45:30 +08:00
}
2018-11-06 15:37:35 +08:00
// NewClient 根据配置
func NewClient(host, port, user, password string) (client *Client, err error) {
p, _ := strconv.Atoi(port)
// if err != nil {
// p = 22
// }
if user == "" {
user = "root"
}
var config = &Config{
Host: host,
Port: p,
User: user,
Password: password,
// KeyFiles: []string{"~/.ssh/id_rsa"},
Passphrase: password,
}
return New(config)
}
func NewWithAgent(Host, Port, User string) (client *Client, err error) {
clientConfig := &ssh.ClientConfig{
User: User,
Timeout: DefaultTimeout,
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
2018-11-13 17:42:29 +08:00
auth, err := AuthWithAgent()
2018-10-30 17:45:30 +08:00
if err != nil {
return nil, err
}
2018-11-06 15:37:35 +08:00
clientConfig.Auth = append(clientConfig.Auth, auth)
// hostPort := config.Host + ":" + strconv.Itoa(config.Port)
sshClient, err := ssh.Dial("tcp", net.JoinHostPort(Host, Port), clientConfig)
if err != nil {
return client, errors.New("Failed to dial ssh: " + err.Error())
}
2018-10-30 17:45:30 +08:00
2018-11-06 15:37:35 +08:00
// create sftp client
var sftpClient *sftp.Client
2018-11-13 17:42:29 +08:00
if sftpClient, err = sftp.NewClient(sshClient, sftp.MaxPacket(10240000)); err != nil {
2018-11-06 15:37:35 +08:00
return client, errors.New("Failed to conn sftp: " + err.Error())
}
return &Client{SSHClient: sshClient, SFTPClient: sftpClient}, nil
2018-10-30 17:45:30 +08:00
}
func NewWithPrivateKey(host, port, user, passphrase string, keyFiles []string) (client *Client, err error) {
p, _ := strconv.Atoi(port)
// if err != nil {
// p = 22
// }
if user == "" {
user = "root"
2018-10-30 17:45:30 +08:00
}
var config = &Config{
Host: host,
Port: p,
User: user,
KeyFiles: keyFiles,
Passphrase: passphrase,
2018-11-06 15:37:35 +08:00
}
return New(config)
2018-11-06 15:37:35 +08:00
}