init
commit
54cdb80ef7
@ -0,0 +1,286 @@
|
||||
package sshd
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/sftp"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
var ShellRes, ShellErr string
|
||||
var ShellExit bool
|
||||
|
||||
type sshd struct {
|
||||
SSHC *ssh.Session
|
||||
infile io.Writer
|
||||
outfile io.Reader
|
||||
errfile io.Reader
|
||||
thread bool
|
||||
counter int
|
||||
}
|
||||
|
||||
func NewTransferSession(client *ssh.Client) (*ssh.Session, error) {
|
||||
session, err := client.NewSession()
|
||||
return session, err
|
||||
}
|
||||
func NewSession(client *ssh.Client) (*ssh.Session, error) {
|
||||
var session *ssh.Session
|
||||
var err error
|
||||
// create session
|
||||
if session, err = client.NewSession(); 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 Connect(user, password, host, key string, port int, cipherList []string) (*ssh.Client, error) {
|
||||
var (
|
||||
auth []ssh.AuthMethod
|
||||
addr string
|
||||
clientConfig *ssh.ClientConfig
|
||||
client *ssh.Client
|
||||
config ssh.Config
|
||||
err error
|
||||
)
|
||||
// get auth method
|
||||
auth = make([]ssh.AuthMethod, 0)
|
||||
if key == "" {
|
||||
keyboardInteractiveChallenge := func(
|
||||
user,
|
||||
instruction string,
|
||||
questions []string,
|
||||
echos []bool,
|
||||
) (answers []string, err error) {
|
||||
if len(questions) == 0 {
|
||||
return []string{}, nil
|
||||
}
|
||||
return []string{password}, nil
|
||||
}
|
||||
auth = append(auth, ssh.Password(password))
|
||||
auth = append(auth, ssh.KeyboardInteractive(keyboardInteractiveChallenge))
|
||||
} else {
|
||||
pemBytes, err := ioutil.ReadFile(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var signer ssh.Signer
|
||||
if password == "" {
|
||||
signer, err = ssh.ParsePrivateKey(pemBytes)
|
||||
} else {
|
||||
signer, err = ssh.ParsePrivateKeyWithPassphrase(pemBytes, []byte(password))
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
auth = append(auth, ssh.PublicKeys(signer))
|
||||
}
|
||||
|
||||
if len(cipherList) == 0 {
|
||||
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"},
|
||||
}
|
||||
} else {
|
||||
config = ssh.Config{
|
||||
Ciphers: cipherList,
|
||||
}
|
||||
}
|
||||
|
||||
clientConfig = &ssh.ClientConfig{
|
||||
User: user,
|
||||
Auth: auth,
|
||||
Timeout: 10 * time.Second,
|
||||
Config: config,
|
||||
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// connet to ssh
|
||||
addr = fmt.Sprintf("%s:%d", host, port)
|
||||
|
||||
if client, err = ssh.Dial("tcp", addr, clientConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func ScpTransfer(src, dst string, session *ssh.Session) error {
|
||||
|
||||
go func() {
|
||||
//Buf := make([]byte, 1024)
|
||||
w, _ := session.StdinPipe()
|
||||
defer w.Close()
|
||||
File, err := os.Open(src)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
info, _ := File.Stat()
|
||||
fmt.Fprintln(w, "C0777", info.Size(), info.Name())
|
||||
io.Copy(w, File)
|
||||
fmt.Fprintln(w, "\x00")
|
||||
}()
|
||||
if err := session.Run("/usr/bin/scp -qrt " + dst); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateSftp(client *ssh.Client) (*sftp.Client, error) {
|
||||
|
||||
sftpClient, err := sftp.NewClient(client)
|
||||
return sftpClient, err
|
||||
}
|
||||
|
||||
func FtpTransfer(src, dst string, sftpClient *sftp.Client) error {
|
||||
srcFile, err := sftpClient.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer srcFile.Close()
|
||||
|
||||
var localFileName = path.Base(src)
|
||||
dstFile, err := os.Create(path.Join(dst, localFileName))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer dstFile.Close()
|
||||
|
||||
if _, err = srcFile.WriteTo(dstFile); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Command(session *ssh.Session, cmdstr string) (string, error) {
|
||||
var res bytes.Buffer
|
||||
session.Stdout = &res
|
||||
err := session.Run(cmdstr)
|
||||
if err != nil {
|
||||
return res.String(), err
|
||||
}
|
||||
return res.String(), nil
|
||||
}
|
||||
|
||||
func SSHPipeShell(session *ssh.Session, cmdstr string) (*sshd, error) {
|
||||
var err error
|
||||
lovessh := sshd{}
|
||||
lovessh.SSHC = session
|
||||
lovessh.infile, err = lovessh.SSHC.StdinPipe()
|
||||
if err != nil {
|
||||
return &lovessh, err
|
||||
}
|
||||
lovessh.outfile, err = lovessh.SSHC.StdoutPipe()
|
||||
if err != nil {
|
||||
return &lovessh, err
|
||||
}
|
||||
lovessh.errfile, err = lovessh.SSHC.StderrPipe()
|
||||
if err != nil {
|
||||
return &lovessh, err
|
||||
}
|
||||
if err := lovessh.SSHC.Start(cmdstr); err != nil {
|
||||
return &lovessh, err
|
||||
}
|
||||
go func() {
|
||||
lovessh.SSHC.Wait()
|
||||
}()
|
||||
ShellExit = false
|
||||
lovessh.thread = false
|
||||
return &lovessh, nil
|
||||
}
|
||||
|
||||
func SedColor(str string) string {
|
||||
reg := regexp.MustCompile(`\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]`)
|
||||
//fmt.Println("regexp:", reg.Match([]byte(str)))
|
||||
return string(reg.ReplaceAll([]byte(str), []byte("")))
|
||||
}
|
||||
|
||||
func (this sshd) GetResult(maxtime int) (string, string, bool) {
|
||||
var stop bool
|
||||
reader := bufio.NewReader(this.outfile)
|
||||
erreader := bufio.NewReader(this.errfile)
|
||||
if !this.thread {
|
||||
this.thread = true
|
||||
go func() {
|
||||
var line2 string
|
||||
var stack bool = false
|
||||
stop = false
|
||||
for {
|
||||
if !stack {
|
||||
go func() {
|
||||
stack = true
|
||||
if erreader.Size() > 0 {
|
||||
line2, _ = erreader.ReadString('\n')
|
||||
ShellErr += line2
|
||||
line2 = ""
|
||||
}
|
||||
stack = false
|
||||
}()
|
||||
}
|
||||
line, err2 := reader.ReadString('\n')
|
||||
if err2 != nil || io.EOF == err2 {
|
||||
stop = true
|
||||
break
|
||||
}
|
||||
this.counter++
|
||||
ShellRes += line
|
||||
}
|
||||
}()
|
||||
}
|
||||
waittm := 0
|
||||
for !stop {
|
||||
time.Sleep(time.Millisecond * 250)
|
||||
waittm += 1
|
||||
if maxtime >= 0 {
|
||||
if waittm/4 > maxtime {
|
||||
restr := SedColor(ShellRes)
|
||||
ShellRes = ""
|
||||
errstr := SedColor(ShellErr)
|
||||
ShellErr = ""
|
||||
return restr, errstr, false
|
||||
}
|
||||
}
|
||||
}
|
||||
ShellExit = true
|
||||
this.thread = false
|
||||
restr := SedColor(ShellRes)
|
||||
ShellRes = ""
|
||||
errstr := SedColor(ShellErr)
|
||||
ShellErr = ""
|
||||
return restr, errstr, true
|
||||
}
|
||||
|
||||
func (this sshd) Exec(cmdstr string, maxtime int) (string, string, bool) {
|
||||
this.infile.Write([]byte(cmdstr + "\n"))
|
||||
return this.GetResult(maxtime)
|
||||
}
|
||||
|
||||
func (this sshd) WriteCmd(cmdstr string) {
|
||||
this.infile.Write([]byte(cmdstr + "\n"))
|
||||
return
|
||||
}
|
||||
|
||||
func (this sshd) IsExit() bool {
|
||||
return ShellExit
|
||||
}
|
Loading…
Reference in New Issue