mirror of
https://github.com/yhl452493373/frps-panel.git
synced 2026-04-04 14:27:00 +08:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5e90c9e6c | ||
|
|
c8c6d17c9c | ||
|
|
dd87729455 |
4
Makefile
4
Makefile
@@ -1,8 +1,12 @@
|
|||||||
export GO111MODULE=on
|
export GO111MODULE=on
|
||||||
|
export CGO_ENABLED=0
|
||||||
|
export GOOS=linux
|
||||||
|
export GOARCH=amd64
|
||||||
|
|
||||||
build: frps-multiuser
|
build: frps-multiuser
|
||||||
cp ./config/frps-multiuser.ini ./bin/frps-multiuser.ini
|
cp ./config/frps-multiuser.ini ./bin/frps-multiuser.ini
|
||||||
cp -r ./assets/ ./bin/assets/
|
cp -r ./assets/ ./bin/assets/
|
||||||
|
|
||||||
frps-multiuser:
|
frps-multiuser:
|
||||||
|
rm -rf ./bin
|
||||||
go build -o ./bin/frps-multiuser ./cmd/frps-multiuser
|
go build -o ./bin/frps-multiuser ./cmd/frps-multiuser
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# frps-multiuser
|
# frps-multiuser
|
||||||
|
|
||||||
|
[README](README.md) | [中文文档](README_zh.md)
|
||||||
|
|
||||||
frp server plugin to support multiple users for [frp](https://github.com/fatedier/frp).
|
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.
|
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***
|
***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`***
|
***the limit of `ports`、`domains`、`subdomains` only effective at `NewProxy`***
|
||||||
|
|
||||||
[README](README.md) | [中文文档](README_zh.md)
|
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
* Support multiple user authentication by tokens saved in file.
|
* Support multiple user authentication by tokens saved in file.
|
||||||
@@ -132,6 +132,8 @@ remote_port = 6000
|
|||||||
|
|
||||||
## Issues & Ideas
|
## 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.
|
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
|
## Credits
|
||||||
|
|||||||
@@ -132,6 +132,8 @@ remote_port = 6000
|
|||||||
|
|
||||||
## 使用
|
## 使用
|
||||||
|
|
||||||
|
___如果要从外网访问管理界面, 需要把配置中的 `plugin_addr` 改为 `0.0.0.0`___
|
||||||
|
|
||||||
如果使用中有问题或者有其他想法,在[issues](https://github.com/yhl452493373/frps-multiuser/issues)上提出来。 如果我能搞定的话,我尽量搞。
|
如果使用中有问题或者有其他想法,在[issues](https://github.com/yhl452493373/frps-multiuser/issues)上提出来。 如果我能搞定的话,我尽量搞。
|
||||||
|
|
||||||
## 致谢
|
## 致谢
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
"Allowed domains": "允许域名",
|
"Allowed domains": "允许域名",
|
||||||
"Please input allowed domains": "请输入允许使用的域名,如:web01.domain.com,web02.domain.com",
|
"Please input allowed domains": "请输入允许使用的域名,如:web01.domain.com,web02.domain.com",
|
||||||
"Allowed subdomains": "允许子域名",
|
"Allowed subdomains": "允许子域名",
|
||||||
"Please input allowed subdomains": "请输入允许使用的端口,如:web01,web02",
|
"Please input allowed subdomains": "请输入允许使用的子域名,如:web01,web02",
|
||||||
"Ports is invalid": "端口不正确",
|
"Ports is invalid": "端口不正确",
|
||||||
"Domains is invalid": "域名不正确",
|
"Domains is invalid": "域名不正确",
|
||||||
"Subdomains is invalid": "子域名不正确",
|
"Subdomains is invalid": "子域名不正确",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"io/fs"
|
"io/fs"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@@ -33,12 +34,21 @@ var rootCmd = &cobra.Command{
|
|||||||
log.Println(version)
|
log.Println(version)
|
||||||
return nil
|
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)
|
common, tokens, ports, domains, subdomains, iniFile, err := ParseConfigFile(configFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("fail to start frps-multiuser : %v", err)
|
log.Printf("fail to start frps-multiuser : %v", err)
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
s, err := server.New(controller.HandleController{
|
s, err := server.New(
|
||||||
|
rootDir,
|
||||||
|
controller.HandleController{
|
||||||
CommonInfo: common,
|
CommonInfo: common,
|
||||||
Tokens: tokens,
|
Tokens: tokens,
|
||||||
Ports: ports,
|
Ports: ports,
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const (
|
|||||||
TokenFormatError = 5
|
TokenFormatError = 5
|
||||||
)
|
)
|
||||||
|
|
||||||
var UserFormatReg = regexp.MustCompile("^\\w$")
|
var UserFormatReg = regexp.MustCompile("^\\w+$")
|
||||||
var TokenFormatReg = regexp.MustCompile("^[\\w!@#$%^&*()]+$")
|
var TokenFormatReg = regexp.MustCompile("^[\\w!@#$%^&*()]+$")
|
||||||
var TrimAllSpaceReg = regexp.MustCompile("[\\n\\t\\r\\s]")
|
var TrimAllSpaceReg = regexp.MustCompile("[\\n\\t\\r\\s]")
|
||||||
var TrimBreakLineReg = regexp.MustCompile("[\\n\\t\\r]")
|
var TrimBreakLineReg = regexp.MustCompile("[\\n\\t\\r]")
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"gopkg.in/ini.v1"
|
"gopkg.in/ini.v1"
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@@ -24,9 +26,15 @@ func NewHandleController(config *HandleController) *HandleController {
|
|||||||
return config
|
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.Delims("${", "}")
|
||||||
engine.LoadHTMLGlob("./assets/templates/*")
|
engine.LoadHTMLGlob(filepath.Join(assets, "templates/*"))
|
||||||
engine.POST("/handler", c.MakeHandlerFunc())
|
engine.POST("/handler", c.MakeHandlerFunc())
|
||||||
|
|
||||||
var group *gin.RouterGroup
|
var group *gin.RouterGroup
|
||||||
@@ -37,7 +45,7 @@ func (c *HandleController) Register(engine *gin.Engine) {
|
|||||||
} else {
|
} else {
|
||||||
group = engine.Group("/")
|
group = engine.Group("/")
|
||||||
}
|
}
|
||||||
group.Static("/static", "./assets/static")
|
group.Static("/static", filepath.Join(assets, "static"))
|
||||||
group.GET("/", c.MakeManagerFunc())
|
group.GET("/", c.MakeManagerFunc())
|
||||||
group.GET("/lang", c.MakeLangFunc())
|
group.GET("/lang", c.MakeLangFunc())
|
||||||
group.GET("/tokens", c.MakeQueryTokensFunc())
|
group.GET("/tokens", c.MakeQueryTokensFunc())
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -22,12 +23,14 @@ type Server struct {
|
|||||||
cfg controller.HandleController
|
cfg controller.HandleController
|
||||||
s *http.Server
|
s *http.Server
|
||||||
done chan struct{}
|
done chan struct{}
|
||||||
|
rootDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(cfg controller.HandleController) (*Server, error) {
|
func New(rootDir string, cfg controller.HandleController) (*Server, error) {
|
||||||
s := &Server{
|
s := &Server{
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
done: make(chan struct{}),
|
done: make(chan struct{}),
|
||||||
|
rootDir: rootDir,
|
||||||
}
|
}
|
||||||
if err := s.init(); err != nil {
|
if err := s.init(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -74,14 +77,10 @@ func LoadSupportLanguage(dir string) ([]language.Tag, error) {
|
|||||||
var tags []language.Tag
|
var tags []language.Tag
|
||||||
|
|
||||||
files, err := os.Open(dir)
|
files, err := os.Open(dir)
|
||||||
if err != nil {
|
|
||||||
log.Printf("error opening directory: %v", err)
|
|
||||||
return tags, err
|
|
||||||
}
|
|
||||||
|
|
||||||
fileList, err := files.Readdir(-1)
|
fileList, err := files.Readdir(-1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("error reading directory: %v", err)
|
log.Printf("error read lang directory: %v", err)
|
||||||
return tags, err
|
return tags, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,15 +102,21 @@ func LoadSupportLanguage(dir string) ([]language.Tag, error) {
|
|||||||
return tags, nil
|
return tags, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GinI18nLocalize() gin.HandlerFunc {
|
func GinI18nLocalize(rootDir string) gin.HandlerFunc {
|
||||||
dir := "./assets/lang"
|
assets := filepath.Join(rootDir, "assets")
|
||||||
tags, err := LoadSupportLanguage(dir)
|
_, err := os.Stat(assets)
|
||||||
|
if err != nil && !os.IsExist(err) {
|
||||||
|
assets = "./assets"
|
||||||
|
}
|
||||||
|
lang := filepath.Join(assets, "lang")
|
||||||
|
tags, err := LoadSupportLanguage(lang)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("language file is not found: %v", err)
|
log.Panicf("language file is not found: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ginI18n.Localize(
|
return ginI18n.Localize(
|
||||||
ginI18n.WithBundle(&ginI18n.BundleCfg{
|
ginI18n.WithBundle(&ginI18n.BundleCfg{
|
||||||
RootPath: dir,
|
RootPath: lang,
|
||||||
AcceptLanguage: tags,
|
AcceptLanguage: tags,
|
||||||
DefaultLanguage: language.Chinese,
|
DefaultLanguage: language.Chinese,
|
||||||
FormatBundleFile: "json",
|
FormatBundleFile: "json",
|
||||||
@@ -133,10 +138,10 @@ func GinI18nLocalize() gin.HandlerFunc {
|
|||||||
func (s *Server) initHTTPServer() error {
|
func (s *Server) initHTTPServer() error {
|
||||||
gin.SetMode(gin.ReleaseMode)
|
gin.SetMode(gin.ReleaseMode)
|
||||||
engine := gin.New()
|
engine := gin.New()
|
||||||
engine.Use(GinI18nLocalize())
|
engine.Use(GinI18nLocalize(s.rootDir))
|
||||||
s.s = &http.Server{
|
s.s = &http.Server{
|
||||||
Handler: engine,
|
Handler: engine,
|
||||||
}
|
}
|
||||||
controller.NewHandleController(&s.cfg).Register(engine)
|
controller.NewHandleController(&s.cfg).Register(s.rootDir, engine)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 327 KiB After Width: | Height: | Size: 331 KiB |
Reference in New Issue
Block a user