-
-
Save indeedhat/dbdf1d426ccdf4617c07eb30d805095f to your computer and use it in GitHub Desktop.
Go net/rpc over ssh+netcat and unix domain sockets It would be nice if ssh.Session implemented io.ReaderWriter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local_client | |
server | |
client | |
ext |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"golang.org/x/crypto/ssh" | |
"log" | |
"net" | |
"net/rpc" | |
"os" | |
"strings" | |
) | |
// RPC response container | |
type Response struct { | |
Greeting string | |
} | |
// RPC request container | |
type Request struct { | |
Name string | |
} | |
// ./client localhost:/tmp/foo {name} {password} | |
func main() { | |
parts := strings.Split(os.Args[1], ":") | |
host := parts[0] | |
path := parts[1] | |
name := os.Args[2] | |
passwd := os.Args[3] | |
// SSH setup, we assume current username and use the ssh agent | |
// for auth | |
agent_sock, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")) | |
if err != nil { | |
log.Fatalf("sorry, this example requires the ssh agent: %s", err) | |
} | |
defer agent_sock.Close() | |
config := &ssh.ClientConfig{ | |
User: os.Getenv("USER"), | |
Auth: []ssh.AuthMethod{ | |
ssh.Password(passwd), | |
}, | |
HostKeyCallback: ssh.InsecureIgnoreHostKey(), | |
} | |
ssh_client, err := ssh.Dial("tcp", fmt.Sprintf("%s:22", host), config) | |
if err != nil { | |
panic("Failed to dial: " + err.Error()) | |
} | |
defer ssh_client.Close() | |
s, err := ssh_client.Dial("unix", path) | |
if err != nil { | |
log.Fatalf("unable to connect to remote socket", err) | |
} | |
// now comes the RPC! | |
client := rpc.NewClient(s) | |
defer client.Close() | |
req := &Request{name} | |
var res Response | |
err = client.Call("Greeter.Greet", req, &res) | |
if err != nil { | |
log.Fatalf("error in rpc: %s", err) | |
} | |
fmt.Println(res.Greeting) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"log" | |
"net/rpc" | |
"os" | |
) | |
type Response struct { | |
Greeting string | |
} | |
type Request struct { | |
Name string | |
} | |
// ./local_client /tmp/foo Brian | |
func main() { | |
client, err := rpc.Dial("unix", os.Args[1]) | |
if err != nil { | |
log.Fatalf("failed: %s", err) | |
} | |
req := &Request{os.Args[2]} | |
var res Response | |
err = client.Call("Greeter.Greet", req, &res) | |
if err != nil { | |
log.Fatalf("error in rpc: %s", err) | |
} | |
fmt.Println(res.Greeting) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
build: setup | |
GOPATH=$(PWD):$(PWD)/ext go build server.go | |
GOPATH=$(PWD):$(PWD)/ext go build client.go | |
GOPATH=$(PWD):$(PWD)/ext go build local_client.go | |
fmt: | |
GOPATH=$(PWD) go fmt *.go | |
clean: | |
rm -rf server client local_client ext/pkg | |
setup: | |
GOPATH=$(PWD)/ext go get golang.org/x/crypto/ssh | |
godoc: | |
GOPATH=$(PWD):$(PWD)/ext godoc -http=:6060 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"log" | |
"net" | |
"net/rpc" | |
"os" | |
"os/signal" | |
"syscall" | |
) | |
// rpc response | |
type Response struct { | |
Greeting string | |
} | |
// rpc request | |
type Request struct { | |
Name string | |
} | |
// rpc host struct thing | |
type Greeter struct{} | |
// our remotely invocable function | |
func (g *Greeter) Greet(req Request, res *Response) (err error) { | |
res.Greeting = fmt.Sprintf("Hello %s", req.Name) | |
return | |
} | |
// start up rpc listener at path | |
func ServeAt(path string) (err error) { | |
rpc.Register(&Greeter{}) | |
listener, err := net.Listen("unix", path) | |
if err != nil { | |
return fmt.Errorf("unable to listen at %s: %s", path, err) | |
} | |
go rpc.Accept(listener) | |
return | |
} | |
// ./server /tmp/foo | |
func main() { | |
path := os.Args[1] | |
err := ServeAt(path) | |
if err != nil { | |
log.Fatalf("failed: %s", err) | |
} | |
defer os.Remove(path) | |
// block until we are signalled to quit | |
wait() | |
} | |
func wait() { | |
signals := make(chan os.Signal) | |
signal.Notify(signals, syscall.SIGINT, syscall.SIGKILL, syscall.SIGHUP) | |
<-signals | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment