package binder import ( "fmt" "io" "log/slog" "net" "os" "os/user" "strconv" "syscall" g "gobang" ) type _CLIArgs struct { fromAddr string toAddr string } const _USER = "nobody" var emitActiveConnection = g.MakeGauge("active-connections") func dropPrivileges(username string) { g.Info("Dropping privileges", "drop-root-init") user, err := user.Lookup(username) g.FatalIf(err) gid, err := strconv.Atoi(user.Gid) g.FatalIf(err) uid, err := strconv.Atoi(user.Uid) g.FatalIf(err) err = syscall.Setgid(gid) g.FatalIf(err) err = syscall.Setgroups([]int{}) g.FatalIf(err) err = syscall.Setuid(uid) g.FatalIf(err) g.Info("Privileges dropped", "drop-root-end") } func isRunningAsRoot() bool { return os.Geteuid() == 0 } func dropRoot() { if isRunningAsRoot() { dropPrivileges(_USER) if isRunningAsRoot() { panic("Failed to drop privileges") } } } func parseArgs(args []string) _CLIArgs { if len(args) != 3 { fmt.Fprintf( os.Stderr, "Usage: %s FROM-ADDRESS TO-ADDRESS\n", args[0], ) os.Exit(2) } return _CLIArgs { fromAddr: args[1], toAddr: args[2], } } func listen(fromAddr string) net.Listener { listener, err := net.Listen("tcp", fromAddr) g.FatalIf(err) g.Info("Started listening", "listen-start", "from-address", fromAddr) return listener } func copyData(c chan struct {}, from io.Reader, to io.WriteCloser) { io.Copy(to, from) c <- struct {} {} } func start(toAddr string, listener net.Listener) { for { connFrom, err := listener.Accept() if err != nil { g.Warning( "Error accepting connection", "accept-connection-error", "err", err, ) continue } defer connFrom.Close() emitActiveConnection.Inc() connTo, err := net.Dial("unix", toAddr) if err != nil { g.Warning( "Error dialing connection", "dial-connection-error", "err", err, ) continue } defer connTo.Close() c := make(chan struct {}) go copyData(c, connFrom, connTo) go copyData(c, connTo, connFrom) go func() { <- c emitActiveConnection.Dec() }() } } func Main() { g.Init(slog.Group("versions", "gobang", g.Version, "this", Version)) args := parseArgs(os.Args) listener := listen(args.fromAddr) dropRoot() start(args.toAddr, listener) }