最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

linux - How to implement ssh session logging in Go? - Stack Overflow

programmeradmin1浏览0评论

I am writing a simple bastion service which will log input/output of a ssh session. The ssh connection part looks like:

func connect(user, host string, logger sessionLogger) error {
    cmd := exec.Command("ssh", user+"@"+host)
    t, err := pty.Start(cmd)
    if err != nil {
        return err
    }
    defer t.Close()
    go func() {
        buf := make([]byte, 1024)
        for {
            n, err := t.Read(buf)
            if err != nil {
                break
            }
            os.Stdout.Write(buf[:n])
            logger(buf[:n])
        }
    }()
    go func() { io.Copy(t, os.Stdin) }()
    return cmd.Wait()
}

The problem is all commands entered by user is echoed to the PTY twice, like this:

I have tried to play with the stdin/stdout of a cmd, including not using pty at all, but having various strange problems, e.g. no output of command prompt etc. most of them related to the nature of stdout of a Command (it must be a pty).

This is the best result I have now. But I do need to eliminate the excessive echo of command.

I am writing a simple bastion service which will log input/output of a ssh session. The ssh connection part looks like:

func connect(user, host string, logger sessionLogger) error {
    cmd := exec.Command("ssh", user+"@"+host)
    t, err := pty.Start(cmd)
    if err != nil {
        return err
    }
    defer t.Close()
    go func() {
        buf := make([]byte, 1024)
        for {
            n, err := t.Read(buf)
            if err != nil {
                break
            }
            os.Stdout.Write(buf[:n])
            logger(buf[:n])
        }
    }()
    go func() { io.Copy(t, os.Stdin) }()
    return cmd.Wait()
}

The problem is all commands entered by user is echoed to the PTY twice, like this:

I have tried to play with the stdin/stdout of a cmd, including not using pty at all, but having various strange problems, e.g. no output of command prompt etc. most of them related to the nature of stdout of a Command (it must be a pty).

This is the best result I have now. But I do need to eliminate the excessive echo of command.

Share Improve this question asked Feb 8 at 6:58 xrfangxrfang 2,3105 gold badges24 silver badges51 bronze badges 2
  • 1 Well, you wrote os.Stdout.Write(buf[:n]), so why are you surprised that you get that output in addition to the tty's own echo? – Toby Speight Commented Feb 8 at 9:38
  • @TobySpeight I know, but the problem is, if I do not write that, there is no echo from the console at all, i.e. the ssh login prompt does NOT appear at all. – xrfang Commented Feb 8 at 9:53
Add a comment  | 

1 Answer 1

Reset to default 1

You need to use raw mode to prevent duplicate input

    // import "golang.org/x/term"
    ...
    defer t.Close()

    oldState, err := term.MakeRaw(int(os.Stdin.Fd()))
    if err != nil {
        return err
    }
    defer term.Restore(int(os.Stdin.Fd()), oldState)
    ...
发布评论

评论列表(0)

  1. 暂无评论