zrepl/cmd/stdinserver.go
Christian Schwarz ce25c01c7e implement stdinserver command + corresponding server
How it works:

`zrepl stdinserver CLIENT_IDENTITY`
 * connects to the socket in $global.serve.stdinserver.sockdir/CLIENT_IDENTITY
 * sends its stdin / stdout file descriptors to the `zrepl daemon` process (see cmsg(3))
 * does nothing more

This enables a setup where `zrepl daemon` is not directly exposed to the
internet but instead all traffic is tunnelled through SSH.
The server with the source job has an authorized_keys file entry for the
public key used by the corresponding pull job

 command="/mnt/zrepl stdinserver CLIENT_IDENTITY" ssh-ed25519 AAAAC3NzaC1E... zrepl@pullingserver
2017-09-11 13:48:07 +02:00

88 lines
1.7 KiB
Go

package cmd
import (
"fmt"
"os"
"github.com/ftrvxmtrx/fd"
"github.com/spf13/cobra"
"io"
"net"
)
var StdinserverCmd = &cobra.Command{
Use: "stdinserver CLIENT_IDENTITY",
Short: "start in stdinserver mode (from authorized_keys file)",
Run: cmdStdinServer,
}
func init() {
RootCmd.AddCommand(StdinserverCmd)
}
func cmdStdinServer(cmd *cobra.Command, args []string) {
var err error
defer func() {
if err != nil {
log.Printf("stdinserver exiting with error: %s", err)
os.Exit(1)
}
}()
if len(args) != 1 || args[0] == "" {
err = fmt.Errorf("must specify client_identity as positional argument")
return
}
identity := args[0]
unixaddr, err := stdinserverListenerSockpath(identity)
if err != nil {
log.Printf("%s", err)
os.Exit(1)
}
log.Printf("opening control connection to zrepld via %s", unixaddr)
conn, err := net.DialUnix("unix", nil, unixaddr)
if err != nil {
log.Printf("error connecting to zrepld: %s", err)
os.Exit(1)
}
log.Printf("sending stdin and stdout fds to zrepld")
err = fd.Put(conn, os.Stdin, os.Stdout)
if err != nil {
log.Printf("error: %s", err)
os.Exit(1)
}
log.Printf("waiting for zrepld to close control connection")
for {
var buf [64]byte
n, err := conn.Read(buf[:])
if err == nil && n != 0 {
log.Printf("protocol error: read expected to timeout or EOF returned bytes")
}
if err == io.EOF {
log.Printf("zrepld closed control connection, terminating")
break
}
neterr, ok := err.(net.Error)
if !ok {
log.Printf("received unexpected error type: %T %s", err, err)
os.Exit(1)
}
if !neterr.Timeout() {
log.Printf("receivd unexpected net.Error (not a timeout): %s", neterr)
os.Exit(1)
}
// Read timed out, as expected
}
return
}