From 461b16f07fb9fec65d8a800d222c490e9faea782 Mon Sep 17 00:00:00 2001 From: Toby Date: Sun, 4 Apr 2021 14:47:07 -0700 Subject: [PATCH] External HTTP auth implementation --- cmd/server.go | 19 ++++++++++++++++ pkg/auth/http.go | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 pkg/auth/http.go diff --git a/cmd/server.go b/cmd/server.go index fe18332..b588b85 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -6,12 +6,15 @@ import ( "github.com/lucas-clemente/quic-go/congestion" "github.com/sirupsen/logrus" "github.com/tobyxdd/hysteria/pkg/acl" + "github.com/tobyxdd/hysteria/pkg/auth" hyCongestion "github.com/tobyxdd/hysteria/pkg/congestion" "github.com/tobyxdd/hysteria/pkg/core" "github.com/tobyxdd/hysteria/pkg/obfs" "github.com/yosuke-furukawa/json5/encoding/json5" "io" "net" + "net/http" + "time" ) func server(config *serverConfig) { @@ -72,6 +75,22 @@ func server(config *serverConfig) { return false, "Wrong password" } } + case "external": + logrus.Info("External authentication enabled") + var extConfig map[string]string + err = json5.Unmarshal(config.Auth.Config, &extConfig) + if err != nil || len(extConfig["http"]) == 0 { + logrus.WithFields(logrus.Fields{ + "error": err, + }).Fatal("Invalid external authentication config") + } + provider := &auth.HTTPAuthProvider{ + Client: &http.Client{ + Timeout: 10 * time.Second, + }, + URL: extConfig["http"], + } + authFunc = provider.Auth default: logrus.WithField("mode", config.Auth.Mode).Fatal("Unsupported authentication mode") } diff --git a/pkg/auth/http.go b/pkg/auth/http.go new file mode 100644 index 0000000..be55836 --- /dev/null +++ b/pkg/auth/http.go @@ -0,0 +1,56 @@ +package auth + +import ( + "bytes" + "encoding/json" + "io/ioutil" + "net" + "net/http" +) + +type HTTPAuthProvider struct { + Client *http.Client + URL string +} + +type authReq struct { + Addr string `json:"addr"` + Payload []byte `json:"payload"` + Send uint64 `json:"send"` + Recv uint64 `json:"recv"` +} + +type authResp struct { + OK bool `json:"ok"` + Msg string `json:"msg"` +} + +func (p *HTTPAuthProvider) Auth(addr net.Addr, auth []byte, sSend uint64, sRecv uint64) (bool, string) { + jbs, err := json.Marshal(&authReq{ + Addr: addr.String(), + Payload: auth, + Send: sSend, + Recv: sRecv, + }) + if err != nil { + return false, "Internal error" + } + resp, err := p.Client.Post(p.URL, "application/json", bytes.NewBuffer(jbs)) + if err != nil { + return false, "Internal error" + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return false, "Auth endpoint error" + } + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + return false, "Auth endpoint error" + } + var ar authResp + err = json.Unmarshal(data, &ar) + if err != nil { + return false, "Auth endpoint error" + } + return ar.OK, ar.Msg +}