From 15f6def3e05ecc9a7ead74f43dce99b63dfc5574 Mon Sep 17 00:00:00 2001 From: traumschule Date: Sun, 24 Mar 2019 19:37:28 -0700 Subject: [PATCH] nats-ssh-bridge.go --- nats-ssh.go | 177 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 nats-ssh.go diff --git a/nats-ssh.go b/nats-ssh.go new file mode 100644 index 0000000..a68abab --- /dev/null +++ b/nats-ssh.go @@ -0,0 +1,177 @@ +package main + +import ( + // nats client + "bufio" + "fmt" + "os" + "time" + + nats "github.com/nats-io/go-nats" + + // ssh +// "errors" +// "net" + "golang.org/x/crypto/ssh" +) + +/* motivation +TLDR ssh <> ssh-chat-server <> [ssh-client & nats-client] <> nats-server +TLDR: ssh.in < nats.out ssh.out > nats.in :s + + add an ssh server to nats-client :p <-- i really want to do this + not sure if everyone needs to run a ssh + uh? in that case no everyone would have to run nats-client.. + sounds like the ricochet or cwtch where everyone runs an onion service + they would connect to nats-client over ssh + the idea was to let everyone connect to gnats via ssh over ssh-chat, right? + what you mean gnats? the nats server? + it's the nats server that runs on serge + its a nats server not an ssh server :s + right. so your idea was to add the ssh-server to the nats client instead? yes + who would connect to it? users like in ssh-chat + and it would be forwarded via nats? + the users ssh session stdin input would be published like the normal stdin is now + and received messages would be printed on all ssh user sessions tty + stdout .. hm no.. tty.. not stdout ;) + and for example another fork of nats-client could have a webserver + then user from browser can talk to ssh user + i want to be able to send messages to everyone's stderr! */ + +func main() { + server := "gam4soeb3t5f56fs.onion" + user := "test" + + // connect to ssh server + //https://github.com/inatus/ssh-client-go/blob/master/main.go#L35 + // https://github.com/shazow/ssh-chat/blob/master/sshd/client_test.go + config := &ssh.ClientConfig{ + User: user, + Auth: []ssh.AuthMethod{ + ssh.KeyboardInteractive(func(user, instruction string, + questions []string, echos []bool) (answers []string, err error) { + return + }), + }, + HostKeyCallback: ssh.InsecureIgnoreHostKey(), + } + conn, err := ssh.Dial("tcp", server+":2022", config) + if err != nil { + panic("Failed to dial: " + err.Error()) + } + defer conn.Close() + + // Each ClientConn can support multiple interactive sessions, + // represented by a Session. + session, err := conn.NewSession() + if err != nil { + panic("Failed to create session: " + err.Error()) + } + defer session.Close() + + // Set IO + session.Stdout = os.Stdout + session.Stderr = os.Stderr +// session.Stdin = os.Stdin + in, _ := session.StdinPipe() + + // Set up terminal modes + modes := ssh.TerminalModes{ + ssh.ECHO: 1, // disable echoing + ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud + ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud + } + + // Request pseudo terminal + if err := session.RequestPty("xterm", 80, 40, modes); err != nil { + fmt.Printf("request for pseudo terminal failed: %s", err) + } + + // Start remote shell + if err := session.Shell(); err != nil { + fmt.Printf("failed to start shell: %s", err) + } + + // no it copy reader to writer using the buffer + // you shouldnt use a buffer + /// or your input/output is only going to get copied $buffersize bytes at a time https://irc.anarchyplanet.org/git/ron/proxybang/src/master/main.go#L159 + + // reader := bufio.NewReader(resp.Body) + // if _, err := io.CopyBuffer(w, reader, buf); err != nil { + // if err == io.EOF { + // log.Println("eof") + // } else { + // log.Println(err) + // } + // } + + answer, err := session.SendRequest("ping", true, nil) + if err != nil { fmt.Println("dammit") + } + fmt.Println(answer) + + // Accepting commands + // TODO needs to be forked + // you can do that with channels using the select keyword + // go func(){}() + for { + reader := bufio.NewReader(os.Stdin) + str, _ := reader.ReadString('\n') + session.Run(str) + fmt.Fprint(in, str) // ssh-chat prob gives no real shell + } + + + + + + + + // connect to nats server + opts := []nats.Option{ + nats.ReconnectWait(time.Second), + nats.MaxReconnects(-1), + nats.DisconnectHandler(disconnectHandler), + nats.ReconnectHandler(reconnectHandler), + nats.ClosedHandler(closedHandler), + } + + nc, err := nats.Connect(server, opts...) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + nc.Subscribe("chat", func(msg *nats.Msg) { + fmt.Println(string(msg.Data)) + fmt.Print("> ") + }) + nc.Flush() + + err = nc.LastError() + if err != nil { + fmt.Print(err) + os.Exit(1) + } + + reader := bufio.NewReader(os.Stdin) + for { + fmt.Print("> ") + text, _ := reader.ReadString('\n') + nc.Publish("chat", []byte(text)) + } + + os.Exit(1) +} + +func disconnectHandler(nc *nats.Conn) { + fmt.Println("disconnected") +} + +func reconnectHandler(nc *nats.Conn) { + fmt.Println("reconnected") +} + +func closedHandler(nc *nats.Conn) { + fmt.Println("closed") +}