美文网首页
go ssh sudo 远程执行 权限问题

go ssh sudo 远程执行 权限问题

作者: 陈卧虫 | 来源:发表于2023-01-31 07:31 被阅读0次

因为需要输入用户密码,所以需要监听shell的标准输出,并根据输出内容输入密码。
找了一个Stack Overflow上的代码进行了优化:

  • 但是发现没有错误输出,所以增加了错误输出,
  • 某条命令执行失败,立即停止
package main

import (
    "bufio"
    "fmt"
    "io"
    "log"
    "net"
    "strings"

    "golang.org/x/crypto/ssh"
)

type Connection struct {
    *ssh.Client
    password string
}

func main() {
    conn, err := Connect("0.0.0.0:2230", "username", "password")
    if err != nil {
        log.Fatal(err)
    }

    output, err := conn.SendCommands("ls", "pwd", "sudo cat /etc/shadow")
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(string(output))
}

func Connect(addr, user, password string) (*Connection, error) {
    sshConfig := &ssh.ClientConfig{
        User: user,
        Auth: []ssh.AuthMethod{
            ssh.Password(password),
        },
        HostKeyCallback: ssh.HostKeyCallback(func(hostname string, remote net.Addr, key ssh.PublicKey) error { return nil }),
    }

    conn, err := ssh.Dial("tcp", addr, sshConfig)
    if err != nil {
        return nil, err
    }

    return &Connection{conn, password}, nil

}

func (conn *Connection) SendCommands(cmds ...string) ([]byte, error) {
    session, err := conn.NewSession()
    if err != nil {
        log.Fatal(err)
    }
    defer session.Close()

    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
    }

    err = session.RequestPty("xterm", 80, 40, modes)
    if err != nil {
        return []byte{}, err
    }

    in, err := session.StdinPipe()
    if err != nil {
        log.Fatal(err)
    }

    out, err := session.StdoutPipe()
    if err != nil {
        log.Fatal(err)
    }

    var output []byte
    rChan := make(chan int, 0)

    go func(in io.WriteCloser, out io.Reader, output *[]byte) {
        var (
            line string
            r    = bufio.NewReader(out)
        )
        for {
            b, err := r.ReadByte()
            if err != nil {
                rChan <- 1
                break
            }

            *output = append(*output, b)

            if b == byte('\n') {
                line = ""
                continue
            }

            line += string(b)

            if strings.HasPrefix(line, "[sudo] password for ") && strings.HasSuffix(line, ": ") {
                _, err = in.Write([]byte(conn.password + "\n"))
                if err != nil {
                    rChan <- 1
                    break
                }
            }
        }
    }(in, out, &output)

    cmd := strings.Join(cmds, "&& ")
    fmt.Printf("> %s\n", cmd)
    _, err = session.CombinedOutput(cmd)
    <-rChan
    if err != nil {
        fmt.Println(string(output))
        return []byte{}, err
    }

    return output, nil
}

相关文章

网友评论

      本文标题:go ssh sudo 远程执行 权限问题

      本文链接:https://www.haomeiwen.com/subject/ggmvhdtx.html