123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- package ssh
- import (
- "bufio"
- "fmt"
- "os"
- "os/user"
- "path"
- "syscall"
- "time"
- "git.wecise.com/wecise/util/merrs"
- "golang.org/x/crypto/ssh"
- "golang.org/x/term"
- )
- var (
- DefaultCiphers = []string{
- "aes128-ctr",
- "aes192-ctr",
- "aes256-ctr",
- "aes128-gcm@openssh.com",
- "chacha20-poly1305@openssh.com",
- "arcfour256",
- "arcfour128",
- "arcfour",
- "aes128-cbc",
- "3des-cbc",
- "blowfish-cbc",
- "cast128-cbc",
- "aes192-cbc",
- "aes256-cbc",
- }
- )
- type Node struct {
- IPPort string
- User string
- Password string
- Passphrase string
- Keypath string
- Timeout time.Duration
- }
- type Client struct {
- *ssh.Client
- }
- func (me *Node) Connect() (*Client, error) {
- authMethods, err := authMethods(me.Password, me.Passphrase, me.Keypath)
- if err != nil {
- return nil, err
- }
- config := &ssh.ClientConfig{
- User: me.User,
- Auth: authMethods,
- HostKeyCallback: ssh.InsecureIgnoreHostKey(),
- Timeout: me.Timeout,
- }
- config.SetDefaults()
- config.Ciphers = append(config.Ciphers, DefaultCiphers...)
- client, err := ssh.Dial("tcp", me.IPPort, config)
- if err != nil {
- return nil, err
- }
- return &Client{
- Client: client,
- }, nil
- }
- func authMethods(password string, passphrase string, keypath string) ([]ssh.AuthMethod, error) {
- var authMethods []ssh.AuthMethod
- osuser, err := user.Current()
- if err != nil {
- return nil, merrs.NewError(err)
- }
- var pemBytes []byte
- if keypath == "" {
- pemBytes, err = os.ReadFile(path.Join(osuser.HomeDir, ".ssh/id_rsa"))
- } else {
- pemBytes, err = os.ReadFile(keypath)
- }
- if err != nil && !os.IsNotExist(err) {
- return nil, merrs.NewError(err)
- }
- if len(pemBytes) > 0 {
- var signer ssh.Signer
- if passphrase != "" {
- signer, err = ssh.ParsePrivateKeyWithPassphrase(pemBytes, []byte(passphrase))
- } else {
- signer, err = ssh.ParsePrivateKey(pemBytes)
- }
- if err != nil {
- return nil, merrs.NewError(err)
- }
- authMethods = append(authMethods, ssh.PublicKeys(signer))
- }
- if password != "" {
- authMethods = append(authMethods, ssh.Password(password))
- }
- authMethods = append(authMethods, ssh.KeyboardInteractive(func(user, instruction string, questions []string, echos []bool) ([]string, error) {
- answers := make([]string, 0, len(questions))
- for i, q := range questions {
- fmt.Print(q)
- if echos[i] {
- scan := bufio.NewScanner(os.Stdin)
- if scan.Scan() {
- answers = append(answers, scan.Text())
- }
- err := scan.Err()
- if err != nil {
- return nil, err
- }
- } else {
- b, err := term.ReadPassword(int(syscall.Stdin))
- if err != nil {
- return nil, err
- }
- fmt.Println()
- answers = append(answers, string(b))
- }
- }
- return answers, nil
- }))
- return authMethods, nil
- }
|