diff --git a/cmd/verysimple/apiServer.go b/cmd/verysimple/apiServer.go index 703e2da..5fe2bba 100644 --- a/cmd/verysimple/apiServer.go +++ b/cmd/verysimple/apiServer.go @@ -10,6 +10,7 @@ import ( "github.com/e1732a364fed/v2ray_simple/tlsLayer" "github.com/e1732a364fed/v2ray_simple/utils" + "go.uber.org/zap" ) var ( @@ -17,16 +18,18 @@ var ( apiServerRunning bool apiServerPathPrefix string apiServerAdminPass string + apiServerAddr string ) func init() { flag.BoolVar(&enableApiServer, "ea", false, "enable api server") flag.StringVar(&apiServerPathPrefix, "spp", "/api", "api Server Path Prefix, must start with '/' ") flag.StringVar(&apiServerAdminPass, "sap", "", "api Server admin password, but won't be used if it's empty") + flag.StringVar(&apiServerAddr, "sa", "127.0.0.1:48345", "api Server listen address") } -//非阻塞,如果运行成功则 apiServerRunning 会被设为 true +// 非阻塞,如果运行成功则 apiServerRunning 会被设为 true func tryRunApiServer() { var thepass string @@ -39,27 +42,67 @@ func tryRunApiServer() { thepass = apiServerAdminPass } - if thepass != "" { - apiServerRunning = true + apiServerRunning = true + + go runApiServer(thepass) - go runApiServer(thepass) - } } -//阻塞 +// 阻塞 func runApiServer(adminUUID string) { - utils.Info("Start Api Server") + utils.Info("Start Api Server at " + apiServerAddr) ser := newApiServer("admin", adminUUID) mux := http.NewServeMux() - mux.HandleFunc(apiServerPathPrefix+"/allstate", ser.basicAuth(func(w http.ResponseWriter, r *http.Request) { + + ser.addServerHandle(mux, "allstate", func(w http.ResponseWriter, r *http.Request) { printAllState(w, false) - })) + }) + ser.addServerHandle(mux, "hotLoadUrl", func(w http.ResponseWriter, r *http.Request) { + q := r.URL.Query() + + listenStr := q.Get("listen") + dialStr := q.Get("dial") + + f := r.Form + + if listenStr == "" { + listenStr = f.Get("listen") + } + if dialStr == "" { + dialStr = f.Get("dial") + } + + var resultStr string = "result:" + if listenStr != "" { + if ce := utils.CanLogInfo("api server got hot load listen request"); ce != nil { + ce.Write(zap.String("listenUrl", listenStr)) + } + e := hotLoadListenUrl(listenStr) + if e == nil { + resultStr += "\nhot load listen Url Success for " + listenStr + } else { + resultStr += "\nhot load listen Url Failed for " + listenStr + } + } + if dialStr != "" { + if ce := utils.CanLogInfo("api server got hot load dial request"); ce != nil { + ce.Write(zap.String("dialUrl", dialStr)) + } + e := hotLoadDialUrl(dialStr) + if e == nil { + resultStr += "\nhot load dial Url Success for " + dialStr + } else { + resultStr += "\nhot load dial Url Failed for " + dialStr + } + } + w.Write([]byte(resultStr)) + }) srv := &http.Server{ - Addr: "127.0.0.1:48345", + Addr: apiServerAddr, Handler: mux, IdleTimeout: time.Minute, ReadTimeout: 10 * time.Second, @@ -81,18 +124,34 @@ type auth struct { type apiServer struct { admin_auth auth + nopass bool } func newApiServer(user, pass string) *apiServer { s := new(apiServer) - s.admin_auth.expectedUsernameHash = sha256.Sum256([]byte(user)) - s.admin_auth.expectedPasswordHash = sha256.Sum256([]byte(pass)) + if pass != "" { + s.admin_auth.expectedUsernameHash = sha256.Sum256([]byte(user)) + s.admin_auth.expectedPasswordHash = sha256.Sum256([]byte(pass)) + + } else { + s.nopass = true + } return s } +func (ser *apiServer) addServerHandle(mux *http.ServeMux, name string, f func(w http.ResponseWriter, r *http.Request)) { + mux.HandleFunc(apiServerPathPrefix+"/"+name, ser.basicAuth(f)) +} + func (ser *apiServer) basicAuth(realfunc http.HandlerFunc) http.HandlerFunc { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + + if ser.nopass { + realfunc.ServeHTTP(w, r) + return + } + thisun, thispass, ok := r.BasicAuth() if ok { usernameHash := sha256.Sum256([]byte(thisun)) diff --git a/cmd/verysimple/cli.go b/cmd/verysimple/cli.go index a948ba1..2b0290f 100644 --- a/cmd/verysimple/cli.go +++ b/cmd/verysimple/cli.go @@ -251,12 +251,12 @@ func generateConfigFileInteractively() { switch ihot { case 0: - hotLoadDialConfForRuntime("", confServer.Dial) - hotLoadListenConfForRuntime(confServer.Listen) + hotLoadDialConf("", confServer.Dial) + hotLoadListenConf(confServer.Listen) case 1: - hotLoadDialConfForRuntime("", confClient.Dial) - hotLoadListenConfForRuntime(confClient.Listen) + hotLoadDialConf("", confClient.Dial) + hotLoadListenConf(confClient.Listen) } utils.PrintStr("加载成功!你可以回退(ctrl+c)到上级来使用 【查询当前状态】来查询新增的配置\n") @@ -430,52 +430,11 @@ func interactively_hotLoadUrlConfig() { } if i == 0 { - u, sn, creator, okTls, err := proxy.GetRealProtocolFromClientUrl(theUrlStr) - if err != nil { - fmt.Printf("parse url failed %v\n", err) - return - } - dc := &proxy.DialConf{} - dc.Protocol = sn - - dc.TLS = okTls - err = proxy.URLToDialConf(u, dc) - if err != nil { - fmt.Printf("parse url failed %v\n", err) - return - } - dc, err = creator.URLToDialConf(u, dc, proxy.UrlStandardFormat) - if err != nil { - fmt.Printf("parse url step 2 failed %v\n", err) - return - } - - hotLoadDialConfForRuntime("", []*proxy.DialConf{dc}) + hotLoadDialUrl(theUrlStr) } else { + hotLoadListenUrl(theUrlStr) - u, sn, creator, okTls, err := proxy.GetRealProtocolFromServerUrl(theUrlStr) - if err != nil { - fmt.Printf("parse url failed %v\n", err) - return - } - - lc := &proxy.ListenConf{} - lc.Protocol = sn - - lc.TLS = okTls - - err = proxy.URLToListenConf(u, lc) - if err != nil { - fmt.Printf("parse url failed %v\n", err) - return - } - lc, err = creator.URLToListenConf(u, lc, proxy.UrlStandardFormat) - if err != nil { - fmt.Printf("parse url step 2 failed %v\n", err) - return - } - hotLoadListenConfForRuntime([]*proxy.ListenConf{lc}) } return @@ -536,12 +495,12 @@ func interactively_hotLoadConfigFile() { switch confMode { case proxy.StandardMode: if len(standardConf.Dial) > 0 { - hotLoadDialConfForRuntime("", standardConf.Dial) + hotLoadDialConf("", standardConf.Dial) } if len(standardConf.Listen) > 0 { - hotLoadListenConfForRuntime(standardConf.Listen) + hotLoadListenConf(standardConf.Listen) } case proxy.SimpleMode: diff --git a/cmd/verysimple/cmd.go b/cmd/verysimple/cmd.go index 21d79d2..3a53c31 100644 --- a/cmd/verysimple/cmd.go +++ b/cmd/verysimple/cmd.go @@ -276,7 +276,9 @@ func tryDownloadGeositeSource() { } -func hotLoadDialConfForRuntime(Default_uuid string, conf []*proxy.DialConf) { +func hotLoadDialConf(Default_uuid string, conf []*proxy.DialConf) (ok bool) { + ok = true + for _, d := range conf { if d.Uuid == "" && Default_uuid != "" { @@ -288,6 +290,7 @@ func hotLoadDialConfForRuntime(Default_uuid string, conf []*proxy.DialConf) { if ce := utils.CanLogErr("can not create outClient: "); ce != nil { ce.Write(zap.Error(err)) } + ok = false continue } @@ -307,9 +310,11 @@ func hotLoadDialConfForRuntime(Default_uuid string, conf []*proxy.DialConf) { defaultOutClient = vs.DirectClient } } + return } -func hotLoadListenConfForRuntime(conf []*proxy.ListenConf) { +func hotLoadListenConf(conf []*proxy.ListenConf) (ok bool) { + ok = true if defaultOutClient == nil { defaultOutClient = vs.DirectClient @@ -319,7 +324,8 @@ func hotLoadListenConfForRuntime(conf []*proxy.ListenConf) { inServer, err := proxy.NewServer(l) if err != nil { log.Println("can not create inServer: ", i, err) - return + ok = false + continue } lis := vs.ListenSer(inServer, defaultOutClient, &routingEnv) if lis != nil { @@ -330,6 +336,63 @@ func hotLoadListenConfForRuntime(conf []*proxy.ListenConf) { } + return +} + +func hotLoadDialUrl(theUrlStr string) error { + u, sn, creator, okTls, err := proxy.GetRealProtocolFromClientUrl(theUrlStr) + if err != nil { + fmt.Printf("parse url failed %v\n", err) + return err + } + dc := &proxy.DialConf{} + dc.Protocol = sn + + dc.TLS = okTls + err = proxy.URLToDialConf(u, dc) + if err != nil { + fmt.Printf("parse url failed %v\n", err) + return err + } + dc, err = creator.URLToDialConf(u, dc, proxy.UrlStandardFormat) + if err != nil { + fmt.Printf("parse url step 2 failed %v\n", err) + return err + } + + if !hotLoadDialConf("", []*proxy.DialConf{dc}) { + return utils.ErrFailed + } + return nil + +} + +func hotLoadListenUrl(theUrlStr string) error { + u, sn, creator, okTls, err := proxy.GetRealProtocolFromServerUrl(theUrlStr) + if err != nil { + fmt.Printf("parse url failed %v\n", err) + return err + } + + lc := &proxy.ListenConf{} + lc.Protocol = sn + + lc.TLS = okTls + + err = proxy.URLToListenConf(u, lc) + if err != nil { + fmt.Printf("parse url failed %v\n", err) + return err + } + lc, err = creator.URLToListenConf(u, lc, proxy.UrlStandardFormat) + if err != nil { + fmt.Printf("parse url step 2 failed %v\n", err) + return err + } + if !hotLoadListenConf([]*proxy.ListenConf{lc}) { + return utils.ErrFailed + } + return nil } func loadSimpleServer() (result int, server proxy.Server) { diff --git a/cmd/verysimple/main.go b/cmd/verysimple/main.go index 7414520..11fdfd5 100644 --- a/cmd/verysimple/main.go +++ b/cmd/verysimple/main.go @@ -362,7 +362,7 @@ func mainFunc() (result int) { break } - hotLoadDialConfForRuntime(Default_uuid, standardConf.Dial) + hotLoadDialConf(Default_uuid, standardConf.Dial) } diff --git a/utils/cast.go b/utils/cast.go index 632acec..dd146f1 100644 --- a/utils/cast.go +++ b/utils/cast.go @@ -44,11 +44,16 @@ func AnyToBool(a any) (v bool, ok bool) { v = true } case string: - if StrNegative(value) { - v = false - } else if StrPositive(value) { - v = true + if b, e := strconv.ParseBool(value); e == nil { + v = b + } else { + if StrNegative(value) { + v = false + } else if StrPositive(value) { + v = true + } } + default: var i64 int64 i64, ok = AnyToInt64(a)