From 3eca20e9272e80f8ebdb328b868ca5d3d1431598 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E9=BB=84=E6=9E=97?= Date: Sat, 9 Sep 2023 20:46:54 +0800 Subject: [PATCH] add an api proxy url to access frp server info --- assets/static/css/index.css | 16 +++++ assets/static/js/index-server-info.js | 37 +++------- assets/static/js/index-user-list.js | 3 +- assets/static/js/index.js | 4 +- assets/static/{js => lib}/echarts.min.js | 0 assets/static/{js => lib}/filesize.min.js | 0 assets/static/{ => lib}/layui/css/layui.css | 0 .../static/{ => lib}/layui/font/iconfont.eot | Bin .../static/{ => lib}/layui/font/iconfont.svg | 0 .../static/{ => lib}/layui/font/iconfont.ttf | Bin .../static/{ => lib}/layui/font/iconfont.woff | Bin .../{ => lib}/layui/font/iconfont.woff2 | Bin assets/static/{ => lib}/layui/layui.js | 0 assets/templates/index.html | 15 ++--- cmd/frps-multiuser/cmd.go | 23 ++----- config/frps-multiuser.ini | 11 ++- pkg/server/controller/controller.go | 63 ++++++++++++++++-- pkg/server/controller/op.go | 1 + 18 files changed, 110 insertions(+), 63 deletions(-) rename assets/static/{js => lib}/echarts.min.js (100%) rename assets/static/{js => lib}/filesize.min.js (100%) rename assets/static/{ => lib}/layui/css/layui.css (100%) rename assets/static/{ => lib}/layui/font/iconfont.eot (100%) rename assets/static/{ => lib}/layui/font/iconfont.svg (100%) rename assets/static/{ => lib}/layui/font/iconfont.ttf (100%) rename assets/static/{ => lib}/layui/font/iconfont.woff (100%) rename assets/static/{ => lib}/layui/font/iconfont.woff2 (100%) rename assets/static/{ => lib}/layui/layui.js (100%) diff --git a/assets/static/css/index.css b/assets/static/css/index.css index f5bf218..1a4b504 100644 --- a/assets/static/css/index.css +++ b/assets/static/css/index.css @@ -14,6 +14,22 @@ section { box-sizing: border-box; } +.layui-header{ + line-height: 60px; + font-size: 16px; +} + +.layui-title{ + position: absolute; + left: 200px; + right: 0; + top: 0; + height: 100%; + color: #fff; + padding: 0 15px; + box-sizing: border-box; +} + #searchForm input { height: 30px; line-height: 28px; diff --git a/assets/static/js/index-server-info.js b/assets/static/js/index-server-info.js index b9bdccf..04301cd 100644 --- a/assets/static/js/index-server-info.js +++ b/assets/static/js/index-server-info.js @@ -5,37 +5,20 @@ var loadServerInfo = (function ($) { * get server info * @param lang {{}} language json */ - function loadServerInfo(lang) { + function loadServerInfo(lang, title) { + console.log(title) + $("#title").text(title); $('#content').empty(); var loading = layui.layer.load(); - $.ajax({ - url: 'http://127.0.0.1:7500/api/serverinfo', - dataType: 'jsonp', - success: function (result) { - result = { - "version": "0.51.3", - "bind_port": 7000, - "vhost_http_port": 80, - "vhost_https_port": 443, - "tcpmux_httpconnect_port": 0, - "kcp_bind_port": 7000, - "quic_bind_port": 0, - "subdomain_host": "frp.yanghuanglin.com", - "max_pool_count": 100, - "max_ports_per_client": 0, - "heart_beat_timeout": 90, - "total_traffic_in": 1669491, - "total_traffic_out": 54422369, - "cur_conns": 0, - "client_counts": 1, - "proxy_type_count": {"http": 9, "https": 8, "tcp": 7} - }; - renderServerInfo(result); - }, - complete: function () { - layui.layer.close(loading); + $.getJSON('/proxy/api/serverinfo').done(function (result) { + if (result.success) { + renderServerInfo(JSON.parse(result.data)); + } else { + layui.layer.msg(result.message); } + }).always(function () { + layui.layer.close(loading); }); } diff --git a/assets/static/js/index-user-list.js b/assets/static/js/index-user-list.js index 251e5ac..6027eb1 100644 --- a/assets/static/js/index-user-list.js +++ b/assets/static/js/index-user-list.js @@ -140,7 +140,8 @@ var loadUserList = (function ($) { * load i18n language * @param lang {{}} language json */ - function loadUserList(lang) { + function loadUserList(lang, title) { + $("#title").text(title); var html = layui.laytpl($('#userListTemplate').html()).render(); $('#content').html(html); diff --git a/assets/static/js/index.js b/assets/static/js/index.js index e84a0f8..eabc37a 100644 --- a/assets/static/js/index.js +++ b/assets/static/js/index.js @@ -4,9 +4,9 @@ $.getJSON('/lang').done(function (lang) { layui.element.on('nav(leftNav)', function (elem) { if (elem.attr('id') === 'serverInfo') { - loadServerInfo(lang); + loadServerInfo(lang, elem.text().trim()); } else if (elem.attr('id') === 'userList') { - loadUserList(lang); + loadUserList(lang, elem.text().trim()); } }); diff --git a/assets/static/js/echarts.min.js b/assets/static/lib/echarts.min.js similarity index 100% rename from assets/static/js/echarts.min.js rename to assets/static/lib/echarts.min.js diff --git a/assets/static/js/filesize.min.js b/assets/static/lib/filesize.min.js similarity index 100% rename from assets/static/js/filesize.min.js rename to assets/static/lib/filesize.min.js diff --git a/assets/static/layui/css/layui.css b/assets/static/lib/layui/css/layui.css similarity index 100% rename from assets/static/layui/css/layui.css rename to assets/static/lib/layui/css/layui.css diff --git a/assets/static/layui/font/iconfont.eot b/assets/static/lib/layui/font/iconfont.eot similarity index 100% rename from assets/static/layui/font/iconfont.eot rename to assets/static/lib/layui/font/iconfont.eot diff --git a/assets/static/layui/font/iconfont.svg b/assets/static/lib/layui/font/iconfont.svg similarity index 100% rename from assets/static/layui/font/iconfont.svg rename to assets/static/lib/layui/font/iconfont.svg diff --git a/assets/static/layui/font/iconfont.ttf b/assets/static/lib/layui/font/iconfont.ttf similarity index 100% rename from assets/static/layui/font/iconfont.ttf rename to assets/static/lib/layui/font/iconfont.ttf diff --git a/assets/static/layui/font/iconfont.woff b/assets/static/lib/layui/font/iconfont.woff similarity index 100% rename from assets/static/layui/font/iconfont.woff rename to assets/static/lib/layui/font/iconfont.woff diff --git a/assets/static/layui/font/iconfont.woff2 b/assets/static/lib/layui/font/iconfont.woff2 similarity index 100% rename from assets/static/layui/font/iconfont.woff2 rename to assets/static/lib/layui/font/iconfont.woff2 diff --git a/assets/static/layui/layui.js b/assets/static/lib/layui/layui.js similarity index 100% rename from assets/static/layui/layui.js rename to assets/static/lib/layui/layui.js diff --git a/assets/templates/index.html b/assets/templates/index.html index 2efcb21..8e55e1e 100644 --- a/assets/templates/index.html +++ b/assets/templates/index.html @@ -2,13 +2,13 @@ ${ .UserManage } - + - - - + + + @@ -22,13 +22,7 @@ } @@ -37,6 +31,7 @@
+
diff --git a/cmd/frps-multiuser/cmd.go b/cmd/frps-multiuser/cmd.go index 7e84bc3..a3557d3 100644 --- a/cmd/frps-multiuser/cmd.go +++ b/cmd/frps-multiuser/cmd.go @@ -10,7 +10,6 @@ import ( "log" "os" "path/filepath" - "strconv" "strings" ) @@ -103,24 +102,14 @@ func ParseConfigFile(file string) (controller.CommonInfo, map[string]controller. log.Printf("fail to get [common] section from file %s : %v", file, err) return common, nil, nil, nil, nil, iniFile, err } - pluginAddr := commonSection.Key("plugin_addr").Value() - if len(pluginAddr) != 0 { - common.PluginAddr = pluginAddr - } else { - common.PluginAddr = "0.0.0.0" - } - pluginPort := commonSection.Key("plugin_port").Value() - if len(pluginPort) != 0 { - port, err := strconv.Atoi(pluginPort) - if err != nil { - return common, nil, nil, nil, nil, iniFile, err - } - common.PluginPort = port - } else { - common.PluginPort = 7200 - } + common.PluginAddr = commonSection.Key("plugin_addr").MustString("0.0.0.0") + common.PluginPort = commonSection.Key("plugin_port").MustInt(7200) common.User = commonSection.Key("admin_user").Value() common.Pwd = commonSection.Key("admin_pwd").Value() + common.DashboardAddr = commonSection.Key("dashboard_addr").MustString("127.0.0.1") + common.DashboardPort = commonSection.Key("dashboard_port").MustInt(7500) + common.DashboardUser = commonSection.Key("dashboard_user").Value() + common.DashboardPwd = commonSection.Key("dashboard_pwd").Value() portsSection, err := iniFile.GetSection("ports") if err != nil { diff --git a/config/frps-multiuser.ini b/config/frps-multiuser.ini index 812c268..0f721f5 100644 --- a/config/frps-multiuser.ini +++ b/config/frps-multiuser.ini @@ -1,9 +1,16 @@ ; basic options [common] +; frps config info plugin_addr = 127.0.0.1 plugin_port = 7200 -admin_user = admin -admin_pwd = admin +admin_user = admin +admin_pwd = admin + +; frp dashboard config info +dashboard_addr = 127.0.0.1 +dashboard_port = 7500 +dashboard_user = admin +dashboard_pwd = admin ; user tokens [users] diff --git a/pkg/server/controller/controller.go b/pkg/server/controller/controller.go index 0bd20dc..8fe549b 100644 --- a/pkg/server/controller/controller.go +++ b/pkg/server/controller/controller.go @@ -1,16 +1,19 @@ package controller import ( + "encoding/base64" "encoding/json" "errors" "fmt" plugin "github.com/fatedier/frp/pkg/plugin/server" ginI18n "github.com/gin-contrib/i18n" "github.com/gin-gonic/gin" + "io" "log" "net/http" "regexp" "sort" + "strconv" "strings" ) @@ -21,6 +24,7 @@ const ( SaveError = 3 UserFormatError = 4 TokenFormatError = 5 + FrpServerError = 6 ) var UserFormatReg = regexp.MustCompile("^\\w+$") @@ -38,10 +42,14 @@ type HTTPError struct { } type CommonInfo struct { - PluginAddr string - PluginPort int - User string - Pwd string + PluginAddr string + PluginPort int + User string + Pwd string + DashboardAddr string + DashboardPort int + DashboardUser string + DashboardPwd string } type TokenInfo struct { @@ -67,6 +75,11 @@ type OperationResponse struct { Message string `json:"message"` } +type ProxyResponse struct { + OperationResponse + Data string `json:"data"` +} + type TokenSearch struct { TokenInfo Page int `form:"page"` @@ -632,3 +645,45 @@ func (c *HandleController) MakeEnableTokensFunc() func(context *gin.Context) { context.JSON(http.StatusOK, &response) } } + +func (c *HandleController) MakeProxyFunc() func(context *gin.Context) { + return func(context *gin.Context) { + res := ProxyResponse{} + host := c.CommonInfo.DashboardAddr + port := c.CommonInfo.DashboardPort + requestUrl := "http://" + host + ":" + strconv.Itoa(port) + context.Param("serverApi") + request, _ := http.NewRequest("GET", requestUrl, nil) + username := c.CommonInfo.DashboardUser + if len(strings.TrimSpace(username)) != 0 { + password := c.CommonInfo.DashboardPwd + auth := []byte(username + ":" + password) + request.Header.Add("Authorization", "Basic "+base64.StdEncoding.EncodeToString(auth)) + } + response, err := http.DefaultClient.Do(request) + + if err != nil { + res.Code = FrpServerError + res.Success = false + res.Message = err.Error() + context.JSON(http.StatusOK, &res) + return + } + + res.Code = response.StatusCode + body, err := io.ReadAll(response.Body) + + if err != nil { + res.Success = false + res.Message = err.Error() + } else { + if res.Code == http.StatusOK { + res.Success = true + res.Data = string(body) + } else { + res.Success = false + res.Message = string(body) + } + } + context.JSON(http.StatusOK, &res) + } +} diff --git a/pkg/server/controller/op.go b/pkg/server/controller/op.go index ddbc0f2..43e1aff 100644 --- a/pkg/server/controller/op.go +++ b/pkg/server/controller/op.go @@ -54,6 +54,7 @@ func (c *HandleController) Register(rootDir string, engine *gin.Engine) { group.POST("/remove", c.MakeRemoveTokensFunc()) group.POST("/disable", c.MakeDisableTokensFunc()) group.POST("/enable", c.MakeEnableTokensFunc()) + group.GET("/proxy/*serverApi", c.MakeProxyFunc()) } func (c *HandleController) HandleLogin(content *plugin.LoginContent) plugin.Response {