diff --git a/Makefile b/Makefile index 966f8f4..e2f5471 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,12 @@ export GO111MODULE=on +export CGO_ENABLED=0 +export GOOS=linux +export GOARCH=amd64 build: frps-multiuser cp ./config/frps-multiuser.ini ./bin/frps-multiuser.ini cp -r ./assets/ ./bin/assets/ frps-multiuser: + rm -rf ./bin go build -o ./bin/frps-multiuser ./cmd/frps-multiuser diff --git a/README.md b/README.md index 5a56a3b..ba8100f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # frps-multiuser +[README](README.md) | [中文文档](README_zh.md) + frp server plugin to support multiple users for [frp](https://github.com/fatedier/frp). frps-multiuser will run as one single process and accept HTTP requests from frps. @@ -23,8 +25,6 @@ frps-multiuser will run as one single process and accept HTTP requests from frps ***when a user is dynamic been `remove` or `disable`,it will take some time to be effective*** ***the limit of `ports`、`domains`、`subdomains` only effective at `NewProxy`*** -[README](README.md) | [中文文档](README_zh.md) - ### Features * Support multiple user authentication by tokens saved in file. @@ -132,6 +132,8 @@ remote_port = 6000 ## Issues & Ideas +___If you want visit mange ui from internet, you should change `plugin_addr` to `0.0.0.0`___ + If you have any issues or ideas, put it on [issues](https://github.com/yhl452493373/frps-multiuser/issues). I will try my best to achieve it. ## Credits diff --git a/README_zh.md b/README_zh.md index 2d8292f..7b8a65d 100644 --- a/README_zh.md +++ b/README_zh.md @@ -132,6 +132,8 @@ remote_port = 6000 ## 使用 +___如果要从外网访问管理界面, 需要把配置中的 `plugin_addr` 改为 `0.0.0.0`___ + 如果使用中有问题或者有其他想法,在[issues](https://github.com/yhl452493373/frps-multiuser/issues)上提出来。 如果我能搞定的话,我尽量搞。 ## 致谢 diff --git a/cmd/frps-multiuser/cmd.go b/cmd/frps-multiuser/cmd.go index fe93220..7e84bc3 100644 --- a/cmd/frps-multiuser/cmd.go +++ b/cmd/frps-multiuser/cmd.go @@ -9,6 +9,7 @@ import ( "io/fs" "log" "os" + "path/filepath" "strconv" "strings" ) @@ -33,20 +34,29 @@ var rootCmd = &cobra.Command{ log.Println(version) return nil } + executable, err := os.Executable() + if err != nil { + log.Printf("error get program path: %v", err) + return err + } + rootDir := filepath.Dir(executable) + common, tokens, ports, domains, subdomains, iniFile, err := ParseConfigFile(configFile) if err != nil { log.Printf("fail to start frps-multiuser : %v", err) - return nil + return err } - s, err := server.New(controller.HandleController{ - CommonInfo: common, - Tokens: tokens, - Ports: ports, - Domains: domains, - Subdomains: subdomains, - ConfigFile: configFile, - IniFile: iniFile, - }) + s, err := server.New( + rootDir, + controller.HandleController{ + CommonInfo: common, + Tokens: tokens, + Ports: ports, + Domains: domains, + Subdomains: subdomains, + ConfigFile: configFile, + IniFile: iniFile, + }) if err != nil { return err } diff --git a/pkg/server/controller/controller.go b/pkg/server/controller/controller.go index 73625a3..3bc6ee4 100644 --- a/pkg/server/controller/controller.go +++ b/pkg/server/controller/controller.go @@ -23,7 +23,7 @@ const ( TokenFormatError = 5 ) -var UserFormatReg = regexp.MustCompile("^\\w$") +var UserFormatReg = regexp.MustCompile("^\\w+$") var TokenFormatReg = regexp.MustCompile("^[\\w!@#$%^&*()]+$") var TrimAllSpaceReg = regexp.MustCompile("[\\n\\t\\r\\s]") var TrimBreakLineReg = regexp.MustCompile("[\\n\\t\\r]") diff --git a/pkg/server/controller/op.go b/pkg/server/controller/op.go index 460fd32..ddbc0f2 100644 --- a/pkg/server/controller/op.go +++ b/pkg/server/controller/op.go @@ -6,6 +6,8 @@ import ( "github.com/gin-gonic/gin" "gopkg.in/ini.v1" "log" + "os" + "path/filepath" "strconv" "strings" ) @@ -24,9 +26,15 @@ func NewHandleController(config *HandleController) *HandleController { return config } -func (c *HandleController) Register(engine *gin.Engine) { +func (c *HandleController) Register(rootDir string, engine *gin.Engine) { + assets := filepath.Join(rootDir, "assets") + _, err := os.Stat(assets) + if err != nil && !os.IsExist(err) { + assets = "./assets" + } + engine.Delims("${", "}") - engine.LoadHTMLGlob("./assets/templates/*") + engine.LoadHTMLGlob(filepath.Join(assets, "templates/*")) engine.POST("/handler", c.MakeHandlerFunc()) var group *gin.RouterGroup @@ -37,7 +45,7 @@ func (c *HandleController) Register(engine *gin.Engine) { } else { group = engine.Group("/") } - group.Static("/static", "./assets/static") + group.Static("/static", filepath.Join(assets, "static")) group.GET("/", c.MakeManagerFunc()) group.GET("/lang", c.MakeLangFunc()) group.GET("/tokens", c.MakeQueryTokensFunc()) diff --git a/pkg/server/server.go b/pkg/server/server.go index 5b5ec83..6c081d8 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -13,21 +13,24 @@ import ( "net" "net/http" "os" + "path/filepath" "strconv" "strings" "time" ) type Server struct { - cfg controller.HandleController - s *http.Server - done chan struct{} + cfg controller.HandleController + s *http.Server + done chan struct{} + rootDir string } -func New(cfg controller.HandleController) (*Server, error) { +func New(rootDir string, cfg controller.HandleController) (*Server, error) { s := &Server{ - cfg: cfg, - done: make(chan struct{}), + cfg: cfg, + done: make(chan struct{}), + rootDir: rootDir, } if err := s.init(); err != nil { return nil, err @@ -74,14 +77,10 @@ func LoadSupportLanguage(dir string) ([]language.Tag, error) { var tags []language.Tag files, err := os.Open(dir) - if err != nil { - log.Printf("error opening directory: %v", err) - return tags, err - } fileList, err := files.Readdir(-1) if err != nil { - log.Printf("error reading directory: %v", err) + log.Printf("error read lang directory: %v", err) return tags, err } @@ -103,15 +102,21 @@ func LoadSupportLanguage(dir string) ([]language.Tag, error) { return tags, nil } -func GinI18nLocalize() gin.HandlerFunc { - dir := "./assets/lang" - tags, err := LoadSupportLanguage(dir) +func GinI18nLocalize(rootDir string) gin.HandlerFunc { + assets := filepath.Join(rootDir, "assets") + _, err := os.Stat(assets) + if err != nil && !os.IsExist(err) { + assets = "./assets" + } + lang := filepath.Join(assets, "lang") + tags, err := LoadSupportLanguage(lang) if err != nil { log.Panicf("language file is not found: %v", err) } + return ginI18n.Localize( ginI18n.WithBundle(&ginI18n.BundleCfg{ - RootPath: dir, + RootPath: lang, AcceptLanguage: tags, DefaultLanguage: language.Chinese, FormatBundleFile: "json", @@ -133,10 +138,10 @@ func GinI18nLocalize() gin.HandlerFunc { func (s *Server) initHTTPServer() error { gin.SetMode(gin.ReleaseMode) engine := gin.New() - engine.Use(GinI18nLocalize()) + engine.Use(GinI18nLocalize(s.rootDir)) s.s = &http.Server{ Handler: engine, } - controller.NewHandleController(&s.cfg).Register(engine) + controller.NewHandleController(&s.cfg).Register(s.rootDir, engine) return nil }