nats-ssh-bridge.go
This commit is contained in:
commit
15f6def3e0
177
nats-ssh.go
Normal file
177
nats-ssh.go
Normal file
@ -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
|
||||
|
||||
<ts> add an ssh server to nats-client :p <-- i really want to do this
|
||||
<ts> not sure if everyone needs to run a ssh
|
||||
<ron> uh? in that case no everyone would have to run nats-client..
|
||||
<ts> sounds like the ricochet or cwtch where everyone runs an onion service
|
||||
<ron> they would connect to nats-client over ssh
|
||||
<ts> the idea was to let everyone connect to gnats via ssh over ssh-chat, right?
|
||||
<ron> what you mean gnats? the nats server?
|
||||
<ts> it's the nats server that runs on serge
|
||||
<ron> its a nats server not an ssh server :s
|
||||
<ts> right. so your idea was to add the ssh-server to the nats client instead? <ron> yes
|
||||
<ts> who would connect to it? <ron> users like in ssh-chat
|
||||
<ts> and it would be forwarded via nats?
|
||||
<ron> the users ssh session stdin input would be published like the normal stdin is now
|
||||
<ron> and received messages would be printed on all ssh user sessions tty
|
||||
<ron> stdout .. hm no.. tty.. not stdout ;)
|
||||
<ron> and for example another fork of nats-client could have a webserver
|
||||
<ron> then user from browser can talk to ssh user
|
||||
<ts> 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")
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user