diff options
-rw-r--r-- | go.mod | 8 | ||||
-rw-r--r-- | go.sum | 8 | ||||
-rw-r--r-- | main.go | 116 |
3 files changed, 132 insertions, 0 deletions
diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..d966455 --- /dev/null +++ b/go.mod @@ -0,0 +1,8 @@ +module ssh-test + +require ( + github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 // indirect + github.com/gliderlabs/ssh v0.1.1 + github.com/kr/pty v1.1.3 + golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..ea59ed7 --- /dev/null +++ b/go.sum @@ -0,0 +1,8 @@ +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/gliderlabs/ssh v0.1.1 h1:j3L6gSLQalDETeEg/Jg0mGY0/y/N6zI2xX1978P0Uqw= +github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/kr/pty v1.1.3 h1:/Um6a/ZmD5tF7peoOJ5oN5KMQ0DrGVQSXLNwyckutPk= +github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 h1:ng3VDlRp5/DHpSWl02R4rM9I+8M2rhmsuLwAMmkLQWE= +golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= diff --git a/main.go b/main.go new file mode 100644 index 0000000..2928196 --- /dev/null +++ b/main.go @@ -0,0 +1,116 @@ +package main + +import ( + "bytes" + "fmt" + "github.com/gliderlabs/ssh" + "github.com/kr/pty" + "io" + "log" + "net/http" + "os/exec" +) + +var ( + metrics_num_passwords int +) + +func main() { + log.Println("Starting SSH listener") + + //// start the ssh server + //go func() { + // listenErr := ssh.ListenAndServe(":2222", nil, ssh.PasswordAuth(handlePass)) + // if listenErr != nil { + // log.Fatalln(listenErr.Error()) + // } + //}() + + go func() { + // star the metrics listener + log.Println("Starting HTTP metrics listener") + http.HandleFunc("/metrics", metricsHandler) + listenErr := http.ListenAndServe(":8080", nil) + if listenErr != nil { + log.Fatalln(listenErr.Error()) + } + }() + + ssh.Handle(handleConnection) + log.Fatal(ssh.ListenAndServe(":2222", nil, ssh.PasswordAuth(handlePass))) +} + +func handleConnection(s ssh.Session) { + cmd := exec.Command("bash") + p, _ := pty.Start(cmd) + + go func() { + var readErr error + for readErr == nil { + // create two buffers, one for storing the char input (buf) + // and the other for storing complete commands (commandBuffer) + buf := make([]byte, 1024) + commandBuffer := make([]byte, 0) + + // the current char + var char string + + // read until ENTER is pressed + for char != "\x0d"{ + + // read the char inserted by the user into the buffer + _, readErr = s.Read(buf) + + // trim the char and append it to the commandBuffer + char1 := bytes.Trim(buf, "\x00")[0] + if char1 == []byte("\x03")[0] { + s.Close() + return + } + commandBuffer = append(commandBuffer, char1) + + // write the char to stdout + char = string(bytes.Trim(buf, "\x00")) + input := string(bytes.Trim(buf, "\x00")) + io.WriteString(s, input) + } + + // prepare the command for execution + input := string(bytes.Trim(commandBuffer, "\x00")) + + // filter out unwanted commands + filteredInput := filter(input) + + // write the string to the commandHandler + io.WriteString(p, filteredInput) + s.Close() + return + } + }() + + io.Copy(s, p) + s.Close() +} + +func filter(buffer string) string { + //if strings.Contains(buffer, "wget") == false { + // return "\n" + //} + //return buffer + + // all ways return a newline -> track what is input + log.Printf("%s", buffer) + return "\n" +} + +func handlePass(ctx ssh.Context, pass string) bool { + metrics_num_passwords++ + log.Printf("%s@%s: '%s'", ctx.User(), ctx.RemoteAddr().String(), pass) + return true +} + +// Handle HTTP /metrics requests +func metricsHandler(w http.ResponseWriter, req *http.Request) { + fmt.Fprintf(w, "num_passwords %d\n", metrics_num_passwords) +} + |