From 25b8eef95923b69df5df7f6949eb0722058585e0 Mon Sep 17 00:00:00 2001 From: Toby Date: Sat, 12 Aug 2023 13:12:36 -0700 Subject: [PATCH] feat: command auth --- app/cmd/server.go | 7 +++++++ app/cmd/server_test.go | 1 + app/cmd/server_test.yaml | 1 + extras/auth/command.go | 28 ++++++++++++++++++++++++++++ 4 files changed, 37 insertions(+) create mode 100644 extras/auth/command.go diff --git a/app/cmd/server.go b/app/cmd/server.go index 88b3adc..572d63f 100644 --- a/app/cmd/server.go +++ b/app/cmd/server.go @@ -98,6 +98,7 @@ type serverConfigAuth struct { Password string `mapstructure:"password"` UserPass map[string]string `mapstructure:"userpass"` HTTP serverConfigAuthHTTP `mapstructure:"http"` + Command string `mapstructure:"command"` } type serverConfigResolverTCP struct { @@ -405,6 +406,12 @@ func (c *serverConfig) fillAuthenticator(hyConfig *server.Config) error { } hyConfig.Authenticator = auth.NewHTTPAuthenticator(c.Auth.HTTP.URL, c.Auth.HTTP.Insecure) return nil + case "command", "cmd": + if c.Auth.Command == "" { + return configError{Field: "auth.command", Err: errors.New("empty auth command")} + } + hyConfig.Authenticator = &auth.CommandAuthenticator{Cmd: c.Auth.Command} + return nil default: return configError{Field: "auth.type", Err: errors.New("unsupported auth type")} } diff --git a/app/cmd/server_test.go b/app/cmd/server_test.go index 6788d7f..60c7b65 100644 --- a/app/cmd/server_test.go +++ b/app/cmd/server_test.go @@ -70,6 +70,7 @@ func TestServerConfig(t *testing.T) { URL: "http://127.0.0.1:5000/auth", Insecure: true, }, + Command: "/etc/some_command", }, Resolver: serverConfigResolver{ Type: "udp", diff --git a/app/cmd/server_test.yaml b/app/cmd/server_test.yaml index dc23f07..1e53060 100644 --- a/app/cmd/server_test.yaml +++ b/app/cmd/server_test.yaml @@ -49,6 +49,7 @@ auth: http: url: http://127.0.0.1:5000/auth insecure: true + command: /etc/some_command resolver: type: udp diff --git a/extras/auth/command.go b/extras/auth/command.go new file mode 100644 index 0000000..9c4d193 --- /dev/null +++ b/extras/auth/command.go @@ -0,0 +1,28 @@ +package auth + +import ( + "net" + "os/exec" + "strconv" + "strings" + + "github.com/apernet/hysteria/core/server" +) + +var _ server.Authenticator = &CommandAuthenticator{} + +type CommandAuthenticator struct { + Cmd string +} + +func (a *CommandAuthenticator) Authenticate(addr net.Addr, auth string, tx uint64) (ok bool, id string) { + cmd := exec.Command(a.Cmd, addr.String(), auth, strconv.Itoa(int(tx))) + out, err := cmd.Output() + if err != nil { + // This includes failing to execute the command, + // or the command exiting with a non-zero exit code. + return false, "" + } else { + return true, strings.TrimSpace(string(out)) + } +}