From 0f6f674a648e248fd1d842bc24cca2034db148bf Mon Sep 17 00:00:00 2001 From: fatedier Date: Tue, 10 Apr 2018 17:46:49 +0800 Subject: [PATCH] cmd: support more cli command --- Makefile | 2 +- README.md | 4 +- README_zh.md | 4 +- client/admin.go | 4 +- client/admin_api.go | 25 +- client/control.go | 34 +- client/proxy.go | 13 +- client/proxy_manager.go | 13 +- client/service.go | 7 +- client/visitor.go | 7 +- cmd/frpc/main.go | 286 +------------ cmd/frpc/sub/http.go | 96 +++++ cmd/frpc/sub/https.go | 88 ++++ cmd/frpc/sub/reload.go | 92 +++++ cmd/frpc/sub/root.go | 200 +++++++++ cmd/frpc/sub/status.go | 146 +++++++ cmd/frpc/sub/stcp.go | 102 +++++ cmd/frpc/sub/tcp.go | 85 ++++ cmd/frpc/sub/udp.go | 85 ++++ cmd/frpc/sub/xtcp.go | 102 +++++ cmd/frps/main.go | 103 +---- cmd/frps/root.go | 174 ++++++++ conf/frpc_full.ini | 8 +- conf/frps_full.ini | 8 +- g/g.go | 32 ++ models/config/client_common.go | 143 +++---- models/config/proxy.go | 380 +++++++++--------- models/config/server_common.go | 185 ++++----- server/control.go | 19 +- server/dashboard.go | 4 +- server/dashboard_api.go | 3 +- server/metric.go | 18 +- server/proxy.go | 23 +- server/service.go | 12 +- tests/conf/auto_test_frpc.ini | 2 +- tests/conf/auto_test_frpc_visitor.ini | 2 +- tests/conf/auto_test_frps.ini | 2 +- utils/version/version.go | 2 +- .../github.com/fatedier/beego/controller.go | 4 +- .../fatedier/beego/controller_test.go | 4 +- .../fatedier/beego/logs/alils/signature.go | 1 - vendor/github.com/fatedier/beego/orm/db.go | 2 +- vendor/github.com/fatedier/beego/template.go | 16 +- .../fatedier/beego/toolbox/statistics.go | 2 +- .../klauspost/cpuid/private/cpuid.go | 264 ++++++------ .../stretchr/testify/assert/assertions.go | 4 +- .../testify/assert/assertions_test.go | 4 +- vendor/github.com/tjfoc/gmsm/sm4/sm4.go | 2 +- vendor/golang.org/x/crypto/ssh/kex.go | 8 +- 49 files changed, 1822 insertions(+), 1004 deletions(-) create mode 100644 cmd/frpc/sub/http.go create mode 100644 cmd/frpc/sub/https.go create mode 100644 cmd/frpc/sub/reload.go create mode 100644 cmd/frpc/sub/root.go create mode 100644 cmd/frpc/sub/status.go create mode 100644 cmd/frpc/sub/stcp.go create mode 100644 cmd/frpc/sub/tcp.go create mode 100644 cmd/frpc/sub/udp.go create mode 100644 cmd/frpc/sub/xtcp.go create mode 100644 cmd/frps/root.go create mode 100644 g/g.go diff --git a/Makefile b/Makefile index b91b334..263ab35 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,7 @@ ci: go test -v ./tests/... cd ./tests && ./clean_test.sh && cd - -ciclean: +cic: cd ./tests && ./clean_test.sh && cd - alltest: gotest ci diff --git a/README.md b/README.md index 458e0e6..2ecdd25 100644 --- a/README.md +++ b/README.md @@ -383,7 +383,7 @@ Then visit `http://[server_addr]:7500` to see dashboard, default username and pa ### Authentication -Since v0.10.0, you only need to set `privilege_token` in frps.ini and frpc.ini. +Since v0.10.0, you only need to set `token` in frps.ini and frpc.ini. Note that time duration between server of frpc and frps mustn't exceed 15 minutes because timestamp is used for authentication. @@ -539,7 +539,7 @@ type = http local_port = 80 custom_domains = test.yourdomain.com http_user = abc -http_pwd = abc +http_passwd = abc ``` Visit `http://test.yourdomain.com` and now you need to input username and password. diff --git a/README_zh.md b/README_zh.md index ebc11a3..76499c8 100644 --- a/README_zh.md +++ b/README_zh.md @@ -401,7 +401,7 @@ dashboard_pwd = admin ### 身份验证 -从 v0.10.0 版本开始,所有 proxy 配置全部放在客户端(也就是之前版本的特权模式),服务端和客户端的 common 配置中的 `privilege_token` 参数一致则身份验证通过。 +从 v0.10.0 版本开始,所有 proxy 配置全部放在客户端(也就是之前版本的特权模式),服务端和客户端的 common 配置中的 `token` 参数一致则身份验证通过。 需要注意的是 frpc 所在机器和 frps 所在机器的时间相差不能超过 15 分钟,因为时间戳会被用于加密验证中,防止报文被劫持后被其他人利用。 @@ -565,7 +565,7 @@ type = http local_port = 80 custom_domains = test.yourdomain.com http_user = abc -http_pwd = abc +http_passwd = abc ``` 通过浏览器访问 `http://test.yourdomain.com`,需要输入配置的用户名和密码才能访问。 diff --git a/client/admin.go b/client/admin.go index e34f44d..06a9f76 100644 --- a/client/admin.go +++ b/client/admin.go @@ -20,7 +20,7 @@ import ( "net/http" "time" - "github.com/fatedier/frp/models/config" + "github.com/fatedier/frp/g" frpNet "github.com/fatedier/frp/utils/net" "github.com/julienschmidt/httprouter" @@ -35,7 +35,7 @@ func (svr *Service) RunAdminServer(addr string, port int) (err error) { // url router router := httprouter.New() - user, passwd := config.ClientCommonCfg.AdminUser, config.ClientCommonCfg.AdminPwd + user, passwd := g.GlbClientCfg.AdminUser, g.GlbClientCfg.AdminPwd // api, see dashboard_api.go router.GET("/api/reload", frpNet.HttprouterBasicAuth(svr.apiReload, user, passwd)) diff --git a/client/admin_api.go b/client/admin_api.go index 1a94752..c9ce169 100644 --- a/client/admin_api.go +++ b/client/admin_api.go @@ -17,6 +17,7 @@ package client import ( "encoding/json" "fmt" + "io/ioutil" "net/http" "sort" "strings" @@ -24,6 +25,7 @@ import ( "github.com/julienschmidt/httprouter" ini "github.com/vaughan0/go-ini" + "github.com/fatedier/frp/g" "github.com/fatedier/frp/models/config" "github.com/fatedier/frp/utils/log" ) @@ -51,15 +53,16 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request, _ httprout log.Info("Http request: [/api/reload]") - conf, err := ini.LoadFile(config.ClientCommonCfg.ConfigFile) + b, err := ioutil.ReadFile(g.GlbClientCfg.CfgFile) if err != nil { res.Code = 1 res.Msg = err.Error() log.Error("reload frpc config file error: %v", err) return } + content := string(b) - newCommonCfg, err := config.LoadClientCommonConf(conf) + newCommonCfg, err := config.UnmarshalClientConfFromIni(nil, content) if err != nil { res.Code = 2 res.Msg = err.Error() @@ -67,7 +70,15 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request, _ httprout return } - pxyCfgs, visitorCfgs, err := config.LoadProxyConfFromFile(config.ClientCommonCfg.User, conf, newCommonCfg.Start) + conf, err := ini.LoadFile(g.GlbClientCfg.CfgFile) + if err != nil { + res.Code = 1 + res.Msg = err.Error() + log.Error("reload frpc config file error: %v", err) + return + } + + pxyCfgs, visitorCfgs, err := config.LoadProxyConfFromIni(g.GlbClientCfg.User, conf, newCommonCfg.Start) if err != nil { res.Code = 3 res.Msg = err.Error() @@ -125,18 +136,18 @@ func NewProxyStatusResp(status *ProxyStatus) ProxyStatusResp { } psr.Plugin = cfg.Plugin if status.Err != "" { - psr.RemoteAddr = fmt.Sprintf("%s:%d", config.ClientCommonCfg.ServerAddr, cfg.RemotePort) + psr.RemoteAddr = fmt.Sprintf("%s:%d", g.GlbClientCfg.ServerAddr, cfg.RemotePort) } else { - psr.RemoteAddr = config.ClientCommonCfg.ServerAddr + status.RemoteAddr + psr.RemoteAddr = g.GlbClientCfg.ServerAddr + status.RemoteAddr } case *config.UdpProxyConf: if cfg.LocalPort != 0 { psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIp, cfg.LocalPort) } if status.Err != "" { - psr.RemoteAddr = fmt.Sprintf("%s:%d", config.ClientCommonCfg.ServerAddr, cfg.RemotePort) + psr.RemoteAddr = fmt.Sprintf("%s:%d", g.GlbClientCfg.ServerAddr, cfg.RemotePort) } else { - psr.RemoteAddr = config.ClientCommonCfg.ServerAddr + status.RemoteAddr + psr.RemoteAddr = g.GlbClientCfg.ServerAddr + status.RemoteAddr } case *config.HttpProxyConf: if cfg.LocalPort != 0 { diff --git a/client/control.go b/client/control.go index 1b31ace..9342238 100644 --- a/client/control.go +++ b/client/control.go @@ -21,6 +21,9 @@ import ( "sync" "time" + "github.com/xtaci/smux" + + "github.com/fatedier/frp/g" "github.com/fatedier/frp/models/config" "github.com/fatedier/frp/models/msg" "github.com/fatedier/frp/utils/crypto" @@ -29,7 +32,6 @@ import ( "github.com/fatedier/frp/utils/shutdown" "github.com/fatedier/frp/utils/util" "github.com/fatedier/frp/utils/version" - "github.com/xtaci/smux" ) const ( @@ -82,8 +84,8 @@ func NewControl(svr *Service, pxyCfgs map[string]config.ProxyConf, visitorCfgs m loginMsg := &msg.Login{ Arch: runtime.GOARCH, Os: runtime.GOOS, - PoolCount: config.ClientCommonCfg.PoolCount, - User: config.ClientCommonCfg.User, + PoolCount: g.GlbClientCfg.PoolCount, + User: g.GlbClientCfg.User, Version: version.Full(), } ctl := &Control{ @@ -110,7 +112,7 @@ func (ctl *Control) Run() (err error) { // if login_fail_exit is true, just exit this program // otherwise sleep a while and continues relogin to server - if config.ClientCommonCfg.LoginFailExit { + if g.GlbClientCfg.LoginFailExit { return } else { time.Sleep(10 * time.Second) @@ -183,8 +185,8 @@ func (ctl *Control) login() (err error) { ctl.session.Close() } - conn, err := frpNet.ConnectServerByHttpProxy(config.ClientCommonCfg.HttpProxy, config.ClientCommonCfg.Protocol, - fmt.Sprintf("%s:%d", config.ClientCommonCfg.ServerAddr, config.ClientCommonCfg.ServerPort)) + conn, err := frpNet.ConnectServerByHttpProxy(g.GlbClientCfg.HttpProxy, g.GlbClientCfg.Protocol, + fmt.Sprintf("%s:%d", g.GlbClientCfg.ServerAddr, g.GlbClientCfg.ServerPort)) if err != nil { return err } @@ -195,7 +197,7 @@ func (ctl *Control) login() (err error) { } }() - if config.ClientCommonCfg.TcpMux { + if g.GlbClientCfg.TcpMux { session, errRet := smux.Client(conn, nil) if errRet != nil { return errRet @@ -210,7 +212,7 @@ func (ctl *Control) login() (err error) { } now := time.Now().Unix() - ctl.loginMsg.PrivilegeKey = util.GetAuthKey(config.ClientCommonCfg.PrivilegeToken, now) + ctl.loginMsg.PrivilegeKey = util.GetAuthKey(g.GlbClientCfg.Token, now) ctl.loginMsg.Timestamp = now ctl.loginMsg.RunId = ctl.runId @@ -234,7 +236,7 @@ func (ctl *Control) login() (err error) { ctl.conn = conn // update runId got from server ctl.runId = loginRespMsg.RunId - config.ClientCommonCfg.ServerUdpPort = loginRespMsg.ServerUdpPort + g.GlbClientCfg.ServerUdpPort = loginRespMsg.ServerUdpPort ctl.ClearLogPrefix() ctl.AddLogPrefix(loginRespMsg.RunId) ctl.Info("login to server success, get run id [%s], server udp port [%d]", loginRespMsg.RunId, loginRespMsg.ServerUdpPort) @@ -242,7 +244,7 @@ func (ctl *Control) login() (err error) { } func (ctl *Control) connectServer() (conn frpNet.Conn, err error) { - if config.ClientCommonCfg.TcpMux { + if g.GlbClientCfg.TcpMux { stream, errRet := ctl.session.OpenStream() if errRet != nil { err = errRet @@ -251,8 +253,8 @@ func (ctl *Control) connectServer() (conn frpNet.Conn, err error) { } conn = frpNet.WrapConn(stream) } else { - conn, err = frpNet.ConnectServerByHttpProxy(config.ClientCommonCfg.HttpProxy, config.ClientCommonCfg.Protocol, - fmt.Sprintf("%s:%d", config.ClientCommonCfg.ServerAddr, config.ClientCommonCfg.ServerPort)) + conn, err = frpNet.ConnectServerByHttpProxy(g.GlbClientCfg.HttpProxy, g.GlbClientCfg.Protocol, + fmt.Sprintf("%s:%d", g.GlbClientCfg.ServerAddr, g.GlbClientCfg.ServerPort)) if err != nil { ctl.Warn("start new connection to server error: %v", err) return @@ -271,7 +273,7 @@ func (ctl *Control) reader() { defer ctl.readerShutdown.Done() defer close(ctl.closedCh) - encReader := crypto.NewReader(ctl.conn, []byte(config.ClientCommonCfg.PrivilegeToken)) + encReader := crypto.NewReader(ctl.conn, []byte(g.GlbClientCfg.Token)) for { if m, err := msg.ReadMsg(encReader); err != nil { if err == io.EOF { @@ -290,7 +292,7 @@ func (ctl *Control) reader() { // writer writes messages got from sendCh to frps func (ctl *Control) writer() { defer ctl.writerShutdown.Done() - encWriter, err := crypto.NewWriter(ctl.conn, []byte(config.ClientCommonCfg.PrivilegeToken)) + encWriter, err := crypto.NewWriter(ctl.conn, []byte(g.GlbClientCfg.Token)) if err != nil { ctl.conn.Error("crypto new writer error: %v", err) ctl.conn.Close() @@ -318,7 +320,7 @@ func (ctl *Control) msgHandler() { }() defer ctl.msgHandlerShutdown.Done() - hbSend := time.NewTicker(time.Duration(config.ClientCommonCfg.HeartBeatInterval) * time.Second) + hbSend := time.NewTicker(time.Duration(g.GlbClientCfg.HeartBeatInterval) * time.Second) defer hbSend.Stop() hbCheck := time.NewTicker(time.Second) defer hbCheck.Stop() @@ -332,7 +334,7 @@ func (ctl *Control) msgHandler() { ctl.Debug("send heartbeat to server") ctl.sendCh <- &msg.Ping{} case <-hbCheck.C: - if time.Since(ctl.lastPong) > time.Duration(config.ClientCommonCfg.HeartBeatTimeout)*time.Second { + if time.Since(ctl.lastPong) > time.Duration(g.GlbClientCfg.HeartBeatTimeout)*time.Second { ctl.Warn("heartbeat timeout") // let reader() stop ctl.conn.Close() diff --git a/client/proxy.go b/client/proxy.go index f68d9fb..8342bc7 100644 --- a/client/proxy.go +++ b/client/proxy.go @@ -22,6 +22,7 @@ import ( "sync" "time" + "github.com/fatedier/frp/g" "github.com/fatedier/frp/models/config" "github.com/fatedier/frp/models/msg" "github.com/fatedier/frp/models/plugin" @@ -46,7 +47,7 @@ type Proxy interface { func NewProxy(pxyConf config.ProxyConf) (pxy Proxy) { baseProxy := BaseProxy{ - Logger: log.NewPrefixLogger(pxyConf.GetName()), + Logger: log.NewPrefixLogger(pxyConf.GetBaseInfo().ProxyName), } switch cfg := pxyConf.(type) { case *config.TcpProxyConf: @@ -115,7 +116,7 @@ func (pxy *TcpProxy) Close() { func (pxy *TcpProxy) InWorkConn(conn frpNet.Conn) { HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, pxy.proxyPlugin, &pxy.cfg.BaseProxyConf, conn, - []byte(config.ClientCommonCfg.PrivilegeToken)) + []byte(g.GlbClientCfg.Token)) } // HTTP @@ -144,7 +145,7 @@ func (pxy *HttpProxy) Close() { func (pxy *HttpProxy) InWorkConn(conn frpNet.Conn) { HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, pxy.proxyPlugin, &pxy.cfg.BaseProxyConf, conn, - []byte(config.ClientCommonCfg.PrivilegeToken)) + []byte(g.GlbClientCfg.Token)) } // HTTPS @@ -173,7 +174,7 @@ func (pxy *HttpsProxy) Close() { func (pxy *HttpsProxy) InWorkConn(conn frpNet.Conn) { HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, pxy.proxyPlugin, &pxy.cfg.BaseProxyConf, conn, - []byte(config.ClientCommonCfg.PrivilegeToken)) + []byte(g.GlbClientCfg.Token)) } // STCP @@ -202,7 +203,7 @@ func (pxy *StcpProxy) Close() { func (pxy *StcpProxy) InWorkConn(conn frpNet.Conn) { HandleTcpWorkConnection(&pxy.cfg.LocalSvrConf, pxy.proxyPlugin, &pxy.cfg.BaseProxyConf, conn, - []byte(config.ClientCommonCfg.PrivilegeToken)) + []byte(g.GlbClientCfg.Token)) } // XTCP @@ -243,7 +244,7 @@ func (pxy *XtcpProxy) InWorkConn(conn frpNet.Conn) { Sid: natHoleSidMsg.Sid, } raddr, _ := net.ResolveUDPAddr("udp", - fmt.Sprintf("%s:%d", config.ClientCommonCfg.ServerAddr, config.ClientCommonCfg.ServerUdpPort)) + fmt.Sprintf("%s:%d", g.GlbClientCfg.ServerAddr, g.GlbClientCfg.ServerUdpPort)) clientConn, err := net.DialUDP("udp", nil, raddr) defer clientConn.Close() diff --git a/client/proxy_manager.go b/client/proxy_manager.go index 9d81ee7..b8cd64d 100644 --- a/client/proxy_manager.go +++ b/client/proxy_manager.go @@ -62,8 +62,8 @@ type ProxyStatus struct { func NewProxyWrapper(cfg config.ProxyConf) *ProxyWrapper { return &ProxyWrapper{ - Name: cfg.GetName(), - Type: cfg.GetType(), + Name: cfg.GetBaseInfo().ProxyName, + Type: cfg.GetBaseInfo().ProxyType, Status: ProxyStatusNew, Cfg: cfg, pxy: nil, @@ -227,7 +227,7 @@ func (pm *ProxyManager) CheckAndStartProxy(pxyStatus []string) { for _, s := range pxyStatus { if status == s { var newProxyMsg msg.NewProxy - pxy.Cfg.UnMarshalToMsg(&newProxyMsg) + pxy.Cfg.MarshalToMsg(&newProxyMsg) err := pm.sendMsg(&newProxyMsg) if err != nil { pm.Warn("[%s] proxy send NewProxy message error") @@ -240,15 +240,16 @@ func (pm *ProxyManager) CheckAndStartProxy(pxyStatus []string) { } for _, cfg := range pm.visitorCfgs { - if _, exist := pm.visitors[cfg.GetName()]; !exist { - pm.Info("try to start visitor [%s]", cfg.GetName()) + name := cfg.GetBaseInfo().ProxyName + if _, exist := pm.visitors[name]; !exist { + pm.Info("try to start visitor [%s]", name) visitor := NewVisitor(pm.ctl, cfg) err := visitor.Run() if err != nil { visitor.Warn("start error: %v", err) continue } - pm.visitors[cfg.GetName()] = visitor + pm.visitors[name] = visitor visitor.Info("start visitor success") } } diff --git a/client/service.go b/client/service.go index c5a2f1e..5fbf33c 100644 --- a/client/service.go +++ b/client/service.go @@ -15,6 +15,7 @@ package client import ( + "github.com/fatedier/frp/g" "github.com/fatedier/frp/models/config" "github.com/fatedier/frp/utils/log" ) @@ -41,12 +42,12 @@ func (svr *Service) Run() error { return err } - if config.ClientCommonCfg.AdminPort != 0 { - err = svr.RunAdminServer(config.ClientCommonCfg.AdminAddr, config.ClientCommonCfg.AdminPort) + if g.GlbClientCfg.AdminPort != 0 { + err = svr.RunAdminServer(g.GlbClientCfg.AdminAddr, g.GlbClientCfg.AdminPort) if err != nil { log.Warn("run admin server error: %v", err) } - log.Info("admin server listen on %s:%d", config.ClientCommonCfg.AdminAddr, config.ClientCommonCfg.AdminPort) + log.Info("admin server listen on %s:%d", g.GlbClientCfg.AdminAddr, g.GlbClientCfg.AdminPort) } <-svr.closedCh diff --git a/client/visitor.go b/client/visitor.go index fd18225..9c16c1d 100644 --- a/client/visitor.go +++ b/client/visitor.go @@ -26,6 +26,7 @@ import ( "golang.org/x/net/ipv4" + "github.com/fatedier/frp/g" "github.com/fatedier/frp/models/config" "github.com/fatedier/frp/models/msg" frpIo "github.com/fatedier/frp/utils/io" @@ -45,7 +46,7 @@ type Visitor interface { func NewVisitor(ctl *Control, pxyConf config.ProxyConf) (visitor Visitor) { baseVisitor := BaseVisitor{ ctl: ctl, - Logger: log.NewPrefixLogger(pxyConf.GetName()), + Logger: log.NewPrefixLogger(pxyConf.GetBaseInfo().ProxyName), } switch cfg := pxyConf.(type) { case *config.StcpProxyConf: @@ -193,13 +194,13 @@ func (sv *XtcpVisitor) handleConn(userConn frpNet.Conn) { defer userConn.Close() sv.Debug("get a new xtcp user connection") - if config.ClientCommonCfg.ServerUdpPort == 0 { + if g.GlbClientCfg.ServerUdpPort == 0 { sv.Error("xtcp is not supported by server") return } raddr, err := net.ResolveUDPAddr("udp", - fmt.Sprintf("%s:%d", config.ClientCommonCfg.ServerAddr, config.ClientCommonCfg.ServerUdpPort)) + fmt.Sprintf("%s:%d", g.GlbClientCfg.ServerAddr, g.GlbClientCfg.ServerUdpPort)) visitorConn, err := net.DialUDP("udp", nil, raddr) defer visitorConn.Close() diff --git a/cmd/frpc/main.go b/cmd/frpc/main.go index 845f4f7..1c6344b 100644 --- a/cmd/frpc/main.go +++ b/cmd/frpc/main.go @@ -15,291 +15,9 @@ package main import ( - "encoding/base64" - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "os" - "os/signal" - "strconv" - "strings" - "syscall" - "time" - - docopt "github.com/docopt/docopt-go" - "github.com/rodaine/table" - ini "github.com/vaughan0/go-ini" - - "github.com/fatedier/frp/client" - "github.com/fatedier/frp/models/config" - "github.com/fatedier/frp/utils/log" - "github.com/fatedier/frp/utils/version" + "github.com/fatedier/frp/cmd/frpc/sub" ) -var ( - configFile string = "./frpc.ini" -) - -var usage string = `frpc is the client of frp - -Usage: - frpc [-c config_file] [-L log_file] [--log-level=] [--server-addr=] - frpc reload [-c config_file] - frpc status [-c config_file] - frpc -h | --help - frpc -v | --version - -Options: - -c config_file set config file - -L log_file set output log file, including console - --log-level= set log level: debug, info, warn, error - --server-addr= addr which frps is listening for, example: 0.0.0.0:7000 - -h --help show this screen - -v --version show version -` - func main() { - var err error - confFile := "./frpc.ini" - // the configures parsed from file will be replaced by those from command line if exist - args, err := docopt.Parse(usage, nil, true, version.Full(), false) - - if args["-c"] != nil { - confFile = args["-c"].(string) - } - - conf, err := ini.LoadFile(confFile) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - - config.ClientCommonCfg, err = config.LoadClientCommonConf(conf) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - config.ClientCommonCfg.ConfigFile = confFile - - // check if reload command - if args["reload"] != nil { - if args["reload"].(bool) { - if err = CmdReload(); err != nil { - fmt.Printf("frpc reload error: %v\n", err) - os.Exit(1) - } else { - fmt.Printf("reload success\n") - os.Exit(0) - } - } - } - - // check if status command - if args["status"] != nil { - if args["status"].(bool) { - if err = CmdStatus(); err != nil { - fmt.Printf("frpc get status error: %v\n", err) - os.Exit(1) - } else { - os.Exit(0) - } - } - } - - if args["-L"] != nil { - if args["-L"].(string) == "console" { - config.ClientCommonCfg.LogWay = "console" - } else { - config.ClientCommonCfg.LogWay = "file" - config.ClientCommonCfg.LogFile = args["-L"].(string) - } - } - - if args["--log-level"] != nil { - config.ClientCommonCfg.LogLevel = args["--log-level"].(string) - } - - if args["--server-addr"] != nil { - addr := strings.Split(args["--server-addr"].(string), ":") - if len(addr) != 2 { - fmt.Println("--server-addr format error: example 0.0.0.0:7000") - os.Exit(1) - } - serverPort, err := strconv.ParseInt(addr[1], 10, 64) - if err != nil { - fmt.Println("--server-addr format error, example 0.0.0.0:7000") - os.Exit(1) - } - config.ClientCommonCfg.ServerAddr = addr[0] - config.ClientCommonCfg.ServerPort = int(serverPort) - } - - if args["-v"] != nil { - if args["-v"].(bool) { - fmt.Println(version.Full()) - os.Exit(0) - } - } - - pxyCfgs, visitorCfgs, err := config.LoadProxyConfFromFile(config.ClientCommonCfg.User, conf, config.ClientCommonCfg.Start) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - - log.InitLog(config.ClientCommonCfg.LogWay, config.ClientCommonCfg.LogFile, - config.ClientCommonCfg.LogLevel, config.ClientCommonCfg.LogMaxDays) - - svr := client.NewService(pxyCfgs, visitorCfgs) - - // Capture the exit signal if we use kcp. - if config.ClientCommonCfg.Protocol == "kcp" { - go HandleSignal(svr) - } - - err = svr.Run() - if err != nil { - fmt.Println(err) - os.Exit(1) - } -} - -func HandleSignal(svr *client.Service) { - ch := make(chan os.Signal) - signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM) - <-ch - svr.Close() - time.Sleep(250 * time.Millisecond) - os.Exit(0) -} - -func CmdReload() error { - if config.ClientCommonCfg.AdminPort == 0 { - return fmt.Errorf("admin_port shoud be set if you want to use reload feature") - } - - req, err := http.NewRequest("GET", "http://"+ - config.ClientCommonCfg.AdminAddr+":"+fmt.Sprintf("%d", config.ClientCommonCfg.AdminPort)+"/api/reload", nil) - if err != nil { - return err - } - - authStr := "Basic " + base64.StdEncoding.EncodeToString([]byte(config.ClientCommonCfg.AdminUser+":"+ - config.ClientCommonCfg.AdminPwd)) - - req.Header.Add("Authorization", authStr) - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } else { - if resp.StatusCode != 200 { - return fmt.Errorf("admin api status code [%d]", resp.StatusCode) - } - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return err - } - res := &client.GeneralResponse{} - err = json.Unmarshal(body, &res) - if err != nil { - return fmt.Errorf("unmarshal http response error: %s", strings.TrimSpace(string(body))) - } else if res.Code != 0 { - return fmt.Errorf(res.Msg) - } - } - return nil -} - -func CmdStatus() error { - if config.ClientCommonCfg.AdminPort == 0 { - return fmt.Errorf("admin_port shoud be set if you want to get proxy status") - } - - req, err := http.NewRequest("GET", "http://"+ - config.ClientCommonCfg.AdminAddr+":"+fmt.Sprintf("%d", config.ClientCommonCfg.AdminPort)+"/api/status", nil) - if err != nil { - return err - } - - authStr := "Basic " + base64.StdEncoding.EncodeToString([]byte(config.ClientCommonCfg.AdminUser+":"+ - config.ClientCommonCfg.AdminPwd)) - - req.Header.Add("Authorization", authStr) - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } else { - if resp.StatusCode != 200 { - return fmt.Errorf("admin api status code [%d]", resp.StatusCode) - } - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return err - } - res := &client.StatusResp{} - err = json.Unmarshal(body, &res) - if err != nil { - return fmt.Errorf("unmarshal http response error: %s", strings.TrimSpace(string(body))) - } - - fmt.Println("Proxy Status...") - if len(res.Tcp) > 0 { - fmt.Printf("TCP") - tbl := table.New("Name", "Status", "LocalAddr", "Plugin", "RemoteAddr", "Error") - for _, ps := range res.Tcp { - tbl.AddRow(ps.Name, ps.Status, ps.LocalAddr, ps.Plugin, ps.RemoteAddr, ps.Err) - } - tbl.Print() - fmt.Println("") - } - if len(res.Udp) > 0 { - fmt.Printf("UDP") - tbl := table.New("Name", "Status", "LocalAddr", "Plugin", "RemoteAddr", "Error") - for _, ps := range res.Udp { - tbl.AddRow(ps.Name, ps.Status, ps.LocalAddr, ps.Plugin, ps.RemoteAddr, ps.Err) - } - tbl.Print() - fmt.Println("") - } - if len(res.Http) > 0 { - fmt.Printf("HTTP") - tbl := table.New("Name", "Status", "LocalAddr", "Plugin", "RemoteAddr", "Error") - for _, ps := range res.Http { - tbl.AddRow(ps.Name, ps.Status, ps.LocalAddr, ps.Plugin, ps.RemoteAddr, ps.Err) - } - tbl.Print() - fmt.Println("") - } - if len(res.Https) > 0 { - fmt.Printf("HTTPS") - tbl := table.New("Name", "Status", "LocalAddr", "Plugin", "RemoteAddr", "Error") - for _, ps := range res.Https { - tbl.AddRow(ps.Name, ps.Status, ps.LocalAddr, ps.Plugin, ps.RemoteAddr, ps.Err) - } - tbl.Print() - fmt.Println("") - } - if len(res.Stcp) > 0 { - fmt.Printf("STCP") - tbl := table.New("Name", "Status", "LocalAddr", "Plugin", "RemoteAddr", "Error") - for _, ps := range res.Stcp { - tbl.AddRow(ps.Name, ps.Status, ps.LocalAddr, ps.Plugin, ps.RemoteAddr, ps.Err) - } - tbl.Print() - fmt.Println("") - } - if len(res.Xtcp) > 0 { - fmt.Printf("XTCP") - tbl := table.New("Name", "Status", "LocalAddr", "Plugin", "RemoteAddr", "Error") - for _, ps := range res.Xtcp { - tbl.AddRow(ps.Name, ps.Status, ps.LocalAddr, ps.Plugin, ps.RemoteAddr, ps.Err) - } - tbl.Print() - fmt.Println("") - } - } - return nil + sub.Execute() } diff --git a/cmd/frpc/sub/http.go b/cmd/frpc/sub/http.go new file mode 100644 index 0000000..3f79972 --- /dev/null +++ b/cmd/frpc/sub/http.go @@ -0,0 +1,96 @@ +// Copyright 2018 fatedier, fatedier@gmail.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sub + +import ( + "fmt" + "os" + "strings" + + "github.com/spf13/cobra" + + "github.com/fatedier/frp/models/config" + "github.com/fatedier/frp/models/consts" +) + +func init() { + httpCmd.PersistentFlags().StringVarP(&serverAddr, "server_addr", "s", "127.0.0.1:7000", "frp server's address") + httpCmd.PersistentFlags().StringVarP(&user, "user", "u", "", "user") + httpCmd.PersistentFlags().StringVarP(&protocol, "protocol", "p", "tcp", "tcp or kcp") + httpCmd.PersistentFlags().StringVarP(&token, "token", "t", "", "auth token") + httpCmd.PersistentFlags().StringVarP(&logLevel, "log_level", "", "info", "log level") + httpCmd.PersistentFlags().StringVarP(&logFile, "log_file", "", "console", "console or file path") + httpCmd.PersistentFlags().IntVarP(&logMaxDays, "log_max_days", "", 3, "log file reversed days") + + httpCmd.PersistentFlags().StringVarP(&proxyName, "proxy_name", "n", "", "proxy name") + httpCmd.PersistentFlags().StringVarP(&localIp, "local_ip", "i", "127.0.0.1", "local ip") + httpCmd.PersistentFlags().IntVarP(&localPort, "local_port", "l", 0, "local port") + httpCmd.PersistentFlags().StringVarP(&customDomains, "custom_domain", "d", "", "custom domain") + httpCmd.PersistentFlags().StringVarP(&subDomain, "sd", "", "", "sub domain") + httpCmd.PersistentFlags().StringVarP(&locations, "locations", "", "", "locations") + httpCmd.PersistentFlags().StringVarP(&httpUser, "http_user", "", "admin", "http auth user") + httpCmd.PersistentFlags().StringVarP(&httpPwd, "http_pwd", "", "admin", "http auth password") + httpCmd.PersistentFlags().StringVarP(&hostHeaderRewrite, "host_header_rewrite", "", "", "host header rewrite") + httpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption") + httpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression") + + rootCmd.AddCommand(httpCmd) +} + +var httpCmd = &cobra.Command{ + Use: "http", + Short: "Run frpc with a single http proxy", + RunE: func(cmd *cobra.Command, args []string) error { + err := parseClientCommonCfg(CfgFileTypeCmd, "") + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + cfg := &config.HttpProxyConf{} + var prefix string + if user != "" { + prefix = user + "." + } + cfg.ProxyName = prefix + proxyName + cfg.ProxyType = consts.HttpProxy + cfg.LocalIp = localIp + cfg.LocalPort = localPort + cfg.CustomDomains = strings.Split(customDomains, ",") + cfg.SubDomain = subDomain + cfg.Locations = strings.Split(locations, ",") + cfg.HttpUser = httpUser + cfg.HttpPwd = httpPwd + cfg.HostHeaderRewrite = hostHeaderRewrite + cfg.UseEncryption = useEncryption + cfg.UseCompression = useCompression + + err = cfg.CheckForCli() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + proxyConfs := map[string]config.ProxyConf{ + cfg.ProxyName: cfg, + } + err = startService(proxyConfs, nil) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + return nil + }, +} diff --git a/cmd/frpc/sub/https.go b/cmd/frpc/sub/https.go new file mode 100644 index 0000000..5c0b0e7 --- /dev/null +++ b/cmd/frpc/sub/https.go @@ -0,0 +1,88 @@ +// Copyright 2018 fatedier, fatedier@gmail.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sub + +import ( + "fmt" + "os" + "strings" + + "github.com/spf13/cobra" + + "github.com/fatedier/frp/models/config" + "github.com/fatedier/frp/models/consts" +) + +func init() { + httpsCmd.PersistentFlags().StringVarP(&serverAddr, "server_addr", "s", "127.0.0.1:7000", "frp server's address") + httpsCmd.PersistentFlags().StringVarP(&user, "user", "u", "", "user") + httpsCmd.PersistentFlags().StringVarP(&protocol, "protocol", "p", "tcp", "tcp or kcp") + httpsCmd.PersistentFlags().StringVarP(&token, "token", "t", "", "auth token") + httpsCmd.PersistentFlags().StringVarP(&logLevel, "log_level", "", "info", "log level") + httpsCmd.PersistentFlags().StringVarP(&logFile, "log_file", "", "console", "console or file path") + httpsCmd.PersistentFlags().IntVarP(&logMaxDays, "log_max_days", "", 3, "log file reversed days") + + httpsCmd.PersistentFlags().StringVarP(&proxyName, "proxy_name", "n", "", "proxy name") + httpsCmd.PersistentFlags().StringVarP(&localIp, "local_ip", "i", "127.0.0.1", "local ip") + httpsCmd.PersistentFlags().IntVarP(&localPort, "local_port", "l", 0, "local port") + httpsCmd.PersistentFlags().StringVarP(&customDomains, "custom_domain", "d", "", "custom domain") + httpsCmd.PersistentFlags().StringVarP(&subDomain, "sd", "", "", "sub domain") + httpsCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption") + httpsCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression") + + rootCmd.AddCommand(httpsCmd) +} + +var httpsCmd = &cobra.Command{ + Use: "https", + Short: "Run frpc with a single https proxy", + RunE: func(cmd *cobra.Command, args []string) error { + err := parseClientCommonCfg(CfgFileTypeCmd, "") + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + cfg := &config.HttpsProxyConf{} + var prefix string + if user != "" { + prefix = user + "." + } + cfg.ProxyName = prefix + proxyName + cfg.ProxyType = consts.HttpsProxy + cfg.LocalIp = localIp + cfg.LocalPort = localPort + cfg.CustomDomains = strings.Split(customDomains, ",") + cfg.SubDomain = subDomain + cfg.UseEncryption = useEncryption + cfg.UseCompression = useCompression + + err = cfg.CheckForCli() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + proxyConfs := map[string]config.ProxyConf{ + cfg.ProxyName: cfg, + } + err = startService(proxyConfs, nil) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + return nil + }, +} diff --git a/cmd/frpc/sub/reload.go b/cmd/frpc/sub/reload.go new file mode 100644 index 0000000..1e6f2c4 --- /dev/null +++ b/cmd/frpc/sub/reload.go @@ -0,0 +1,92 @@ +// Copyright 2018 fatedier, fatedier@gmail.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sub + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "os" + "strings" + + "github.com/spf13/cobra" + + "github.com/fatedier/frp/client" + "github.com/fatedier/frp/g" +) + +func init() { + rootCmd.AddCommand(reloadCmd) +} + +var reloadCmd = &cobra.Command{ + Use: "reload", + Short: "Hot-Reload frpc configuration", + RunE: func(cmd *cobra.Command, args []string) error { + err := parseClientCommonCfg(CfgFileTypeIni, cfgFile) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + err = reload() + if err != nil { + fmt.Printf("frpc reload error: %v\n", err) + os.Exit(1) + } + fmt.Printf("reload success\n") + return nil + }, +} + +func reload() error { + if g.GlbClientCfg.AdminPort == 0 { + return fmt.Errorf("admin_port shoud be set if you want to use reload feature") + } + + req, err := http.NewRequest("GET", "http://"+ + g.GlbClientCfg.AdminAddr+":"+fmt.Sprintf("%d", g.GlbClientCfg.AdminPort)+"/api/reload", nil) + if err != nil { + return err + } + + authStr := "Basic " + base64.StdEncoding.EncodeToString([]byte(g.GlbClientCfg.AdminUser+":"+ + g.GlbClientCfg.AdminPwd)) + + req.Header.Add("Authorization", authStr) + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } else { + if resp.StatusCode != 200 { + return fmt.Errorf("admin api status code [%d]", resp.StatusCode) + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return err + } + res := &client.GeneralResponse{} + err = json.Unmarshal(body, &res) + if err != nil { + return fmt.Errorf("unmarshal http response error: %s", strings.TrimSpace(string(body))) + } else if res.Code != 0 { + return fmt.Errorf(res.Msg) + } + } + return nil +} diff --git a/cmd/frpc/sub/root.go b/cmd/frpc/sub/root.go new file mode 100644 index 0000000..bbb4c96 --- /dev/null +++ b/cmd/frpc/sub/root.go @@ -0,0 +1,200 @@ +// Copyright 2018 fatedier, fatedier@gmail.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sub + +import ( + "fmt" + "io/ioutil" + "os" + "os/signal" + "strconv" + "strings" + "syscall" + "time" + + "github.com/spf13/cobra" + ini "github.com/vaughan0/go-ini" + + "github.com/fatedier/frp/client" + "github.com/fatedier/frp/g" + "github.com/fatedier/frp/models/config" + "github.com/fatedier/frp/utils/log" + "github.com/fatedier/frp/utils/version" +) + +const ( + CfgFileTypeIni = iota + CfgFileTypeCmd +) + +var ( + cfgFile string + showVersion bool + + serverAddr string + user string + protocol string + token string + logLevel string + logFile string + logMaxDays int + + proxyName string + localIp string + localPort int + remotePort int + useEncryption bool + useCompression bool + customDomains string + subDomain string + httpUser string + httpPwd string + locations string + hostHeaderRewrite string + role string + sk string + serverName string + bindAddr string +) + +func init() { + rootCmd.PersistentFlags().StringVarP(&cfgFile, "", "c", "./frpc.ini", "config file of frpc") + rootCmd.PersistentFlags().BoolVarP(&showVersion, "version", "v", false, "version of frpc") +} + +var rootCmd = &cobra.Command{ + Use: "frpc", + Short: "frpc is the client of frp (https://github.com/fatedier/frp)", + RunE: func(cmd *cobra.Command, args []string) error { + if showVersion { + fmt.Println(version.Full()) + return nil + } + + // Do not show command usage here. + err := runClient(cfgFile) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + return nil + }, +} + +func Execute() { + if err := rootCmd.Execute(); err != nil { + os.Exit(1) + } +} + +func handleSignal(svr *client.Service) { + ch := make(chan os.Signal) + signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM) + <-ch + svr.Close() + time.Sleep(250 * time.Millisecond) + os.Exit(0) +} + +func parseClientCommonCfg(fileType int, filePath string) (err error) { + if fileType == CfgFileTypeIni { + err = parseClientCommonCfgFromIni(filePath) + } else if fileType == CfgFileTypeCmd { + err = parseClientCommonCfgFromCmd() + } + if err != nil { + return + } + + g.GlbClientCfg.CfgFile = cfgFile + + err = g.GlbClientCfg.ClientCommonConf.Check() + if err != nil { + return + } + return +} + +func parseClientCommonCfgFromIni(filePath string) (err error) { + b, err := ioutil.ReadFile(filePath) + if err != nil { + return err + } + content := string(b) + + cfg, err := config.UnmarshalClientConfFromIni(&g.GlbClientCfg.ClientCommonConf, content) + if err != nil { + return err + } + g.GlbClientCfg.ClientCommonConf = *cfg + return +} + +func parseClientCommonCfgFromCmd() (err error) { + strs := strings.Split(serverAddr, ":") + if len(strs) < 2 { + err = fmt.Errorf("invalid server_addr") + return + } + if strs[0] != "" { + g.GlbClientCfg.ServerAddr = strs[0] + } + g.GlbClientCfg.ServerPort, err = strconv.Atoi(strs[1]) + if err != nil { + err = fmt.Errorf("invalid server_addr") + return + } + + g.GlbClientCfg.User = user + g.GlbClientCfg.Protocol = protocol + g.GlbClientCfg.Token = token + g.GlbClientCfg.LogLevel = logLevel + g.GlbClientCfg.LogFile = logFile + g.GlbClientCfg.LogMaxDays = int64(logMaxDays) + return nil +} + +func runClient(cfgFilePath string) (err error) { + err = parseClientCommonCfg(CfgFileTypeIni, cfgFilePath) + if err != nil { + return + } + + conf, err := ini.LoadFile(cfgFilePath) + if err != nil { + return err + } + + pxyCfgs, visitorCfgs, err := config.LoadProxyConfFromIni(g.GlbClientCfg.User, conf, g.GlbClientCfg.Start) + if err != nil { + return err + } + + err = startService(pxyCfgs, visitorCfgs) + return +} + +func startService(pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]config.ProxyConf) (err error) { + log.InitLog(g.GlbClientCfg.LogWay, g.GlbClientCfg.LogFile, g.GlbClientCfg.LogLevel, g.GlbClientCfg.LogMaxDays) + svr := client.NewService(pxyCfgs, visitorCfgs) + + // Capture the exit signal if we use kcp. + if g.GlbClientCfg.Protocol == "kcp" { + go handleSignal(svr) + } + + err = svr.Run() + return +} diff --git a/cmd/frpc/sub/status.go b/cmd/frpc/sub/status.go new file mode 100644 index 0000000..3a25a4b --- /dev/null +++ b/cmd/frpc/sub/status.go @@ -0,0 +1,146 @@ +// Copyright 2018 fatedier, fatedier@gmail.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sub + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "os" + "strings" + + "github.com/rodaine/table" + "github.com/spf13/cobra" + + "github.com/fatedier/frp/client" + "github.com/fatedier/frp/g" +) + +func init() { + rootCmd.AddCommand(statusCmd) +} + +var statusCmd = &cobra.Command{ + Use: "status", + Short: "Overview of all proxies status", + RunE: func(cmd *cobra.Command, args []string) error { + err := parseClientCommonCfg(CfgFileTypeIni, cfgFile) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + err = status() + if err != nil { + fmt.Printf("frpc get status error: %v\n", err) + os.Exit(1) + } + return nil + }, +} + +func status() error { + if g.GlbClientCfg.AdminPort == 0 { + return fmt.Errorf("admin_port shoud be set if you want to get proxy status") + } + + req, err := http.NewRequest("GET", "http://"+ + g.GlbClientCfg.AdminAddr+":"+fmt.Sprintf("%d", g.GlbClientCfg.AdminPort)+"/api/status", nil) + if err != nil { + return err + } + + authStr := "Basic " + base64.StdEncoding.EncodeToString([]byte(g.GlbClientCfg.AdminUser+":"+ + g.GlbClientCfg.AdminPwd)) + + req.Header.Add("Authorization", authStr) + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } else { + if resp.StatusCode != 200 { + return fmt.Errorf("admin api status code [%d]", resp.StatusCode) + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return err + } + res := &client.StatusResp{} + err = json.Unmarshal(body, &res) + if err != nil { + return fmt.Errorf("unmarshal http response error: %s", strings.TrimSpace(string(body))) + } + + fmt.Println("Proxy Status...") + if len(res.Tcp) > 0 { + fmt.Printf("TCP") + tbl := table.New("Name", "Status", "LocalAddr", "Plugin", "RemoteAddr", "Error") + for _, ps := range res.Tcp { + tbl.AddRow(ps.Name, ps.Status, ps.LocalAddr, ps.Plugin, ps.RemoteAddr, ps.Err) + } + tbl.Print() + fmt.Println("") + } + if len(res.Udp) > 0 { + fmt.Printf("UDP") + tbl := table.New("Name", "Status", "LocalAddr", "Plugin", "RemoteAddr", "Error") + for _, ps := range res.Udp { + tbl.AddRow(ps.Name, ps.Status, ps.LocalAddr, ps.Plugin, ps.RemoteAddr, ps.Err) + } + tbl.Print() + fmt.Println("") + } + if len(res.Http) > 0 { + fmt.Printf("HTTP") + tbl := table.New("Name", "Status", "LocalAddr", "Plugin", "RemoteAddr", "Error") + for _, ps := range res.Http { + tbl.AddRow(ps.Name, ps.Status, ps.LocalAddr, ps.Plugin, ps.RemoteAddr, ps.Err) + } + tbl.Print() + fmt.Println("") + } + if len(res.Https) > 0 { + fmt.Printf("HTTPS") + tbl := table.New("Name", "Status", "LocalAddr", "Plugin", "RemoteAddr", "Error") + for _, ps := range res.Https { + tbl.AddRow(ps.Name, ps.Status, ps.LocalAddr, ps.Plugin, ps.RemoteAddr, ps.Err) + } + tbl.Print() + fmt.Println("") + } + if len(res.Stcp) > 0 { + fmt.Printf("STCP") + tbl := table.New("Name", "Status", "LocalAddr", "Plugin", "RemoteAddr", "Error") + for _, ps := range res.Stcp { + tbl.AddRow(ps.Name, ps.Status, ps.LocalAddr, ps.Plugin, ps.RemoteAddr, ps.Err) + } + tbl.Print() + fmt.Println("") + } + if len(res.Xtcp) > 0 { + fmt.Printf("XTCP") + tbl := table.New("Name", "Status", "LocalAddr", "Plugin", "RemoteAddr", "Error") + for _, ps := range res.Xtcp { + tbl.AddRow(ps.Name, ps.Status, ps.LocalAddr, ps.Plugin, ps.RemoteAddr, ps.Err) + } + tbl.Print() + fmt.Println("") + } + } + return nil +} diff --git a/cmd/frpc/sub/stcp.go b/cmd/frpc/sub/stcp.go new file mode 100644 index 0000000..66585ad --- /dev/null +++ b/cmd/frpc/sub/stcp.go @@ -0,0 +1,102 @@ +// Copyright 2018 fatedier, fatedier@gmail.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sub + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" + + "github.com/fatedier/frp/models/config" + "github.com/fatedier/frp/models/consts" +) + +func init() { + stcpCmd.PersistentFlags().StringVarP(&serverAddr, "server_addr", "s", "127.0.0.1:7000", "frp server's address") + stcpCmd.PersistentFlags().StringVarP(&user, "user", "u", "", "user") + stcpCmd.PersistentFlags().StringVarP(&protocol, "protocol", "p", "tcp", "tcp or kcp") + stcpCmd.PersistentFlags().StringVarP(&token, "token", "t", "", "auth token") + stcpCmd.PersistentFlags().StringVarP(&logLevel, "log_level", "", "info", "log level") + stcpCmd.PersistentFlags().StringVarP(&logFile, "log_file", "", "console", "console or file path") + stcpCmd.PersistentFlags().IntVarP(&logMaxDays, "log_max_days", "", 3, "log file reversed days") + + stcpCmd.PersistentFlags().StringVarP(&proxyName, "proxy_name", "n", "", "proxy name") + stcpCmd.PersistentFlags().StringVarP(&role, "role", "", "server", "role") + stcpCmd.PersistentFlags().StringVarP(&sk, "sk", "", "", "secret key") + stcpCmd.PersistentFlags().StringVarP(&serverName, "server_name", "", "", "server name") + stcpCmd.PersistentFlags().StringVarP(&localIp, "local_ip", "i", "127.0.0.1", "local ip") + stcpCmd.PersistentFlags().IntVarP(&localPort, "local_port", "l", 0, "local port") + stcpCmd.PersistentFlags().StringVarP(&bindAddr, "bind_addr", "", "", "bind addr") + stcpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption") + stcpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression") + + rootCmd.AddCommand(stcpCmd) +} + +var stcpCmd = &cobra.Command{ + Use: "http", + Short: "Run frpc with a single http proxy", + RunE: func(cmd *cobra.Command, args []string) error { + err := parseClientCommonCfg(CfgFileTypeCmd, "") + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + cfg := &config.StcpProxyConf{} + var prefix string + if user != "" { + prefix = user + "." + } + cfg.ProxyName = prefix + proxyName + cfg.ProxyType = consts.StcpProxy + cfg.Role = role + cfg.Sk = sk + cfg.ServerName = serverName + cfg.LocalIp = localIp + cfg.LocalPort = localPort + cfg.BindAddr = bindAddr + cfg.UseEncryption = useEncryption + cfg.UseCompression = useCompression + + err = cfg.CheckForCli() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + if cfg.Role == "server" { + proxyConfs := map[string]config.ProxyConf{ + cfg.ProxyName: cfg, + } + err = startService(proxyConfs, nil) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + } else { + visitorConfs := map[string]config.ProxyConf{ + cfg.ProxyName: cfg, + } + err = startService(nil, visitorConfs) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + } + return nil + }, +} diff --git a/cmd/frpc/sub/tcp.go b/cmd/frpc/sub/tcp.go new file mode 100644 index 0000000..154db15 --- /dev/null +++ b/cmd/frpc/sub/tcp.go @@ -0,0 +1,85 @@ +// Copyright 2018 fatedier, fatedier@gmail.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sub + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" + + "github.com/fatedier/frp/models/config" + "github.com/fatedier/frp/models/consts" +) + +func init() { + tcpCmd.PersistentFlags().StringVarP(&serverAddr, "server_addr", "s", "127.0.0.1:7000", "frp server's address") + tcpCmd.PersistentFlags().StringVarP(&user, "user", "u", "", "user") + tcpCmd.PersistentFlags().StringVarP(&protocol, "protocol", "p", "tcp", "tcp or kcp") + tcpCmd.PersistentFlags().StringVarP(&token, "token", "t", "", "auth token") + tcpCmd.PersistentFlags().StringVarP(&logLevel, "log_level", "", "info", "log level") + tcpCmd.PersistentFlags().StringVarP(&logFile, "log_file", "", "console", "console or file path") + tcpCmd.PersistentFlags().IntVarP(&logMaxDays, "log_max_days", "", 3, "log file reversed days") + + tcpCmd.PersistentFlags().StringVarP(&proxyName, "proxy_name", "n", "", "proxy name") + tcpCmd.PersistentFlags().StringVarP(&localIp, "local_ip", "i", "127.0.0.1", "local ip") + tcpCmd.PersistentFlags().IntVarP(&localPort, "local_port", "l", 0, "local port") + tcpCmd.PersistentFlags().IntVarP(&remotePort, "remote_port", "r", 0, "remote port") + tcpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption") + tcpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression") + + rootCmd.AddCommand(tcpCmd) +} + +var tcpCmd = &cobra.Command{ + Use: "tcp", + Short: "Run frpc with a single tcp proxy", + RunE: func(cmd *cobra.Command, args []string) error { + err := parseClientCommonCfg(CfgFileTypeCmd, "") + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + cfg := &config.TcpProxyConf{} + var prefix string + if user != "" { + prefix = user + "." + } + cfg.ProxyName = prefix + proxyName + cfg.ProxyType = consts.TcpProxy + cfg.LocalIp = localIp + cfg.LocalPort = localPort + cfg.RemotePort = remotePort + cfg.UseEncryption = useEncryption + cfg.UseCompression = useCompression + + err = cfg.CheckForCli() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + proxyConfs := map[string]config.ProxyConf{ + cfg.ProxyName: cfg, + } + err = startService(proxyConfs, nil) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + return nil + }, +} diff --git a/cmd/frpc/sub/udp.go b/cmd/frpc/sub/udp.go new file mode 100644 index 0000000..bbe1936 --- /dev/null +++ b/cmd/frpc/sub/udp.go @@ -0,0 +1,85 @@ +// Copyright 2018 fatedier, fatedier@gmail.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sub + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" + + "github.com/fatedier/frp/models/config" + "github.com/fatedier/frp/models/consts" +) + +func init() { + udpCmd.PersistentFlags().StringVarP(&serverAddr, "server_addr", "s", "127.0.0.1:7000", "frp server's address") + udpCmd.PersistentFlags().StringVarP(&user, "user", "u", "", "user") + udpCmd.PersistentFlags().StringVarP(&protocol, "protocol", "p", "tcp", "tcp or kcp") + udpCmd.PersistentFlags().StringVarP(&token, "token", "t", "", "auth token") + udpCmd.PersistentFlags().StringVarP(&logLevel, "log_level", "", "info", "log level") + udpCmd.PersistentFlags().StringVarP(&logFile, "log_file", "", "console", "console or file path") + udpCmd.PersistentFlags().IntVarP(&logMaxDays, "log_max_days", "", 3, "log file reversed days") + + udpCmd.PersistentFlags().StringVarP(&proxyName, "proxy_name", "n", "", "proxy name") + udpCmd.PersistentFlags().StringVarP(&localIp, "local_ip", "i", "127.0.0.1", "local ip") + udpCmd.PersistentFlags().IntVarP(&localPort, "local_port", "l", 0, "local port") + udpCmd.PersistentFlags().IntVarP(&remotePort, "remote_port", "r", 0, "remote port") + udpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption") + udpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression") + + rootCmd.AddCommand(udpCmd) +} + +var udpCmd = &cobra.Command{ + Use: "udp", + Short: "Run frpc with a single udp proxy", + RunE: func(cmd *cobra.Command, args []string) error { + err := parseClientCommonCfg(CfgFileTypeCmd, "") + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + cfg := &config.UdpProxyConf{} + var prefix string + if user != "" { + prefix = user + "." + } + cfg.ProxyName = prefix + proxyName + cfg.ProxyType = consts.UdpProxy + cfg.LocalIp = localIp + cfg.LocalPort = localPort + cfg.RemotePort = remotePort + cfg.UseEncryption = useEncryption + cfg.UseCompression = useCompression + + err = cfg.CheckForCli() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + proxyConfs := map[string]config.ProxyConf{ + cfg.ProxyName: cfg, + } + err = startService(proxyConfs, nil) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + return nil + }, +} diff --git a/cmd/frpc/sub/xtcp.go b/cmd/frpc/sub/xtcp.go new file mode 100644 index 0000000..53bd137 --- /dev/null +++ b/cmd/frpc/sub/xtcp.go @@ -0,0 +1,102 @@ +// Copyright 2018 fatedier, fatedier@gmail.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sub + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" + + "github.com/fatedier/frp/models/config" + "github.com/fatedier/frp/models/consts" +) + +func init() { + xtcpCmd.PersistentFlags().StringVarP(&serverAddr, "server_addr", "s", "127.0.0.1:7000", "frp server's address") + xtcpCmd.PersistentFlags().StringVarP(&user, "user", "u", "", "user") + xtcpCmd.PersistentFlags().StringVarP(&protocol, "protocol", "p", "tcp", "tcp or kcp") + xtcpCmd.PersistentFlags().StringVarP(&token, "token", "t", "", "auth token") + xtcpCmd.PersistentFlags().StringVarP(&logLevel, "log_level", "", "info", "log level") + xtcpCmd.PersistentFlags().StringVarP(&logFile, "log_file", "", "console", "console or file path") + xtcpCmd.PersistentFlags().IntVarP(&logMaxDays, "log_max_days", "", 3, "log file reversed days") + + xtcpCmd.PersistentFlags().StringVarP(&proxyName, "proxy_name", "n", "", "proxy name") + xtcpCmd.PersistentFlags().StringVarP(&role, "role", "", "server", "role") + xtcpCmd.PersistentFlags().StringVarP(&sk, "sk", "", "", "secret key") + xtcpCmd.PersistentFlags().StringVarP(&serverName, "server_name", "", "", "server name") + xtcpCmd.PersistentFlags().StringVarP(&localIp, "local_ip", "i", "127.0.0.1", "local ip") + xtcpCmd.PersistentFlags().IntVarP(&localPort, "local_port", "l", 0, "local port") + xtcpCmd.PersistentFlags().StringVarP(&bindAddr, "bind_addr", "", "", "bind addr") + xtcpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption") + xtcpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression") + + rootCmd.AddCommand(xtcpCmd) +} + +var xtcpCmd = &cobra.Command{ + Use: "http", + Short: "Run frpc with a single http proxy", + RunE: func(cmd *cobra.Command, args []string) error { + err := parseClientCommonCfg(CfgFileTypeCmd, "") + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + cfg := &config.XtcpProxyConf{} + var prefix string + if user != "" { + prefix = user + "." + } + cfg.ProxyName = prefix + proxyName + cfg.ProxyType = consts.XtcpProxy + cfg.Role = role + cfg.Sk = sk + cfg.ServerName = serverName + cfg.LocalIp = localIp + cfg.LocalPort = localPort + cfg.BindAddr = bindAddr + cfg.UseEncryption = useEncryption + cfg.UseCompression = useCompression + + err = cfg.CheckForCli() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + if cfg.Role == "server" { + proxyConfs := map[string]config.ProxyConf{ + cfg.ProxyName: cfg, + } + err = startService(proxyConfs, nil) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + } else { + visitorConfs := map[string]config.ProxyConf{ + cfg.ProxyName: cfg, + } + err = startService(nil, visitorConfs) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + } + return nil + }, +} diff --git a/cmd/frps/main.go b/cmd/frps/main.go index c3b495a..842bf3a 100644 --- a/cmd/frps/main.go +++ b/cmd/frps/main.go @@ -1,4 +1,4 @@ -// Copyright 2016 fatedier, fatedier@gmail.com +// Copyright 2018 fatedier, fatedier@gmail.com // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,105 +14,6 @@ package main -import ( - "fmt" - "os" - "strconv" - "strings" - - docopt "github.com/docopt/docopt-go" - ini "github.com/vaughan0/go-ini" - - "github.com/fatedier/frp/models/config" - "github.com/fatedier/frp/server" - "github.com/fatedier/frp/utils/log" - "github.com/fatedier/frp/utils/version" -) - -var usage string = `frps is the server of frp - -Usage: - frps [-c config_file] [-L log_file] [--log-level=] [--addr=] - frps -h | --help - frps -v | --version - -Options: - -c config_file set config file - -L log_file set output log file, including console - --log-level= set log level: debug, info, warn, error - --addr= listen addr for client, example: 0.0.0.0:7000 - -h --help show this screen - -v --version show version -` - func main() { - var err error - confFile := "./frps.ini" - // the configures parsed from file will be replaced by those from command line if exist - args, err := docopt.Parse(usage, nil, true, version.Full(), false) - - if args["-c"] != nil { - confFile = args["-c"].(string) - } - - conf, err := ini.LoadFile(confFile) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - config.ServerCommonCfg, err = config.LoadServerCommonConf(conf) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - - if args["-L"] != nil { - if args["-L"].(string) == "console" { - config.ServerCommonCfg.LogWay = "console" - } else { - config.ServerCommonCfg.LogWay = "file" - config.ServerCommonCfg.LogFile = args["-L"].(string) - } - } - - if args["--log-level"] != nil { - config.ServerCommonCfg.LogLevel = args["--log-level"].(string) - } - - if args["--addr"] != nil { - addr := strings.Split(args["--addr"].(string), ":") - if len(addr) != 2 { - fmt.Println("--addr format error: example 0.0.0.0:7000") - os.Exit(1) - } - bindPort, err := strconv.ParseInt(addr[1], 10, 64) - if err != nil { - fmt.Println("--addr format error, example 0.0.0.0:7000") - os.Exit(1) - } - config.ServerCommonCfg.BindAddr = addr[0] - config.ServerCommonCfg.BindPort = int(bindPort) - } - - if args["-v"] != nil { - if args["-v"].(bool) { - fmt.Println(version.Full()) - os.Exit(0) - } - } - - log.InitLog(config.ServerCommonCfg.LogWay, config.ServerCommonCfg.LogFile, - config.ServerCommonCfg.LogLevel, config.ServerCommonCfg.LogMaxDays) - - svr, err := server.NewService() - if err != nil { - fmt.Println(err) - os.Exit(1) - } - log.Info("Start frps success") - if config.ServerCommonCfg.PrivilegeMode == true { - log.Info("PrivilegeMode is enabled, you should pay more attention to security issues") - } - server.ServerService = svr - svr.Run() + Execute() } diff --git a/cmd/frps/root.go b/cmd/frps/root.go new file mode 100644 index 0000000..44a35f3 --- /dev/null +++ b/cmd/frps/root.go @@ -0,0 +1,174 @@ +package main + +import ( + "fmt" + "io/ioutil" + "os" + + "github.com/spf13/cobra" + + "github.com/fatedier/frp/g" + "github.com/fatedier/frp/models/config" + "github.com/fatedier/frp/server" + "github.com/fatedier/frp/utils/log" + "github.com/fatedier/frp/utils/version" +) + +const ( + CfgFileTypeIni = iota + CfgFileTypeCmd +) + +var ( + cfgFile string + showVersion bool + + bindAddr string + bindPort int + bindUdpPort int + kcpBindPort int + proxyBindAddr string + vhostHttpPort int + vhostHttpsPort int + dashboardAddr string + dashboardPort int + dashboardUser string + dashboardPwd string + assetsDir string + logFile string + logWay string + logLevel string + logMaxDays int64 + token string + authTimeout int64 + subDomainHost string + tcpMux bool + allowPorts string + maxPoolCount int64 + maxPortsPerClient int64 +) + +func init() { + rootCmd.PersistentFlags().StringVarP(&cfgFile, "", "c", "", "config file of frps") + rootCmd.PersistentFlags().BoolVarP(&showVersion, "version", "v", false, "version of frpc") + + rootCmd.PersistentFlags().StringVarP(&bindAddr, "bind_addr", "h", "0.0.0.0", "bind address") + rootCmd.PersistentFlags().IntVarP(&bindPort, "bind_port", "p", 7000, "bind port") + rootCmd.PersistentFlags().IntVarP(&bindUdpPort, "bind_udp_port", "", 0, "bind udp port") + rootCmd.PersistentFlags().IntVarP(&kcpBindPort, "kcp_bind_port", "", 0, "kcp bind udp port") + rootCmd.PersistentFlags().StringVarP(&proxyBindAddr, "proxy_bind_addr", "", "0.0.0.0", "proxy bind address") + rootCmd.PersistentFlags().IntVarP(&vhostHttpPort, "vhost_http_port", "", 0, "vhost http port") + rootCmd.PersistentFlags().IntVarP(&vhostHttpsPort, "vhost_https_port", "", 0, "vhost https port") + rootCmd.PersistentFlags().StringVarP(&dashboardAddr, "dashboard_addr", "", "0.0.0.0", "dasboard address") + rootCmd.PersistentFlags().IntVarP(&dashboardPort, "dashboard_port", "", 0, "dashboard port") + rootCmd.PersistentFlags().StringVarP(&dashboardUser, "dashboard_user", "", "admin", "dashboard user") + rootCmd.PersistentFlags().StringVarP(&dashboardPwd, "dashboard_pwd", "", "admin", "dashboard password") + rootCmd.PersistentFlags().StringVarP(&logFile, "log_file", "", "console", "log file") + rootCmd.PersistentFlags().StringVarP(&logWay, "log_way", "", "console", "log way") + rootCmd.PersistentFlags().StringVarP(&logLevel, "log_level", "", "info", "log level") + rootCmd.PersistentFlags().Int64VarP(&logMaxDays, "log_max_days", "", 3, "log_max_days") + rootCmd.PersistentFlags().StringVarP(&token, "token", "", "", "auth token") + rootCmd.PersistentFlags().Int64VarP(&authTimeout, "auth_timeout", "", 900, "auth timeout") + rootCmd.PersistentFlags().StringVarP(&subDomainHost, "subdomain_host", "", "", "subdomain host") + rootCmd.PersistentFlags().Int64VarP(&maxPortsPerClient, "max_ports_per_client", "", 0, "max ports per client") +} + +var rootCmd = &cobra.Command{ + Use: "frps", + Short: "frps is the server of frp (https://github.com/fatedier/frp)", + RunE: func(cmd *cobra.Command, args []string) error { + if showVersion { + fmt.Println(version.Full()) + return nil + } + + if cfgFile != "" { + parseServerCommonCfg(CfgFileTypeIni, cfgFile) + } else { + parseServerCommonCfg(CfgFileTypeCmd, "") + } + + err := runServer() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + return nil + }, +} + +func Execute() { + if err := rootCmd.Execute(); err != nil { + os.Exit(1) + } +} + +func parseServerCommonCfg(fileType int, filePath string) (err error) { + if fileType == CfgFileTypeIni { + err = parseServerCommonCfgFromIni(filePath) + } else if fileType == CfgFileTypeCmd { + err = parseServerCommonCfgFromCmd() + } + if err != nil { + return + } + + g.GlbServerCfg.CfgFile = cfgFile + + err = g.GlbServerCfg.ServerCommonConf.Check() + if err != nil { + return + } + return +} + +func parseServerCommonCfgFromIni(filePath string) (err error) { + b, err := ioutil.ReadFile(filePath) + if err != nil { + return err + } + content := string(b) + + cfg, err := config.UnmarshalServerConfFromIni(&g.GlbServerCfg.ServerCommonConf, content) + if err != nil { + return err + } + g.GlbServerCfg.ServerCommonConf = *cfg + return +} + +func parseServerCommonCfgFromCmd() (err error) { + g.GlbServerCfg.BindAddr = bindAddr + g.GlbServerCfg.BindPort = bindPort + g.GlbServerCfg.BindUdpPort = bindUdpPort + g.GlbServerCfg.KcpBindPort = kcpBindPort + g.GlbServerCfg.ProxyBindAddr = proxyBindAddr + g.GlbServerCfg.VhostHttpPort = vhostHttpPort + g.GlbServerCfg.VhostHttpsPort = vhostHttpsPort + g.GlbServerCfg.DashboardAddr = dashboardAddr + g.GlbServerCfg.DashboardPort = dashboardPort + g.GlbServerCfg.DashboardUser = dashboardUser + g.GlbServerCfg.DashboardPwd = dashboardPwd + g.GlbServerCfg.LogFile = logFile + g.GlbServerCfg.LogWay = logWay + g.GlbServerCfg.LogLevel = logLevel + g.GlbServerCfg.LogMaxDays = logMaxDays + g.GlbServerCfg.Token = token + g.GlbServerCfg.AuthTimeout = authTimeout + g.GlbServerCfg.SubDomainHost = subDomainHost + g.GlbServerCfg.MaxPortsPerClient = maxPortsPerClient + return +} + +func runServer() (err error) { + log.InitLog(g.GlbServerCfg.LogWay, g.GlbServerCfg.LogFile, g.GlbServerCfg.LogLevel, + g.GlbServerCfg.LogMaxDays) + svr, err := server.NewService() + if err != nil { + return err + } + log.Info("Start frps success") + server.ServerService = svr + svr.Run() + return +} diff --git a/conf/frpc_full.ini b/conf/frpc_full.ini index 4bec160..844ed0e 100644 --- a/conf/frpc_full.ini +++ b/conf/frpc_full.ini @@ -7,7 +7,7 @@ server_port = 7000 # if you want to connect frps by http proxy, you can set http_proxy here or in global environment variables # it only works when protocol is tcp -# http_proxy = http://user:pwd@192.168.1.128:8080 +# http_proxy = http://user:passwd@192.168.1.128:8080 # console or real logFile path like ./frpc.log log_file = ./frpc.log @@ -18,13 +18,13 @@ log_level = info log_max_days = 3 # for authentication -privilege_token = 12345678 +token = 12345678 # set admin address for control frpc's action by http api such as reload admin_addr = 127.0.0.1 admin_port = 7400 admin_user = admin -admin_pwd = admin +admin_passwd = admin # connections will be established in advance, default value is zero pool_count = 5 @@ -109,7 +109,7 @@ use_compression = true # http username and password are safety certification for http protocol # if not set, you can access this custom_domains without certification http_user = admin -http_pwd = admin +http_passwd = admin # if domain for frps is frps.com, then you can access [web01] proxy by URL http://test.frps.com subdomain = web01 custom_domains = web02.yourdomain.com diff --git a/conf/frps_full.ini b/conf/frps_full.ini index e2a7c3f..a808cc3 100644 --- a/conf/frps_full.ini +++ b/conf/frps_full.ini @@ -25,9 +25,9 @@ vhost_https_port = 443 dashboard_addr = 0.0.0.0 dashboard_port = 7500 -# dashboard user and pwd for basic auth protect, if not set, both default value is admin +# dashboard user and passwd for basic auth protect, if not set, both default value is admin dashboard_user = admin -dashboard_pwd = admin +dashboard_passwd = admin # dashboard assets directory(only for debug mode) # assets_dir = ./static @@ -39,8 +39,8 @@ log_level = info log_max_days = 3 -# privilege mode is the only supported mode since v0.10.0 -privilege_token = 12345678 +# auth token +token = 12345678 # heartbeat configure, it's not recommended to modify the default value # the default value of heartbeat_timeout is 90 diff --git a/g/g.go b/g/g.go new file mode 100644 index 0000000..3c7385f --- /dev/null +++ b/g/g.go @@ -0,0 +1,32 @@ +package g + +import ( + "github.com/fatedier/frp/models/config" +) + +var ( + GlbClientCfg *ClientCfg + GlbServerCfg *ServerCfg +) + +func init() { + GlbClientCfg = &ClientCfg{ + ClientCommonConf: *config.GetDefaultClientConf(), + } + GlbServerCfg = &ServerCfg{ + ServerCommonConf: *config.GetDefaultServerConf(), + } +} + +type ClientCfg struct { + config.ClientCommonConf + + CfgFile string + ServerUdpPort int // this is configured by login response from frps +} + +type ServerCfg struct { + config.ServerCommonConf + + CfgFile string +} diff --git a/models/config/client_common.go b/models/config/client_common.go index 4b9ede7..726352d 100644 --- a/models/config/client_common.go +++ b/models/config/client_common.go @@ -23,46 +23,40 @@ import ( ini "github.com/vaughan0/go-ini" ) -var ClientCommonCfg *ClientCommonConf - // client common config type ClientCommonConf struct { - ConfigFile string - ServerAddr string - ServerPort int - ServerUdpPort int // this is specified by login response message from frps - HttpProxy string - LogFile string - LogWay string - LogLevel string - LogMaxDays int64 - PrivilegeToken string - AdminAddr string - AdminPort int - AdminUser string - AdminPwd string - PoolCount int - TcpMux bool - User string - LoginFailExit bool - Start map[string]struct{} - Protocol string - HeartBeatInterval int64 - HeartBeatTimeout int64 + ServerAddr string `json:"server_addr"` + ServerPort int `json:"server_port"` + HttpProxy string `json:"http_proxy"` + LogFile string `json:"log_file"` + LogWay string `json:"log_way"` + LogLevel string `json:"log_level"` + LogMaxDays int64 `json:"log_max_days"` + Token string `json:"token"` + AdminAddr string `json:"admin_addr"` + AdminPort int `json:"admin_port"` + AdminUser string `json:"admin_user"` + AdminPwd string `json:"admin_pwd"` + PoolCount int `json:"pool_count"` + TcpMux bool `json:"tcp_mux"` + User string `json:"user"` + LoginFailExit bool `json:"login_fail_exit"` + Start map[string]struct{} `json:"start"` + Protocol string `json:"protocol"` + HeartBeatInterval int64 `json:"heartbeat_interval"` + HeartBeatTimeout int64 `json:"heartbeat_timeout"` } -func GetDeaultClientCommonConf() *ClientCommonConf { +func GetDefaultClientConf() *ClientCommonConf { return &ClientCommonConf{ - ConfigFile: "./frpc.ini", ServerAddr: "0.0.0.0", ServerPort: 7000, - ServerUdpPort: 0, - HttpProxy: "", + HttpProxy: os.Getenv("http_proxy"), LogFile: "console", LogWay: "console", LogLevel: "info", LogMaxDays: 3, - PrivilegeToken: "", + Token: "", AdminAddr: "127.0.0.1", AdminPort: 0, AdminUser: "", @@ -78,21 +72,28 @@ func GetDeaultClientCommonConf() *ClientCommonConf { } } -func LoadClientCommonConf(conf ini.File) (cfg *ClientCommonConf, err error) { +func UnmarshalClientConfFromIni(defaultCfg *ClientCommonConf, content string) (cfg *ClientCommonConf, err error) { + cfg = defaultCfg + if cfg == nil { + cfg = GetDefaultClientConf() + } + + conf, err := ini.Load(strings.NewReader(content)) + if err != nil { + err = fmt.Errorf("parse ini conf file error: %v", err) + return nil, err + } + var ( tmpStr string ok bool v int64 ) - cfg = GetDeaultClientCommonConf() - - tmpStr, ok = conf.Get("common", "server_addr") - if ok { + if tmpStr, ok = conf.Get("common", "server_addr"); ok { cfg.ServerAddr = tmpStr } - tmpStr, ok = conf.Get("common", "server_port") - if ok { + if tmpStr, ok = conf.Get("common", "server_port"); ok { v, err = strconv.ParseInt(tmpStr, 10, 64) if err != nil { err = fmt.Errorf("Parse conf error: invalid server_port") @@ -101,16 +102,11 @@ func LoadClientCommonConf(conf ini.File) (cfg *ClientCommonConf, err error) { cfg.ServerPort = int(v) } - tmpStr, ok = conf.Get("common", "http_proxy") - if ok { + if tmpStr, ok = conf.Get("common", "http_proxy"); ok { cfg.HttpProxy = tmpStr - } else { - // get http_proxy from env - cfg.HttpProxy = os.Getenv("http_proxy") } - tmpStr, ok = conf.Get("common", "log_file") - if ok { + if tmpStr, ok = conf.Get("common", "log_file"); ok { cfg.LogFile = tmpStr if cfg.LogFile == "console" { cfg.LogWay = "console" @@ -119,30 +115,25 @@ func LoadClientCommonConf(conf ini.File) (cfg *ClientCommonConf, err error) { } } - tmpStr, ok = conf.Get("common", "log_level") - if ok { + if tmpStr, ok = conf.Get("common", "log_level"); ok { cfg.LogLevel = tmpStr } - tmpStr, ok = conf.Get("common", "log_max_days") - if ok { + if tmpStr, ok = conf.Get("common", "log_max_days"); ok { if v, err = strconv.ParseInt(tmpStr, 10, 64); err == nil { cfg.LogMaxDays = v } } - tmpStr, ok = conf.Get("common", "privilege_token") - if ok { - cfg.PrivilegeToken = tmpStr + if tmpStr, ok = conf.Get("common", "token"); ok { + cfg.Token = tmpStr } - tmpStr, ok = conf.Get("common", "admin_addr") - if ok { + if tmpStr, ok = conf.Get("common", "admin_addr"); ok { cfg.AdminAddr = tmpStr } - tmpStr, ok = conf.Get("common", "admin_port") - if ok { + if tmpStr, ok = conf.Get("common", "admin_port"); ok { if v, err = strconv.ParseInt(tmpStr, 10, 64); err == nil { cfg.AdminPort = int(v) } else { @@ -151,55 +142,44 @@ func LoadClientCommonConf(conf ini.File) (cfg *ClientCommonConf, err error) { } } - tmpStr, ok = conf.Get("common", "admin_user") - if ok { + if tmpStr, ok = conf.Get("common", "admin_user"); ok { cfg.AdminUser = tmpStr } - tmpStr, ok = conf.Get("common", "admin_pwd") - if ok { + if tmpStr, ok = conf.Get("common", "admin_pwd"); ok { cfg.AdminPwd = tmpStr } - tmpStr, ok = conf.Get("common", "pool_count") - if ok { - v, err = strconv.ParseInt(tmpStr, 10, 64) - if err != nil { - cfg.PoolCount = 1 - } else { + if tmpStr, ok = conf.Get("common", "pool_count"); ok { + if v, err = strconv.ParseInt(tmpStr, 10, 64); err == nil { cfg.PoolCount = int(v) } } - tmpStr, ok = conf.Get("common", "tcp_mux") - if ok && tmpStr == "false" { + if tmpStr, ok = conf.Get("common", "tcp_mux"); ok && tmpStr == "false" { cfg.TcpMux = false } else { cfg.TcpMux = true } - tmpStr, ok = conf.Get("common", "user") - if ok { + if tmpStr, ok = conf.Get("common", "user"); ok { cfg.User = tmpStr } - tmpStr, ok = conf.Get("common", "start") - if ok { + if tmpStr, ok = conf.Get("common", "start"); ok { proxyNames := strings.Split(tmpStr, ",") for _, name := range proxyNames { cfg.Start[strings.TrimSpace(name)] = struct{}{} } } - tmpStr, ok = conf.Get("common", "login_fail_exit") - if ok && tmpStr == "false" { + if tmpStr, ok = conf.Get("common", "login_fail_exit"); ok && tmpStr == "false" { cfg.LoginFailExit = false } else { cfg.LoginFailExit = true } - tmpStr, ok = conf.Get("common", "protocol") - if ok { + if tmpStr, ok = conf.Get("common", "protocol"); ok { // Now it only support tcp and kcp. if tmpStr != "kcp" { tmpStr = "tcp" @@ -207,10 +187,8 @@ func LoadClientCommonConf(conf ini.File) (cfg *ClientCommonConf, err error) { cfg.Protocol = tmpStr } - tmpStr, ok = conf.Get("common", "heartbeat_timeout") - if ok { - v, err = strconv.ParseInt(tmpStr, 10, 64) - if err != nil { + if tmpStr, ok = conf.Get("common", "heartbeat_timeout"); ok { + if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil { err = fmt.Errorf("Parse conf error: invalid heartbeat_timeout") return } else { @@ -218,17 +196,18 @@ func LoadClientCommonConf(conf ini.File) (cfg *ClientCommonConf, err error) { } } - tmpStr, ok = conf.Get("common", "heartbeat_interval") - if ok { - v, err = strconv.ParseInt(tmpStr, 10, 64) - if err != nil { + if tmpStr, ok = conf.Get("common", "heartbeat_interval"); ok { + if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil { err = fmt.Errorf("Parse conf error: invalid heartbeat_interval") return } else { cfg.HeartBeatInterval = v } } + return +} +func (cfg *ClientCommonConf) Check() (err error) { if cfg.HeartBeatInterval <= 0 { err = fmt.Errorf("Parse conf error: invalid heartbeat_interval") return diff --git a/models/config/proxy.go b/models/config/proxy.go index 49835c3..e6022b6 100644 --- a/models/config/proxy.go +++ b/models/config/proxy.go @@ -27,7 +27,9 @@ import ( ini "github.com/vaughan0/go-ini" ) -var proxyConfTypeMap map[string]reflect.Type +var ( + proxyConfTypeMap map[string]reflect.Type +) func init() { proxyConfTypeMap = make(map[string]reflect.Type) @@ -51,17 +53,16 @@ func NewConfByType(proxyType string) ProxyConf { } type ProxyConf interface { - GetName() string - GetType() string GetBaseInfo() *BaseProxyConf - LoadFromMsg(pMsg *msg.NewProxy) - LoadFromFile(name string, conf ini.Section) error - UnMarshalToMsg(pMsg *msg.NewProxy) - Check() error + UnmarshalFromMsg(pMsg *msg.NewProxy) + UnmarshalFromIni(prefix string, name string, conf ini.Section) error + MarshalToMsg(pMsg *msg.NewProxy) + CheckForCli() error + CheckForSvr() error Compare(conf ProxyConf) bool } -func NewProxyConf(pMsg *msg.NewProxy) (cfg ProxyConf, err error) { +func NewProxyConfFromMsg(pMsg *msg.NewProxy) (cfg ProxyConf, err error) { if pMsg.ProxyType == "" { pMsg.ProxyType = consts.TcpProxy } @@ -71,12 +72,12 @@ func NewProxyConf(pMsg *msg.NewProxy) (cfg ProxyConf, err error) { err = fmt.Errorf("proxy [%s] type [%s] error", pMsg.ProxyName, pMsg.ProxyType) return } - cfg.LoadFromMsg(pMsg) - err = cfg.Check() + cfg.UnmarshalFromMsg(pMsg) + err = cfg.CheckForSvr() return } -func NewProxyConfFromFile(name string, section ini.Section) (cfg ProxyConf, err error) { +func NewProxyConfFromIni(prefix string, name string, section ini.Section) (cfg ProxyConf, err error) { proxyType := section["type"] if proxyType == "" { proxyType = consts.TcpProxy @@ -87,7 +88,10 @@ func NewProxyConfFromFile(name string, section ini.Section) (cfg ProxyConf, err err = fmt.Errorf("proxy [%s] type [%s] error", name, proxyType) return } - err = cfg.LoadFromFile(name, section) + if err = cfg.UnmarshalFromIni(prefix, name, section); err != nil { + return + } + err = cfg.CheckForCli() return } @@ -100,14 +104,6 @@ type BaseProxyConf struct { UseCompression bool `json:"use_compression"` } -func (cfg *BaseProxyConf) GetName() string { - return cfg.ProxyName -} - -func (cfg *BaseProxyConf) GetType() string { - return cfg.ProxyType -} - func (cfg *BaseProxyConf) GetBaseInfo() *BaseProxyConf { return cfg } @@ -122,23 +118,19 @@ func (cfg *BaseProxyConf) compare(cmp *BaseProxyConf) bool { return true } -func (cfg *BaseProxyConf) LoadFromMsg(pMsg *msg.NewProxy) { +func (cfg *BaseProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) { cfg.ProxyName = pMsg.ProxyName cfg.ProxyType = pMsg.ProxyType cfg.UseEncryption = pMsg.UseEncryption cfg.UseCompression = pMsg.UseCompression } -func (cfg *BaseProxyConf) LoadFromFile(name string, section ini.Section) error { +func (cfg *BaseProxyConf) UnmarshalFromIni(prefix string, name string, section ini.Section) error { var ( tmpStr string ok bool ) - if ClientCommonCfg.User != "" { - cfg.ProxyName = ClientCommonCfg.User + "." + name - } else { - cfg.ProxyName = name - } + cfg.ProxyName = prefix + name cfg.ProxyType = section["type"] tmpStr, ok = section["use_encryption"] @@ -153,7 +145,7 @@ func (cfg *BaseProxyConf) LoadFromFile(name string, section ini.Section) error { return nil } -func (cfg *BaseProxyConf) UnMarshalToMsg(pMsg *msg.NewProxy) { +func (cfg *BaseProxyConf) MarshalToMsg(pMsg *msg.NewProxy) { pMsg.ProxyName = cfg.ProxyName pMsg.ProxyType = cfg.ProxyType pMsg.UseEncryption = cfg.UseEncryption @@ -162,24 +154,21 @@ func (cfg *BaseProxyConf) UnMarshalToMsg(pMsg *msg.NewProxy) { // Bind info type BindInfoConf struct { - BindAddr string `json:"bind_addr"` - RemotePort int `json:"remote_port"` + RemotePort int `json:"remote_port"` } func (cfg *BindInfoConf) compare(cmp *BindInfoConf) bool { - if cfg.BindAddr != cmp.BindAddr || - cfg.RemotePort != cmp.RemotePort { + if cfg.RemotePort != cmp.RemotePort { return false } return true } -func (cfg *BindInfoConf) LoadFromMsg(pMsg *msg.NewProxy) { - cfg.BindAddr = ServerCommonCfg.ProxyBindAddr +func (cfg *BindInfoConf) UnmarshalFromMsg(pMsg *msg.NewProxy) { cfg.RemotePort = pMsg.RemotePort } -func (cfg *BindInfoConf) LoadFromFile(name string, section ini.Section) (err error) { +func (cfg *BindInfoConf) UnmarshalFromIni(prefix string, name string, section ini.Section) (err error) { var ( tmpStr string ok bool @@ -197,14 +186,10 @@ func (cfg *BindInfoConf) LoadFromFile(name string, section ini.Section) (err err return nil } -func (cfg *BindInfoConf) UnMarshalToMsg(pMsg *msg.NewProxy) { +func (cfg *BindInfoConf) MarshalToMsg(pMsg *msg.NewProxy) { pMsg.RemotePort = cfg.RemotePort } -func (cfg *BindInfoConf) check() (err error) { - return nil -} - // Domain info type DomainConf struct { CustomDomains []string `json:"custom_domains"` @@ -219,12 +204,12 @@ func (cfg *DomainConf) compare(cmp *DomainConf) bool { return true } -func (cfg *DomainConf) LoadFromMsg(pMsg *msg.NewProxy) { +func (cfg *DomainConf) UnmarshalFromMsg(pMsg *msg.NewProxy) { cfg.CustomDomains = pMsg.CustomDomains cfg.SubDomain = pMsg.SubDomain } -func (cfg *DomainConf) LoadFromFile(name string, section ini.Section) (err error) { +func (cfg *DomainConf) UnmarshalFromIni(prefix string, name string, section ini.Section) (err error) { var ( tmpStr string ok bool @@ -239,42 +224,60 @@ func (cfg *DomainConf) LoadFromFile(name string, section ini.Section) (err error if tmpStr, ok = section["subdomain"]; ok { cfg.SubDomain = tmpStr } - - if len(cfg.CustomDomains) == 0 && cfg.SubDomain == "" { - return fmt.Errorf("Parse conf error: proxy [%s] custom_domains and subdomain should set at least one of them", name) - } return } -func (cfg *DomainConf) UnMarshalToMsg(pMsg *msg.NewProxy) { +func (cfg *DomainConf) MarshalToMsg(pMsg *msg.NewProxy) { pMsg.CustomDomains = cfg.CustomDomains pMsg.SubDomain = cfg.SubDomain } func (cfg *DomainConf) check() (err error) { + if len(cfg.CustomDomains) == 0 && cfg.SubDomain == "" { + err = fmt.Errorf("custom_domains and subdomain should set at least one of them") + return + } + return +} + +func (cfg *DomainConf) checkForCli() (err error) { + if err = cfg.check(); err != nil { + return + } + return +} + +func (cfg *DomainConf) checkForSvr() (err error) { + if err = cfg.check(); err != nil { + return + } + for _, domain := range cfg.CustomDomains { - if ServerCommonCfg.SubDomainHost != "" && len(strings.Split(ServerCommonCfg.SubDomainHost, ".")) < len(strings.Split(domain, ".")) { - if strings.Contains(domain, ServerCommonCfg.SubDomainHost) { - return fmt.Errorf("custom domain [%s] should not belong to subdomain_host [%s]", domain, ServerCommonCfg.SubDomainHost) + if subDomainHost != "" && len(strings.Split(subDomainHost, ".")) < len(strings.Split(domain, ".")) { + if strings.Contains(domain, subDomainHost) { + return fmt.Errorf("custom domain [%s] should not belong to subdomain_host [%s]", domain, subDomainHost) } } } if cfg.SubDomain != "" { - if ServerCommonCfg.SubDomainHost == "" { + if subDomainHost == "" { return fmt.Errorf("subdomain is not supported because this feature is not enabled by frps") } if strings.Contains(cfg.SubDomain, ".") || strings.Contains(cfg.SubDomain, "*") { return fmt.Errorf("'.' and '*' is not supported in subdomain") } } - return nil + return } // Local service info type LocalSvrConf struct { - LocalIp string `json:"-"` - LocalPort int `json:"-"` + LocalIp string `json:"local_ip"` + LocalPort int `json:"local_port"` + + Plugin string `json:"plugin"` + PluginParams map[string]string `json:"plugin_params"` } func (cfg *LocalSvrConf) compare(cmp *LocalSvrConf) bool { @@ -282,30 +285,6 @@ func (cfg *LocalSvrConf) compare(cmp *LocalSvrConf) bool { cfg.LocalPort != cmp.LocalPort { return false } - return true -} - -func (cfg *LocalSvrConf) LoadFromFile(name string, section ini.Section) (err error) { - if cfg.LocalIp = section["local_ip"]; cfg.LocalIp == "" { - cfg.LocalIp = "127.0.0.1" - } - - if tmpStr, ok := section["local_port"]; ok { - if cfg.LocalPort, err = strconv.Atoi(tmpStr); err != nil { - return fmt.Errorf("Parse conf error: proxy [%s] local_port error", name) - } - } else { - return fmt.Errorf("Parse conf error: proxy [%s] local_port not found", name) - } - return nil -} - -type PluginConf struct { - Plugin string `json:"-"` - PluginParams map[string]string `json:"-"` -} - -func (cfg *PluginConf) compare(cmp *PluginConf) bool { if cfg.Plugin != cmp.Plugin || len(cfg.PluginParams) != len(cmp.PluginParams) { return false @@ -319,7 +298,7 @@ func (cfg *PluginConf) compare(cmp *PluginConf) bool { return true } -func (cfg *PluginConf) LoadFromFile(name string, section ini.Section) (err error) { +func (cfg *LocalSvrConf) UnmarshalFromIni(prefix string, name string, section ini.Section) (err error) { cfg.Plugin = section["plugin"] cfg.PluginParams = make(map[string]string) if cfg.Plugin != "" { @@ -330,7 +309,17 @@ func (cfg *PluginConf) LoadFromFile(name string, section ini.Section) (err error } } } else { - return fmt.Errorf("Parse conf error: proxy [%s] no plugin info found", name) + if cfg.LocalIp = section["local_ip"]; cfg.LocalIp == "" { + cfg.LocalIp = "127.0.0.1" + } + + if tmpStr, ok := section["local_port"]; ok { + if cfg.LocalPort, err = strconv.Atoi(tmpStr); err != nil { + return fmt.Errorf("Parse conf error: proxy [%s] local_port error", name) + } + } else { + return fmt.Errorf("Parse conf error: proxy [%s] local_port not found", name) + } } return } @@ -341,7 +330,6 @@ type TcpProxyConf struct { BindInfoConf LocalSvrConf - PluginConf } func (cfg *TcpProxyConf) Compare(cmp ProxyConf) bool { @@ -352,43 +340,38 @@ func (cfg *TcpProxyConf) Compare(cmp ProxyConf) bool { if !cfg.BaseProxyConf.compare(&cmpConf.BaseProxyConf) || !cfg.BindInfoConf.compare(&cmpConf.BindInfoConf) || - !cfg.LocalSvrConf.compare(&cmpConf.LocalSvrConf) || - !cfg.PluginConf.compare(&cmpConf.PluginConf) { + !cfg.LocalSvrConf.compare(&cmpConf.LocalSvrConf) { return false } return true } -func (cfg *TcpProxyConf) LoadFromMsg(pMsg *msg.NewProxy) { - cfg.BaseProxyConf.LoadFromMsg(pMsg) - cfg.BindInfoConf.LoadFromMsg(pMsg) +func (cfg *TcpProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.UnmarshalFromMsg(pMsg) + cfg.BindInfoConf.UnmarshalFromMsg(pMsg) } -func (cfg *TcpProxyConf) LoadFromFile(name string, section ini.Section) (err error) { - if err = cfg.BaseProxyConf.LoadFromFile(name, section); err != nil { +func (cfg *TcpProxyConf) UnmarshalFromIni(prefix string, name string, section ini.Section) (err error) { + if err = cfg.BaseProxyConf.UnmarshalFromIni(prefix, name, section); err != nil { return } - if err = cfg.BindInfoConf.LoadFromFile(name, section); err != nil { + if err = cfg.BindInfoConf.UnmarshalFromIni(prefix, name, section); err != nil { return } - - if err = cfg.PluginConf.LoadFromFile(name, section); err != nil { - if err = cfg.LocalSvrConf.LoadFromFile(name, section); err != nil { - return - } + if err = cfg.LocalSvrConf.UnmarshalFromIni(prefix, name, section); err != nil { + return } return } -func (cfg *TcpProxyConf) UnMarshalToMsg(pMsg *msg.NewProxy) { - cfg.BaseProxyConf.UnMarshalToMsg(pMsg) - cfg.BindInfoConf.UnMarshalToMsg(pMsg) +func (cfg *TcpProxyConf) MarshalToMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.MarshalToMsg(pMsg) + cfg.BindInfoConf.MarshalToMsg(pMsg) } -func (cfg *TcpProxyConf) Check() (err error) { - err = cfg.BindInfoConf.check() - return -} +func (cfg *TcpProxyConf) CheckForCli() error { return nil } + +func (cfg *TcpProxyConf) CheckForSvr() error { return nil } // UDP type UdpProxyConf struct { @@ -412,33 +395,32 @@ func (cfg *UdpProxyConf) Compare(cmp ProxyConf) bool { return true } -func (cfg *UdpProxyConf) LoadFromMsg(pMsg *msg.NewProxy) { - cfg.BaseProxyConf.LoadFromMsg(pMsg) - cfg.BindInfoConf.LoadFromMsg(pMsg) +func (cfg *UdpProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.UnmarshalFromMsg(pMsg) + cfg.BindInfoConf.UnmarshalFromMsg(pMsg) } -func (cfg *UdpProxyConf) LoadFromFile(name string, section ini.Section) (err error) { - if err = cfg.BaseProxyConf.LoadFromFile(name, section); err != nil { +func (cfg *UdpProxyConf) UnmarshalFromIni(prefix string, name string, section ini.Section) (err error) { + if err = cfg.BaseProxyConf.UnmarshalFromIni(prefix, name, section); err != nil { return } - if err = cfg.BindInfoConf.LoadFromFile(name, section); err != nil { + if err = cfg.BindInfoConf.UnmarshalFromIni(prefix, name, section); err != nil { return } - if err = cfg.LocalSvrConf.LoadFromFile(name, section); err != nil { + if err = cfg.LocalSvrConf.UnmarshalFromIni(prefix, name, section); err != nil { return } return } -func (cfg *UdpProxyConf) UnMarshalToMsg(pMsg *msg.NewProxy) { - cfg.BaseProxyConf.UnMarshalToMsg(pMsg) - cfg.BindInfoConf.UnMarshalToMsg(pMsg) +func (cfg *UdpProxyConf) MarshalToMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.MarshalToMsg(pMsg) + cfg.BindInfoConf.MarshalToMsg(pMsg) } -func (cfg *UdpProxyConf) Check() (err error) { - err = cfg.BindInfoConf.check() - return -} +func (cfg *UdpProxyConf) CheckForCli() error { return nil } + +func (cfg *UdpProxyConf) CheckForSvr() error { return nil } // HTTP type HttpProxyConf struct { @@ -446,12 +428,11 @@ type HttpProxyConf struct { DomainConf LocalSvrConf - PluginConf Locations []string `json:"locations"` HostHeaderRewrite string `json:"host_header_rewrite"` - HttpUser string `json:"-"` - HttpPwd string `json:"-"` + HttpUser string `json:"http_user"` + HttpPwd string `json:"http_pwd"` } func (cfg *HttpProxyConf) Compare(cmp ProxyConf) bool { @@ -463,7 +444,6 @@ func (cfg *HttpProxyConf) Compare(cmp ProxyConf) bool { if !cfg.BaseProxyConf.compare(&cmpConf.BaseProxyConf) || !cfg.DomainConf.compare(&cmpConf.DomainConf) || !cfg.LocalSvrConf.compare(&cmpConf.LocalSvrConf) || - !cfg.PluginConf.compare(&cmpConf.PluginConf) || strings.Join(cfg.Locations, " ") != strings.Join(cmpConf.Locations, " ") || cfg.HostHeaderRewrite != cmpConf.HostHeaderRewrite || cfg.HttpUser != cmpConf.HttpUser || @@ -473,9 +453,9 @@ func (cfg *HttpProxyConf) Compare(cmp ProxyConf) bool { return true } -func (cfg *HttpProxyConf) LoadFromMsg(pMsg *msg.NewProxy) { - cfg.BaseProxyConf.LoadFromMsg(pMsg) - cfg.DomainConf.LoadFromMsg(pMsg) +func (cfg *HttpProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.UnmarshalFromMsg(pMsg) + cfg.DomainConf.UnmarshalFromMsg(pMsg) cfg.Locations = pMsg.Locations cfg.HostHeaderRewrite = pMsg.HostHeaderRewrite @@ -483,17 +463,15 @@ func (cfg *HttpProxyConf) LoadFromMsg(pMsg *msg.NewProxy) { cfg.HttpPwd = pMsg.HttpPwd } -func (cfg *HttpProxyConf) LoadFromFile(name string, section ini.Section) (err error) { - if err = cfg.BaseProxyConf.LoadFromFile(name, section); err != nil { +func (cfg *HttpProxyConf) UnmarshalFromIni(prefix string, name string, section ini.Section) (err error) { + if err = cfg.BaseProxyConf.UnmarshalFromIni(prefix, name, section); err != nil { return } - if err = cfg.DomainConf.LoadFromFile(name, section); err != nil { + if err = cfg.DomainConf.UnmarshalFromIni(prefix, name, section); err != nil { return } - if err = cfg.PluginConf.LoadFromFile(name, section); err != nil { - if err = cfg.LocalSvrConf.LoadFromFile(name, section); err != nil { - return - } + if err = cfg.LocalSvrConf.UnmarshalFromIni(prefix, name, section); err != nil { + return } var ( @@ -512,9 +490,9 @@ func (cfg *HttpProxyConf) LoadFromFile(name string, section ini.Section) (err er return } -func (cfg *HttpProxyConf) UnMarshalToMsg(pMsg *msg.NewProxy) { - cfg.BaseProxyConf.UnMarshalToMsg(pMsg) - cfg.DomainConf.UnMarshalToMsg(pMsg) +func (cfg *HttpProxyConf) MarshalToMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.MarshalToMsg(pMsg) + cfg.DomainConf.MarshalToMsg(pMsg) pMsg.Locations = cfg.Locations pMsg.HostHeaderRewrite = cfg.HostHeaderRewrite @@ -522,11 +500,20 @@ func (cfg *HttpProxyConf) UnMarshalToMsg(pMsg *msg.NewProxy) { pMsg.HttpPwd = cfg.HttpPwd } -func (cfg *HttpProxyConf) Check() (err error) { - if ServerCommonCfg.VhostHttpPort == 0 { - return fmt.Errorf("type [http] not support when vhost_http_port is not set") +func (cfg *HttpProxyConf) CheckForCli() (err error) { + if err = cfg.DomainConf.checkForCli(); err != nil { + return + } + return +} + +func (cfg *HttpProxyConf) CheckForSvr() (err error) { + if vhostHttpPort == 0 { + err = fmt.Errorf("type [http] not support when vhost_http_port is not set") + } + if err = cfg.DomainConf.checkForSvr(); err != nil { + return } - err = cfg.DomainConf.check() return } @@ -536,7 +523,6 @@ type HttpsProxyConf struct { DomainConf LocalSvrConf - PluginConf } func (cfg *HttpsProxyConf) Compare(cmp ProxyConf) bool { @@ -547,43 +533,49 @@ func (cfg *HttpsProxyConf) Compare(cmp ProxyConf) bool { if !cfg.BaseProxyConf.compare(&cmpConf.BaseProxyConf) || !cfg.DomainConf.compare(&cmpConf.DomainConf) || - !cfg.LocalSvrConf.compare(&cmpConf.LocalSvrConf) || - !cfg.PluginConf.compare(&cmpConf.PluginConf) { + !cfg.LocalSvrConf.compare(&cmpConf.LocalSvrConf) { return false } return true } -func (cfg *HttpsProxyConf) LoadFromMsg(pMsg *msg.NewProxy) { - cfg.BaseProxyConf.LoadFromMsg(pMsg) - cfg.DomainConf.LoadFromMsg(pMsg) +func (cfg *HttpsProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.UnmarshalFromMsg(pMsg) + cfg.DomainConf.UnmarshalFromMsg(pMsg) } -func (cfg *HttpsProxyConf) LoadFromFile(name string, section ini.Section) (err error) { - if err = cfg.BaseProxyConf.LoadFromFile(name, section); err != nil { +func (cfg *HttpsProxyConf) UnmarshalFromIni(prefix string, name string, section ini.Section) (err error) { + if err = cfg.BaseProxyConf.UnmarshalFromIni(prefix, name, section); err != nil { return } - if err = cfg.DomainConf.LoadFromFile(name, section); err != nil { + if err = cfg.DomainConf.UnmarshalFromIni(prefix, name, section); err != nil { return } - if err = cfg.PluginConf.LoadFromFile(name, section); err != nil { - if err = cfg.LocalSvrConf.LoadFromFile(name, section); err != nil { - return - } + if err = cfg.LocalSvrConf.UnmarshalFromIni(prefix, name, section); err != nil { + return } return } -func (cfg *HttpsProxyConf) UnMarshalToMsg(pMsg *msg.NewProxy) { - cfg.BaseProxyConf.UnMarshalToMsg(pMsg) - cfg.DomainConf.UnMarshalToMsg(pMsg) +func (cfg *HttpsProxyConf) MarshalToMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.MarshalToMsg(pMsg) + cfg.DomainConf.MarshalToMsg(pMsg) } -func (cfg *HttpsProxyConf) Check() (err error) { - if ServerCommonCfg.VhostHttpsPort == 0 { +func (cfg *HttpsProxyConf) CheckForCli() (err error) { + if err = cfg.DomainConf.checkForCli(); err != nil { + return + } + return +} + +func (cfg *HttpsProxyConf) CheckForSvr() (err error) { + if vhostHttpsPort == 0 { return fmt.Errorf("type [https] not support when vhost_https_port is not set") } - err = cfg.DomainConf.check() + if err = cfg.DomainConf.checkForSvr(); err != nil { + return + } return } @@ -596,7 +588,6 @@ type StcpProxyConf struct { // used in role server LocalSvrConf - PluginConf // used in role visitor ServerName string `json:"server_name"` @@ -612,7 +603,6 @@ func (cfg *StcpProxyConf) Compare(cmp ProxyConf) bool { if !cfg.BaseProxyConf.compare(&cmpConf.BaseProxyConf) || !cfg.LocalSvrConf.compare(&cmpConf.LocalSvrConf) || - !cfg.PluginConf.compare(&cmpConf.PluginConf) || cfg.Role != cmpConf.Role || cfg.Sk != cmpConf.Sk || cfg.ServerName != cmpConf.ServerName || @@ -624,13 +614,13 @@ func (cfg *StcpProxyConf) Compare(cmp ProxyConf) bool { } // Only for role server. -func (cfg *StcpProxyConf) LoadFromMsg(pMsg *msg.NewProxy) { - cfg.BaseProxyConf.LoadFromMsg(pMsg) +func (cfg *StcpProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.UnmarshalFromMsg(pMsg) cfg.Sk = pMsg.Sk } -func (cfg *StcpProxyConf) LoadFromFile(name string, section ini.Section) (err error) { - if err = cfg.BaseProxyConf.LoadFromFile(name, section); err != nil { +func (cfg *StcpProxyConf) UnmarshalFromIni(prefix string, name string, section ini.Section) (err error) { + if err = cfg.BaseProxyConf.UnmarshalFromIni(prefix, name, section); err != nil { return } @@ -661,21 +651,33 @@ func (cfg *StcpProxyConf) LoadFromFile(name string, section ini.Section) (err er return fmt.Errorf("Parse conf error: proxy [%s] bind_port not found", name) } } else { - if err = cfg.PluginConf.LoadFromFile(name, section); err != nil { - if err = cfg.LocalSvrConf.LoadFromFile(name, section); err != nil { - return - } + if err = cfg.LocalSvrConf.UnmarshalFromIni(prefix, name, section); err != nil { + return } } return } -func (cfg *StcpProxyConf) UnMarshalToMsg(pMsg *msg.NewProxy) { - cfg.BaseProxyConf.UnMarshalToMsg(pMsg) +func (cfg *StcpProxyConf) MarshalToMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.MarshalToMsg(pMsg) pMsg.Sk = cfg.Sk } -func (cfg *StcpProxyConf) Check() (err error) { +func (cfg *StcpProxyConf) CheckForCli() (err error) { + if cfg.Role != "server" && cfg.Role != "visitor" { + err = fmt.Errorf("role should be 'server' or 'visitor'") + return + } + if cfg.Role == "visitor" { + if cfg.BindAddr == "" { + err = fmt.Errorf("bind_addr shouldn't be empty") + return + } + } + return +} + +func (cfg *StcpProxyConf) CheckForSvr() (err error) { return } @@ -688,7 +690,6 @@ type XtcpProxyConf struct { // used in role server LocalSvrConf - PluginConf // used in role visitor ServerName string `json:"server_name"` @@ -704,7 +705,6 @@ func (cfg *XtcpProxyConf) Compare(cmp ProxyConf) bool { if !cfg.BaseProxyConf.compare(&cmpConf.BaseProxyConf) || !cfg.LocalSvrConf.compare(&cmpConf.LocalSvrConf) || - !cfg.PluginConf.compare(&cmpConf.PluginConf) || cfg.Role != cmpConf.Role || cfg.Sk != cmpConf.Sk || cfg.ServerName != cmpConf.ServerName || @@ -716,13 +716,13 @@ func (cfg *XtcpProxyConf) Compare(cmp ProxyConf) bool { } // Only for role server. -func (cfg *XtcpProxyConf) LoadFromMsg(pMsg *msg.NewProxy) { - cfg.BaseProxyConf.LoadFromMsg(pMsg) +func (cfg *XtcpProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.UnmarshalFromMsg(pMsg) cfg.Sk = pMsg.Sk } -func (cfg *XtcpProxyConf) LoadFromFile(name string, section ini.Section) (err error) { - if err = cfg.BaseProxyConf.LoadFromFile(name, section); err != nil { +func (cfg *XtcpProxyConf) UnmarshalFromIni(prefix string, name string, section ini.Section) (err error) { + if err = cfg.BaseProxyConf.UnmarshalFromIni(prefix, name, section); err != nil { return } @@ -753,21 +753,33 @@ func (cfg *XtcpProxyConf) LoadFromFile(name string, section ini.Section) (err er return fmt.Errorf("Parse conf error: proxy [%s] bind_port not found", name) } } else { - if err = cfg.PluginConf.LoadFromFile(name, section); err != nil { - if err = cfg.LocalSvrConf.LoadFromFile(name, section); err != nil { - return - } + if err = cfg.LocalSvrConf.UnmarshalFromIni(prefix, name, section); err != nil { + return } } return } -func (cfg *XtcpProxyConf) UnMarshalToMsg(pMsg *msg.NewProxy) { - cfg.BaseProxyConf.UnMarshalToMsg(pMsg) +func (cfg *XtcpProxyConf) MarshalToMsg(pMsg *msg.NewProxy) { + cfg.BaseProxyConf.MarshalToMsg(pMsg) pMsg.Sk = cfg.Sk } -func (cfg *XtcpProxyConf) Check() (err error) { +func (cfg *XtcpProxyConf) CheckForCli() (err error) { + if cfg.Role != "server" && cfg.Role != "visitor" { + err = fmt.Errorf("role should be 'server' or 'visitor'") + return + } + if cfg.Role == "visitor" { + if cfg.BindAddr == "" { + err = fmt.Errorf("bind_addr shouldn't be empty") + return + } + } + return +} + +func (cfg *XtcpProxyConf) CheckForSvr() (err error) { return } @@ -805,7 +817,7 @@ func ParseRangeSection(name string, section ini.Section) (sections map[string]in // if len(startProxy) is 0, start all // otherwise just start proxies in startProxy map -func LoadProxyConfFromFile(prefix string, conf ini.File, startProxy map[string]struct{}) ( +func LoadProxyConfFromIni(prefix string, conf ini.File, startProxy map[string]struct{}) ( proxyConfs map[string]ProxyConf, visitorConfs map[string]ProxyConf, err error) { if prefix != "" { @@ -842,9 +854,7 @@ func LoadProxyConfFromFile(prefix string, conf ini.File, startProxy map[string]s } for subName, subSection := range subSections { - // some proxy or visotr configure may be used this prefix - subSection["prefix"] = prefix - cfg, err := NewProxyConfFromFile(subName, subSection) + cfg, err := NewProxyConfFromIni(prefix, subName, subSection) if err != nil { return proxyConfs, visitorConfs, err } diff --git a/models/config/server_common.go b/models/config/server_common.go index 51880a7..20b37d8 100644 --- a/models/config/server_common.go +++ b/models/config/server_common.go @@ -24,49 +24,59 @@ import ( "github.com/fatedier/frp/utils/util" ) -var ServerCommonCfg *ServerCommonConf +var ( + // server global configure used for generate proxy conf used in frps + proxyBindAddr string + subDomainHost string + vhostHttpPort int + vhostHttpsPort int +) + +func InitServerCfg(cfg *ServerCommonConf) { + proxyBindAddr = cfg.ProxyBindAddr + subDomainHost = cfg.SubDomainHost + vhostHttpPort = cfg.VhostHttpPort + vhostHttpsPort = cfg.VhostHttpsPort +} // common config type ServerCommonConf struct { - ConfigFile string - BindAddr string - BindPort int - BindUdpPort int - KcpBindPort int - ProxyBindAddr string + BindAddr string `json:"bind_addr"` + BindPort int `json:"bind_port"` + BindUdpPort int `json:"bind_udp_port"` + KcpBindPort int `json:"kcp_bind_port"` + ProxyBindAddr string `json:"proxy_bind_addr"` // If VhostHttpPort equals 0, don't listen a public port for http protocol. - VhostHttpPort int + VhostHttpPort int `json:"vhost_http_port"` // if VhostHttpsPort equals 0, don't listen a public port for https protocol - VhostHttpsPort int - DashboardAddr string + VhostHttpsPort int `json:"vhost_http_port"` + DashboardAddr string `json:"dashboard_addr"` // if DashboardPort equals 0, dashboard is not available - DashboardPort int - DashboardUser string - DashboardPwd string - AssetsDir string - LogFile string - LogWay string // console or file - LogLevel string - LogMaxDays int64 - PrivilegeMode bool - PrivilegeToken string - AuthTimeout int64 - SubDomainHost string - TcpMux bool + DashboardPort int `json:"dashboard_port"` + DashboardUser string `json:"dashboard_user"` + DashboardPwd string `json:"dashboard_pwd"` + AssetsDir string `json:"asserts_dir"` + LogFile string `json:"log_file"` + LogWay string `json:"log_way"` // console or file + LogLevel string `json:"log_level"` + LogMaxDays int64 `json:"log_max_days"` + Token string `json:"token"` + AuthTimeout int64 `json:"auth_timeout"` + SubDomainHost string `json:"subdomain_host"` + TcpMux bool `json:"tcp_mux"` PrivilegeAllowPorts map[int]struct{} - MaxPoolCount int64 - MaxPortsPerClient int64 - HeartBeatTimeout int64 - UserConnTimeout int64 + MaxPoolCount int64 `json:"max_pool_count"` + MaxPortsPerClient int64 `json:"max_ports_per_client"` + HeartBeatTimeout int64 `json:"heart_beat_timeout"` + UserConnTimeout int64 `json:"user_conn_timeout"` } -func GetDefaultServerCommonConf() *ServerCommonConf { +func GetDefaultServerConf() *ServerCommonConf { return &ServerCommonConf{ - ConfigFile: "./frps.ini", BindAddr: "0.0.0.0", BindPort: 7000, BindUdpPort: 0, @@ -83,8 +93,7 @@ func GetDefaultServerCommonConf() *ServerCommonConf { LogWay: "console", LogLevel: "info", LogMaxDays: 3, - PrivilegeMode: true, - PrivilegeToken: "", + Token: "", AuthTimeout: 900, SubDomainHost: "", TcpMux: true, @@ -96,22 +105,28 @@ func GetDefaultServerCommonConf() *ServerCommonConf { } } -// Load server common configure. -func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) { +func UnmarshalServerConfFromIni(defaultCfg *ServerCommonConf, content string) (cfg *ServerCommonConf, err error) { + cfg = defaultCfg + if cfg == nil { + cfg = GetDefaultServerConf() + } + + conf, err := ini.Load(strings.NewReader(content)) + if err != nil { + err = fmt.Errorf("parse ini conf file error: %v", err) + return nil, err + } + var ( tmpStr string ok bool v int64 ) - cfg = GetDefaultServerCommonConf() - - tmpStr, ok = conf.Get("common", "bind_addr") - if ok { + if tmpStr, ok = conf.Get("common", "bind_addr"); ok { cfg.BindAddr = tmpStr } - tmpStr, ok = conf.Get("common", "bind_port") - if ok { + if tmpStr, ok = conf.Get("common", "bind_port"); ok { if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil { err = fmt.Errorf("Parse conf error: invalid bind_port") return @@ -120,8 +135,7 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) { } } - tmpStr, ok = conf.Get("common", "bind_udp_port") - if ok { + if tmpStr, ok = conf.Get("common", "bind_udp_port"); ok { if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil { err = fmt.Errorf("Parse conf error: invalid bind_udp_port") return @@ -130,8 +144,7 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) { } } - tmpStr, ok = conf.Get("common", "kcp_bind_port") - if ok { + if tmpStr, ok = conf.Get("common", "kcp_bind_port"); ok { if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil { err = fmt.Errorf("Parse conf error: invalid kcp_bind_port") return @@ -140,15 +153,13 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) { } } - tmpStr, ok = conf.Get("common", "proxy_bind_addr") - if ok { + if tmpStr, ok = conf.Get("common", "proxy_bind_addr"); ok { cfg.ProxyBindAddr = tmpStr } else { cfg.ProxyBindAddr = cfg.BindAddr } - tmpStr, ok = conf.Get("common", "vhost_http_port") - if ok { + if tmpStr, ok = conf.Get("common", "vhost_http_port"); ok { if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil { err = fmt.Errorf("Parse conf error: invalid vhost_http_port") return @@ -159,8 +170,7 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) { cfg.VhostHttpPort = 0 } - tmpStr, ok = conf.Get("common", "vhost_https_port") - if ok { + if tmpStr, ok = conf.Get("common", "vhost_https_port"); ok { if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil { err = fmt.Errorf("Parse conf error: invalid vhost_https_port") return @@ -171,15 +181,13 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) { cfg.VhostHttpsPort = 0 } - tmpStr, ok = conf.Get("common", "dashboard_addr") - if ok { + if tmpStr, ok = conf.Get("common", "dashboard_addr"); ok { cfg.DashboardAddr = tmpStr } else { cfg.DashboardAddr = cfg.BindAddr } - tmpStr, ok = conf.Get("common", "dashboard_port") - if ok { + if tmpStr, ok = conf.Get("common", "dashboard_port"); ok { if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil { err = fmt.Errorf("Parse conf error: invalid dashboard_port") return @@ -190,23 +198,19 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) { cfg.DashboardPort = 0 } - tmpStr, ok = conf.Get("common", "dashboard_user") - if ok { + if tmpStr, ok = conf.Get("common", "dashboard_user"); ok { cfg.DashboardUser = tmpStr } - tmpStr, ok = conf.Get("common", "dashboard_pwd") - if ok { + if tmpStr, ok = conf.Get("common", "dashboard_pwd"); ok { cfg.DashboardPwd = tmpStr } - tmpStr, ok = conf.Get("common", "assets_dir") - if ok { + if tmpStr, ok = conf.Get("common", "assets_dir"); ok { cfg.AssetsDir = tmpStr } - tmpStr, ok = conf.Get("common", "log_file") - if ok { + if tmpStr, ok = conf.Get("common", "log_file"); ok { cfg.LogFile = tmpStr if cfg.LogFile == "console" { cfg.LogWay = "console" @@ -215,47 +219,33 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) { } } - tmpStr, ok = conf.Get("common", "log_level") - if ok { + if tmpStr, ok = conf.Get("common", "log_level"); ok { cfg.LogLevel = tmpStr } - tmpStr, ok = conf.Get("common", "log_max_days") - if ok { + if tmpStr, ok = conf.Get("common", "log_max_days"); ok { v, err = strconv.ParseInt(tmpStr, 10, 64) if err == nil { cfg.LogMaxDays = v } } - tmpStr, ok = conf.Get("common", "privilege_mode") - if ok { - if tmpStr == "true" { - cfg.PrivilegeMode = true - } - } - - // PrivilegeMode configure - if cfg.PrivilegeMode == true { - cfg.PrivilegeToken, _ = conf.Get("common", "privilege_token") + cfg.Token, _ = conf.Get("common", "token") - allowPortsStr, ok := conf.Get("common", "privilege_allow_ports") - if ok { - // e.g. 1000-2000,2001,2002,3000-4000 - ports, errRet := util.ParseRangeNumbers(allowPortsStr) - if errRet != nil { - err = fmt.Errorf("Parse conf error: privilege_allow_ports: %v", errRet) - return - } + if allowPortsStr, ok := conf.Get("common", "privilege_allow_ports"); ok { + // e.g. 1000-2000,2001,2002,3000-4000 + ports, errRet := util.ParseRangeNumbers(allowPortsStr) + if errRet != nil { + err = fmt.Errorf("Parse conf error: privilege_allow_ports: %v", errRet) + return + } - for _, port := range ports { - cfg.PrivilegeAllowPorts[int(port)] = struct{}{} - } + for _, port := range ports { + cfg.PrivilegeAllowPorts[int(port)] = struct{}{} } } - tmpStr, ok = conf.Get("common", "max_pool_count") - if ok { + if tmpStr, ok = conf.Get("common", "max_pool_count"); ok { if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil { err = fmt.Errorf("Parse conf error: invalid max_pool_count") return @@ -268,8 +258,7 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) { } } - tmpStr, ok = conf.Get("common", "max_ports_per_client") - if ok { + if tmpStr, ok = conf.Get("common", "max_ports_per_client"); ok { if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil { err = fmt.Errorf("Parse conf error: invalid max_ports_per_client") return @@ -282,8 +271,7 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) { } } - tmpStr, ok = conf.Get("common", "authentication_timeout") - if ok { + if tmpStr, ok = conf.Get("common", "authentication_timeout"); ok { v, errRet := strconv.ParseInt(tmpStr, 10, 64) if errRet != nil { err = fmt.Errorf("Parse conf error: authentication_timeout is incorrect") @@ -293,20 +281,17 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) { } } - tmpStr, ok = conf.Get("common", "subdomain_host") - if ok { + if tmpStr, ok = conf.Get("common", "subdomain_host"); ok { cfg.SubDomainHost = strings.ToLower(strings.TrimSpace(tmpStr)) } - tmpStr, ok = conf.Get("common", "tcp_mux") - if ok && tmpStr == "false" { + if tmpStr, ok = conf.Get("common", "tcp_mux"); ok && tmpStr == "false" { cfg.TcpMux = false } else { cfg.TcpMux = true } - tmpStr, ok = conf.Get("common", "heartbeat_timeout") - if ok { + if tmpStr, ok = conf.Get("common", "heartbeat_timeout"); ok { v, errRet := strconv.ParseInt(tmpStr, 10, 64) if errRet != nil { err = fmt.Errorf("Parse conf error: heartbeat_timeout is incorrect") @@ -317,3 +302,7 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) { } return } + +func (cfg *ServerCommonConf) Check() (err error) { + return +} diff --git a/server/control.go b/server/control.go index d7938e7..0739f95 100644 --- a/server/control.go +++ b/server/control.go @@ -20,6 +20,7 @@ import ( "sync" "time" + "github.com/fatedier/frp/g" "github.com/fatedier/frp/models/config" "github.com/fatedier/frp/models/consts" "github.com/fatedier/frp/models/msg" @@ -103,7 +104,7 @@ func (ctl *Control) Start() { loginRespMsg := &msg.LoginResp{ Version: version.Full(), RunId: ctl.runId, - ServerUdpPort: config.ServerCommonCfg.BindUdpPort, + ServerUdpPort: g.GlbServerCfg.BindUdpPort, Error: "", } msg.WriteMsg(ctl.conn, loginRespMsg) @@ -172,7 +173,7 @@ func (ctl *Control) GetWorkConn() (workConn net.Conn, err error) { return } - case <-time.After(time.Duration(config.ServerCommonCfg.UserConnTimeout) * time.Second): + case <-time.After(time.Duration(g.GlbServerCfg.UserConnTimeout) * time.Second): err = fmt.Errorf("timeout trying to get work connection") ctl.conn.Warn("%v", err) return @@ -202,7 +203,7 @@ func (ctl *Control) writer() { defer ctl.allShutdown.Start() defer ctl.writerShutdown.Done() - encWriter, err := crypto.NewWriter(ctl.conn, []byte(config.ServerCommonCfg.PrivilegeToken)) + encWriter, err := crypto.NewWriter(ctl.conn, []byte(g.GlbServerCfg.Token)) if err != nil { ctl.conn.Error("crypto new writer error: %v", err) ctl.allShutdown.Start() @@ -231,7 +232,7 @@ func (ctl *Control) reader() { defer ctl.allShutdown.Start() defer ctl.readerShutdown.Done() - encReader := crypto.NewReader(ctl.conn, []byte(config.ServerCommonCfg.PrivilegeToken)) + encReader := crypto.NewReader(ctl.conn, []byte(g.GlbServerCfg.Token)) for { if m, err := msg.ReadMsg(encReader); err != nil { if err == io.EOF { @@ -301,7 +302,7 @@ func (ctl *Control) manager() { for { select { case <-heartbeat.C: - if time.Since(ctl.lastPing) > time.Duration(config.ServerCommonCfg.HeartBeatTimeout)*time.Second { + if time.Since(ctl.lastPing) > time.Duration(g.GlbServerCfg.HeartBeatTimeout)*time.Second { ctl.conn.Warn("heartbeat timeout") ctl.allShutdown.Start() return @@ -342,7 +343,7 @@ func (ctl *Control) manager() { func (ctl *Control) RegisterProxy(pxyMsg *msg.NewProxy) (remoteAddr string, err error) { var pxyConf config.ProxyConf // Load configures from NewProxy message and check. - pxyConf, err = config.NewProxyConf(pxyMsg) + pxyConf, err = config.NewProxyConfFromMsg(pxyMsg) if err != nil { return } @@ -355,9 +356,9 @@ func (ctl *Control) RegisterProxy(pxyMsg *msg.NewProxy) (remoteAddr string, err } // Check ports used number in each client - if config.ServerCommonCfg.MaxPortsPerClient > 0 { + if g.GlbServerCfg.MaxPortsPerClient > 0 { ctl.mu.Lock() - if ctl.portsUsedNum+pxy.GetUsedPortsNum() > int(config.ServerCommonCfg.MaxPortsPerClient) { + if ctl.portsUsedNum+pxy.GetUsedPortsNum() > int(g.GlbServerCfg.MaxPortsPerClient) { ctl.mu.Unlock() err = fmt.Errorf("exceed the max_ports_per_client") return @@ -404,7 +405,7 @@ func (ctl *Control) CloseProxy(closeMsg *msg.CloseProxy) (err error) { return } - if config.ServerCommonCfg.MaxPortsPerClient > 0 { + if g.GlbServerCfg.MaxPortsPerClient > 0 { ctl.portsUsedNum = ctl.portsUsedNum - pxy.GetUsedPortsNum() } pxy.Close() diff --git a/server/dashboard.go b/server/dashboard.go index 3c77875..75fd5d7 100644 --- a/server/dashboard.go +++ b/server/dashboard.go @@ -21,7 +21,7 @@ import ( "time" "github.com/fatedier/frp/assets" - "github.com/fatedier/frp/models/config" + "github.com/fatedier/frp/g" frpNet "github.com/fatedier/frp/utils/net" "github.com/julienschmidt/httprouter" @@ -36,7 +36,7 @@ func RunDashboardServer(addr string, port int) (err error) { // url router router := httprouter.New() - user, passwd := config.ServerCommonCfg.DashboardUser, config.ServerCommonCfg.DashboardPwd + user, passwd := g.GlbServerCfg.DashboardUser, g.GlbServerCfg.DashboardPwd // api, see dashboard_api.go router.GET("/api/serverinfo", frpNet.HttprouterBasicAuth(apiServerInfo, user, passwd)) diff --git a/server/dashboard_api.go b/server/dashboard_api.go index 3f9acd0..99aa62d 100644 --- a/server/dashboard_api.go +++ b/server/dashboard_api.go @@ -18,6 +18,7 @@ import ( "encoding/json" "net/http" + "github.com/fatedier/frp/g" "github.com/fatedier/frp/models/config" "github.com/fatedier/frp/models/consts" "github.com/fatedier/frp/utils/log" @@ -60,7 +61,7 @@ func apiServerInfo(w http.ResponseWriter, r *http.Request, _ httprouter.Params) }() log.Info("Http request: [/api/serverinfo]") - cfg := config.ServerCommonCfg + cfg := &g.GlbServerCfg.ServerCommonConf serverStats := StatsGetServer() res = ServerInfoResp{ Version: version.Full(), diff --git a/server/metric.go b/server/metric.go index 0e1680c..3c135e7 100644 --- a/server/metric.go +++ b/server/metric.go @@ -18,7 +18,7 @@ import ( "sync" "time" - "github.com/fatedier/frp/models/config" + "github.com/fatedier/frp/g" "github.com/fatedier/frp/utils/log" "github.com/fatedier/frp/utils/metric" ) @@ -92,19 +92,19 @@ func StatsClearUselessInfo() { } func StatsNewClient() { - if config.ServerCommonCfg.DashboardPort != 0 { + if g.GlbServerCfg.DashboardPort != 0 { globalStats.ClientCounts.Inc(1) } } func StatsCloseClient() { - if config.ServerCommonCfg.DashboardPort != 0 { + if g.GlbServerCfg.DashboardPort != 0 { globalStats.ClientCounts.Dec(1) } } func StatsNewProxy(name string, proxyType string) { - if config.ServerCommonCfg.DashboardPort != 0 { + if g.GlbServerCfg.DashboardPort != 0 { globalStats.mu.Lock() defer globalStats.mu.Unlock() counter, ok := globalStats.ProxyTypeCounts[proxyType] @@ -130,7 +130,7 @@ func StatsNewProxy(name string, proxyType string) { } func StatsCloseProxy(proxyName string, proxyType string) { - if config.ServerCommonCfg.DashboardPort != 0 { + if g.GlbServerCfg.DashboardPort != 0 { globalStats.mu.Lock() defer globalStats.mu.Unlock() if counter, ok := globalStats.ProxyTypeCounts[proxyType]; ok { @@ -143,7 +143,7 @@ func StatsCloseProxy(proxyName string, proxyType string) { } func StatsOpenConnection(name string) { - if config.ServerCommonCfg.DashboardPort != 0 { + if g.GlbServerCfg.DashboardPort != 0 { globalStats.CurConns.Inc(1) globalStats.mu.Lock() @@ -157,7 +157,7 @@ func StatsOpenConnection(name string) { } func StatsCloseConnection(name string) { - if config.ServerCommonCfg.DashboardPort != 0 { + if g.GlbServerCfg.DashboardPort != 0 { globalStats.CurConns.Dec(1) globalStats.mu.Lock() @@ -171,7 +171,7 @@ func StatsCloseConnection(name string) { } func StatsAddTrafficIn(name string, trafficIn int64) { - if config.ServerCommonCfg.DashboardPort != 0 { + if g.GlbServerCfg.DashboardPort != 0 { globalStats.TotalTrafficIn.Inc(trafficIn) globalStats.mu.Lock() @@ -186,7 +186,7 @@ func StatsAddTrafficIn(name string, trafficIn int64) { } func StatsAddTrafficOut(name string, trafficOut int64) { - if config.ServerCommonCfg.DashboardPort != 0 { + if g.GlbServerCfg.DashboardPort != 0 { globalStats.TotalTrafficOut.Inc(trafficOut) globalStats.mu.Lock() diff --git a/server/proxy.go b/server/proxy.go index 715bf0c..a0620c9 100644 --- a/server/proxy.go +++ b/server/proxy.go @@ -23,6 +23,7 @@ import ( "sync" "time" + "github.com/fatedier/frp/g" "github.com/fatedier/frp/models/config" "github.com/fatedier/frp/models/msg" "github.com/fatedier/frp/models/proto/udp" @@ -126,7 +127,7 @@ func (pxy *BaseProxy) startListenHandler(p Proxy, handler func(Proxy, frpNet.Con func NewProxy(ctl *Control, pxyConf config.ProxyConf) (pxy Proxy, err error) { basePxy := BaseProxy{ - name: pxyConf.GetName(), + name: pxyConf.GetBaseInfo().ProxyName, ctl: ctl, listeners: make([]frpNet.Listener, 0), Logger: log.NewPrefixLogger(ctl.runId), @@ -191,7 +192,7 @@ func (pxy *TcpProxy) Run() (remoteAddr string, err error) { remoteAddr = fmt.Sprintf(":%d", pxy.realPort) pxy.cfg.RemotePort = pxy.realPort - listener, errRet := frpNet.ListenTcp(config.ServerCommonCfg.ProxyBindAddr, pxy.realPort) + listener, errRet := frpNet.ListenTcp(g.GlbServerCfg.ProxyBindAddr, pxy.realPort) if errRet != nil { err = errRet return @@ -244,7 +245,7 @@ func (pxy *HttpProxy) Run() (remoteAddr string, err error) { } tmpDomain := routeConfig.Domain tmpLocation := routeConfig.Location - addrs = append(addrs, util.CanonicalAddr(tmpDomain, int(config.ServerCommonCfg.VhostHttpPort))) + addrs = append(addrs, util.CanonicalAddr(tmpDomain, int(g.GlbServerCfg.VhostHttpPort))) pxy.closeFuncs = append(pxy.closeFuncs, func() { pxy.ctl.svr.httpReverseProxy.UnRegister(tmpDomain, tmpLocation) }) @@ -253,7 +254,7 @@ func (pxy *HttpProxy) Run() (remoteAddr string, err error) { } if pxy.cfg.SubDomain != "" { - routeConfig.Domain = pxy.cfg.SubDomain + "." + config.ServerCommonCfg.SubDomainHost + routeConfig.Domain = pxy.cfg.SubDomain + "." + g.GlbServerCfg.SubDomainHost for _, location := range locations { routeConfig.Location = location err = pxy.ctl.svr.httpReverseProxy.Register(routeConfig) @@ -262,7 +263,7 @@ func (pxy *HttpProxy) Run() (remoteAddr string, err error) { } tmpDomain := routeConfig.Domain tmpLocation := routeConfig.Location - addrs = append(addrs, util.CanonicalAddr(tmpDomain, int(config.ServerCommonCfg.VhostHttpPort))) + addrs = append(addrs, util.CanonicalAddr(tmpDomain, g.GlbServerCfg.VhostHttpPort)) pxy.closeFuncs = append(pxy.closeFuncs, func() { pxy.ctl.svr.httpReverseProxy.UnRegister(tmpDomain, tmpLocation) }) @@ -286,7 +287,7 @@ func (pxy *HttpProxy) GetRealConn() (workConn frpNet.Conn, err error) { var rwc io.ReadWriteCloser = tmpConn if pxy.cfg.UseEncryption { - rwc, err = frpIo.WithEncryption(rwc, []byte(config.ServerCommonCfg.PrivilegeToken)) + rwc, err = frpIo.WithEncryption(rwc, []byte(g.GlbServerCfg.Token)) if err != nil { pxy.Error("create encryption stream error: %v", err) return @@ -334,11 +335,11 @@ func (pxy *HttpsProxy) Run() (remoteAddr string, err error) { l.AddLogPrefix(pxy.name) pxy.Info("https proxy listen for host [%s]", routeConfig.Domain) pxy.listeners = append(pxy.listeners, l) - addrs = append(addrs, util.CanonicalAddr(routeConfig.Domain, int(config.ServerCommonCfg.VhostHttpsPort))) + addrs = append(addrs, util.CanonicalAddr(routeConfig.Domain, g.GlbServerCfg.VhostHttpsPort)) } if pxy.cfg.SubDomain != "" { - routeConfig.Domain = pxy.cfg.SubDomain + "." + config.ServerCommonCfg.SubDomainHost + routeConfig.Domain = pxy.cfg.SubDomain + "." + g.GlbServerCfg.SubDomainHost l, errRet := pxy.ctl.svr.VhostHttpsMuxer.Listen(routeConfig) if errRet != nil { err = errRet @@ -347,7 +348,7 @@ func (pxy *HttpsProxy) Run() (remoteAddr string, err error) { l.AddLogPrefix(pxy.name) pxy.Info("https proxy listen for host [%s]", routeConfig.Domain) pxy.listeners = append(pxy.listeners, l) - addrs = append(addrs, util.CanonicalAddr(routeConfig.Domain, int(config.ServerCommonCfg.VhostHttpsPort))) + addrs = append(addrs, util.CanonicalAddr(routeConfig.Domain, int(g.GlbServerCfg.VhostHttpsPort))) } pxy.startListenHandler(pxy, HandleUserTcpConnection) @@ -478,7 +479,7 @@ func (pxy *UdpProxy) Run() (remoteAddr string, err error) { remoteAddr = fmt.Sprintf(":%d", pxy.realPort) pxy.cfg.RemotePort = pxy.realPort - addr, errRet := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", config.ServerCommonCfg.ProxyBindAddr, pxy.realPort)) + addr, errRet := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", g.GlbServerCfg.ProxyBindAddr, pxy.realPort)) if errRet != nil { err = errRet return @@ -644,7 +645,7 @@ func HandleUserTcpConnection(pxy Proxy, userConn frpNet.Conn) { var local io.ReadWriteCloser = workConn cfg := pxy.GetConf().GetBaseInfo() if cfg.UseEncryption { - local, err = frpIo.WithEncryption(local, []byte(config.ServerCommonCfg.PrivilegeToken)) + local, err = frpIo.WithEncryption(local, []byte(g.GlbServerCfg.Token)) if err != nil { pxy.Error("create encryption stream error: %v", err) return diff --git a/server/service.go b/server/service.go index e976658..82b1a35 100644 --- a/server/service.go +++ b/server/service.go @@ -21,7 +21,7 @@ import ( "time" "github.com/fatedier/frp/assets" - "github.com/fatedier/frp/models/config" + "github.com/fatedier/frp/g" "github.com/fatedier/frp/models/msg" "github.com/fatedier/frp/utils/log" frpNet "github.com/fatedier/frp/utils/net" @@ -71,7 +71,7 @@ type Service struct { } func NewService() (svr *Service, err error) { - cfg := config.ServerCommonCfg + cfg := &g.GlbServerCfg.ServerCommonConf svr = &Service{ ctlManager: NewControlManager(), pxyManager: NewProxyManager(), @@ -170,7 +170,7 @@ func (svr *Service) Run() { if svr.natHoleController != nil { go svr.natHoleController.Run() } - if config.ServerCommonCfg.KcpBindPort > 0 { + if g.GlbServerCfg.KcpBindPort > 0 { go svr.HandleListener(svr.kcpListener) } svr.HandleListener(svr.listener) @@ -233,7 +233,7 @@ func (svr *Service) HandleListener(l frpNet.Listener) { } } - if config.ServerCommonCfg.TcpMux { + if g.GlbServerCfg.TcpMux { session, err := smux.Server(frpConn, nil) if err != nil { log.Warn("Failed to create mux connection: %v", err) @@ -270,11 +270,11 @@ func (svr *Service) RegisterControl(ctlConn frpNet.Conn, loginMsg *msg.Login) (e // Check auth. nowTime := time.Now().Unix() - if config.ServerCommonCfg.AuthTimeout != 0 && nowTime-loginMsg.Timestamp > config.ServerCommonCfg.AuthTimeout { + if g.GlbServerCfg.AuthTimeout != 0 && nowTime-loginMsg.Timestamp > g.GlbServerCfg.AuthTimeout { err = fmt.Errorf("authorization timeout") return } - if util.GetAuthKey(config.ServerCommonCfg.PrivilegeToken, loginMsg.Timestamp) != loginMsg.PrivilegeKey { + if util.GetAuthKey(g.GlbServerCfg.Token, loginMsg.Timestamp) != loginMsg.PrivilegeKey { err = fmt.Errorf("authorization failed") return } diff --git a/tests/conf/auto_test_frpc.ini b/tests/conf/auto_test_frpc.ini index 9376990..0ada325 100644 --- a/tests/conf/auto_test_frpc.ini +++ b/tests/conf/auto_test_frpc.ini @@ -4,7 +4,7 @@ server_port = 10700 log_file = ./frpc.log # debug, info, warn, error log_level = debug -privilege_token = 123456 +token = 123456 admin_port = 10600 admin_user = abc admin_pwd = abc diff --git a/tests/conf/auto_test_frpc_visitor.ini b/tests/conf/auto_test_frpc_visitor.ini index cc524de..e06d160 100644 --- a/tests/conf/auto_test_frpc_visitor.ini +++ b/tests/conf/auto_test_frpc_visitor.ini @@ -4,7 +4,7 @@ server_port = 10700 log_file = ./frpc_visitor.log # debug, info, warn, error log_level = debug -privilege_token = 123456 +token = 123456 [stcp_visitor] type = stcp diff --git a/tests/conf/auto_test_frps.ini b/tests/conf/auto_test_frps.ini index f59b8a3..193a108 100644 --- a/tests/conf/auto_test_frps.ini +++ b/tests/conf/auto_test_frps.ini @@ -4,6 +4,6 @@ bind_port = 10700 vhost_http_port = 10804 log_file = ./frps.log log_level = debug -privilege_token = 123456 +token = 123456 privilege_allow_ports = 10000-20000,20002,30000-50000 subdomain_host = sub.com diff --git a/utils/version/version.go b/utils/version/version.go index 5c901e7..8e46803 100644 --- a/utils/version/version.go +++ b/utils/version/version.go @@ -19,7 +19,7 @@ import ( "strings" ) -var version string = "0.16.1" +var version string = "0.17.0" func Full() string { return version diff --git a/vendor/github.com/fatedier/beego/controller.go b/vendor/github.com/fatedier/beego/controller.go index 488ffcd..d341ea8 100644 --- a/vendor/github.com/fatedier/beego/controller.go +++ b/vendor/github.com/fatedier/beego/controller.go @@ -223,7 +223,7 @@ func (c *Controller) RenderBytes() ([]byte, error) { } buf.Reset() - ExecuteViewPathTemplate(&buf, c.Layout, c.viewPath() ,c.Data) + ExecuteViewPathTemplate(&buf, c.Layout, c.viewPath(), c.Data) } return buf.Bytes(), err } @@ -249,7 +249,7 @@ func (c *Controller) renderTemplate() (bytes.Buffer, error) { } } } - BuildTemplate(c.viewPath() , buildFiles...) + BuildTemplate(c.viewPath(), buildFiles...) } return buf, ExecuteViewPathTemplate(&buf, c.TplName, c.viewPath(), c.Data) } diff --git a/vendor/github.com/fatedier/beego/controller_test.go b/vendor/github.com/fatedier/beego/controller_test.go index c202586..1e53416 100644 --- a/vendor/github.com/fatedier/beego/controller_test.go +++ b/vendor/github.com/fatedier/beego/controller_test.go @@ -172,10 +172,10 @@ func TestAdditionalViewPaths(t *testing.T) { t.Fatal("TestAdditionalViewPaths expected error") } }() - ctrl.RenderString(); + ctrl.RenderString() }() ctrl.TplName = "file2.tpl" ctrl.ViewPath = dir2 - ctrl.RenderString(); + ctrl.RenderString() } diff --git a/vendor/github.com/fatedier/beego/logs/alils/signature.go b/vendor/github.com/fatedier/beego/logs/alils/signature.go index e0e4b3f..c96aeb9 100755 --- a/vendor/github.com/fatedier/beego/logs/alils/signature.go +++ b/vendor/github.com/fatedier/beego/logs/alils/signature.go @@ -109,4 +109,3 @@ func signature(project *LogProject, method, uri string, digest = base64.StdEncoding.EncodeToString(mac.Sum(nil)) return } - diff --git a/vendor/github.com/fatedier/beego/orm/db.go b/vendor/github.com/fatedier/beego/orm/db.go index bca6071..6e97ab1 100644 --- a/vendor/github.com/fatedier/beego/orm/db.go +++ b/vendor/github.com/fatedier/beego/orm/db.go @@ -48,7 +48,7 @@ var ( "lte": true, "eq": true, "nq": true, - "ne": true, + "ne": true, "startswith": true, "endswith": true, "istartswith": true, diff --git a/vendor/github.com/fatedier/beego/template.go b/vendor/github.com/fatedier/beego/template.go index 17c1859..ffd4df4 100644 --- a/vendor/github.com/fatedier/beego/template.go +++ b/vendor/github.com/fatedier/beego/template.go @@ -31,11 +31,11 @@ import ( ) var ( - beegoTplFuncMap = make(template.FuncMap) + beegoTplFuncMap = make(template.FuncMap) beeViewPathTemplateLocked = false // beeViewPathTemplates caching map and supported template file extensions per view - beeViewPathTemplates = make(map[string]map[string]*template.Template) - templatesLock sync.RWMutex + beeViewPathTemplates = make(map[string]map[string]*template.Template) + templatesLock sync.RWMutex // beeTemplateExt stores the template extension which will build beeTemplateExt = []string{"tpl", "html"} // beeTemplatePreprocessors stores associations of extension -> preprocessor handler @@ -46,7 +46,7 @@ var ( // writing the output to wr. // A template will be executed safely in parallel. func ExecuteTemplate(wr io.Writer, name string, data interface{}) error { - return ExecuteViewPathTemplate(wr,name, BConfig.WebConfig.ViewsPath, data) + return ExecuteViewPathTemplate(wr, name, BConfig.WebConfig.ViewsPath, data) } // ExecuteViewPathTemplate applies the template with name and from specific viewPath to the specified data object, @@ -57,7 +57,7 @@ func ExecuteViewPathTemplate(wr io.Writer, name string, viewPath string, data in templatesLock.RLock() defer templatesLock.RUnlock() } - if beeTemplates,ok := beeViewPathTemplates[viewPath]; ok { + if beeTemplates, ok := beeViewPathTemplates[viewPath]; ok { if t, ok := beeTemplates[name]; ok { var err error if t.Lookup(name) != nil { @@ -160,9 +160,9 @@ func AddTemplateExt(ext string) { beeTemplateExt = append(beeTemplateExt, ext) } -// AddViewPath adds a new path to the supported view paths. +// AddViewPath adds a new path to the supported view paths. //Can later be used by setting a controller ViewPath to this folder -//will panic if called after beego.Run() +//will panic if called after beego.Run() func AddViewPath(viewPath string) error { if beeViewPathTemplateLocked { panic("Can not add new view paths after beego.Run()") @@ -184,7 +184,7 @@ func BuildTemplate(dir string, files ...string) error { } return errors.New("dir open err") } - beeTemplates,ok := beeViewPathTemplates[dir]; + beeTemplates, ok := beeViewPathTemplates[dir] if !ok { panic("Unknown view path: " + dir) } diff --git a/vendor/github.com/fatedier/beego/toolbox/statistics.go b/vendor/github.com/fatedier/beego/toolbox/statistics.go index c6a9489..d014544 100644 --- a/vendor/github.com/fatedier/beego/toolbox/statistics.go +++ b/vendor/github.com/fatedier/beego/toolbox/statistics.go @@ -119,7 +119,7 @@ func (m *URLMap) GetMap() map[string]interface{} { func (m *URLMap) GetMapData() []map[string]interface{} { m.lock.Lock() defer m.lock.Unlock() - + var resultLists []map[string]interface{} for k, v := range m.urlmap { diff --git a/vendor/github.com/klauspost/cpuid/private/cpuid.go b/vendor/github.com/klauspost/cpuid/private/cpuid.go index be99cb0..56c26c4 100644 --- a/vendor/github.com/klauspost/cpuid/private/cpuid.go +++ b/vendor/github.com/klauspost/cpuid/private/cpuid.go @@ -12,146 +12,146 @@ import ( type vendor int const ( - other vendor = iota + other vendor = iota intel amd via transmeta nsc - kvm // Kernel-based Virtual Machine - msvm // Microsoft Hyper-V or Windows Virtual PC + kvm // Kernel-based Virtual Machine + msvm // Microsoft Hyper-V or Windows Virtual PC vmware xenhvm ) const ( - cmov = 1 << iota // i686 CMOV - nx // NX (No-Execute) bit - amd3dnow // AMD 3DNOW - amd3dnowext // AMD 3DNowExt - mmx // standard MMX - mmxext // SSE integer functions or AMD MMX ext - sse // SSE functions - sse2 // P4 SSE functions - sse3 // Prescott SSE3 functions - ssse3 // Conroe SSSE3 functions - sse4 // Penryn SSE4.1 functions - sse4a // AMD Barcelona microarchitecture SSE4a instructions - sse42 // Nehalem SSE4.2 functions - avx // AVX functions - avx2 // AVX2 functions - fma3 // Intel FMA 3 - fma4 // Bulldozer FMA4 functions - xop // Bulldozer XOP functions - f16c // Half-precision floating-point conversion - bmi1 // Bit Manipulation Instruction Set 1 - bmi2 // Bit Manipulation Instruction Set 2 - tbm // AMD Trailing Bit Manipulation - lzcnt // LZCNT instruction - popcnt // POPCNT instruction - aesni // Advanced Encryption Standard New Instructions - clmul // Carry-less Multiplication - htt // Hyperthreading (enabled) - hle // Hardware Lock Elision - rtm // Restricted Transactional Memory - rdrand // RDRAND instruction is available - rdseed // RDSEED instruction is available - adx // Intel ADX (Multi-Precision Add-Carry Instruction Extensions) - sha // Intel SHA Extensions - avx512f // AVX-512 Foundation - avx512dq // AVX-512 Doubleword and Quadword Instructions - avx512ifma // AVX-512 Integer Fused Multiply-Add Instructions - avx512pf // AVX-512 Prefetch Instructions - avx512er // AVX-512 Exponential and Reciprocal Instructions - avx512cd // AVX-512 Conflict Detection Instructions - avx512bw // AVX-512 Byte and Word Instructions - avx512vl // AVX-512 Vector Length Extensions - avx512vbmi // AVX-512 Vector Bit Manipulation Instructions - mpx // Intel MPX (Memory Protection Extensions) - erms // Enhanced REP MOVSB/STOSB - rdtscp // RDTSCP Instruction - cx16 // CMPXCHG16B Instruction + cmov = 1 << iota // i686 CMOV + nx // NX (No-Execute) bit + amd3dnow // AMD 3DNOW + amd3dnowext // AMD 3DNowExt + mmx // standard MMX + mmxext // SSE integer functions or AMD MMX ext + sse // SSE functions + sse2 // P4 SSE functions + sse3 // Prescott SSE3 functions + ssse3 // Conroe SSSE3 functions + sse4 // Penryn SSE4.1 functions + sse4a // AMD Barcelona microarchitecture SSE4a instructions + sse42 // Nehalem SSE4.2 functions + avx // AVX functions + avx2 // AVX2 functions + fma3 // Intel FMA 3 + fma4 // Bulldozer FMA4 functions + xop // Bulldozer XOP functions + f16c // Half-precision floating-point conversion + bmi1 // Bit Manipulation Instruction Set 1 + bmi2 // Bit Manipulation Instruction Set 2 + tbm // AMD Trailing Bit Manipulation + lzcnt // LZCNT instruction + popcnt // POPCNT instruction + aesni // Advanced Encryption Standard New Instructions + clmul // Carry-less Multiplication + htt // Hyperthreading (enabled) + hle // Hardware Lock Elision + rtm // Restricted Transactional Memory + rdrand // RDRAND instruction is available + rdseed // RDSEED instruction is available + adx // Intel ADX (Multi-Precision Add-Carry Instruction Extensions) + sha // Intel SHA Extensions + avx512f // AVX-512 Foundation + avx512dq // AVX-512 Doubleword and Quadword Instructions + avx512ifma // AVX-512 Integer Fused Multiply-Add Instructions + avx512pf // AVX-512 Prefetch Instructions + avx512er // AVX-512 Exponential and Reciprocal Instructions + avx512cd // AVX-512 Conflict Detection Instructions + avx512bw // AVX-512 Byte and Word Instructions + avx512vl // AVX-512 Vector Length Extensions + avx512vbmi // AVX-512 Vector Bit Manipulation Instructions + mpx // Intel MPX (Memory Protection Extensions) + erms // Enhanced REP MOVSB/STOSB + rdtscp // RDTSCP Instruction + cx16 // CMPXCHG16B Instruction // Performance indicators - sse2slow // SSE2 is supported, but usually not faster - sse3slow // SSE3 is supported, but usually not faster - atom // Atom processor, some SSSE3 instructions are slower + sse2slow // SSE2 is supported, but usually not faster + sse3slow // SSE3 is supported, but usually not faster + atom // Atom processor, some SSSE3 instructions are slower ) var flagNames = map[flags]string{ - cmov: "CMOV", // i686 CMOV - nx: "NX", // NX (No-Execute) bit - amd3dnow: "AMD3DNOW", // AMD 3DNOW - amd3dnowext: "AMD3DNOWEXT", // AMD 3DNowExt - mmx: "MMX", // Standard MMX - mmxext: "MMXEXT", // SSE integer functions or AMD MMX ext - sse: "SSE", // SSE functions - sse2: "SSE2", // P4 SSE2 functions - sse3: "SSE3", // Prescott SSE3 functions - ssse3: "SSSE3", // Conroe SSSE3 functions - sse4: "SSE4.1", // Penryn SSE4.1 functions - sse4a: "SSE4A", // AMD Barcelona microarchitecture SSE4a instructions - sse42: "SSE4.2", // Nehalem SSE4.2 functions - avx: "AVX", // AVX functions - avx2: "AVX2", // AVX functions - fma3: "FMA3", // Intel FMA 3 - fma4: "FMA4", // Bulldozer FMA4 functions - xop: "XOP", // Bulldozer XOP functions - f16c: "F16C", // Half-precision floating-point conversion - bmi1: "BMI1", // Bit Manipulation Instruction Set 1 - bmi2: "BMI2", // Bit Manipulation Instruction Set 2 - tbm: "TBM", // AMD Trailing Bit Manipulation - lzcnt: "LZCNT", // LZCNT instruction - popcnt: "POPCNT", // POPCNT instruction - aesni: "AESNI", // Advanced Encryption Standard New Instructions - clmul: "CLMUL", // Carry-less Multiplication - htt: "HTT", // Hyperthreading (enabled) - hle: "HLE", // Hardware Lock Elision - rtm: "RTM", // Restricted Transactional Memory - rdrand: "RDRAND", // RDRAND instruction is available - rdseed: "RDSEED", // RDSEED instruction is available - adx: "ADX", // Intel ADX (Multi-Precision Add-Carry Instruction Extensions) - sha: "SHA", // Intel SHA Extensions - avx512f: "AVX512F", // AVX-512 Foundation - avx512dq: "AVX512DQ", // AVX-512 Doubleword and Quadword Instructions - avx512ifma: "AVX512IFMA", // AVX-512 Integer Fused Multiply-Add Instructions - avx512pf: "AVX512PF", // AVX-512 Prefetch Instructions - avx512er: "AVX512ER", // AVX-512 Exponential and Reciprocal Instructions - avx512cd: "AVX512CD", // AVX-512 Conflict Detection Instructions - avx512bw: "AVX512BW", // AVX-512 Byte and Word Instructions - avx512vl: "AVX512VL", // AVX-512 Vector Length Extensions - avx512vbmi: "AVX512VBMI", // AVX-512 Vector Bit Manipulation Instructions - mpx: "MPX", // Intel MPX (Memory Protection Extensions) - erms: "ERMS", // Enhanced REP MOVSB/STOSB - rdtscp: "RDTSCP", // RDTSCP Instruction - cx16: "CX16", // CMPXCHG16B Instruction + cmov: "CMOV", // i686 CMOV + nx: "NX", // NX (No-Execute) bit + amd3dnow: "AMD3DNOW", // AMD 3DNOW + amd3dnowext: "AMD3DNOWEXT", // AMD 3DNowExt + mmx: "MMX", // Standard MMX + mmxext: "MMXEXT", // SSE integer functions or AMD MMX ext + sse: "SSE", // SSE functions + sse2: "SSE2", // P4 SSE2 functions + sse3: "SSE3", // Prescott SSE3 functions + ssse3: "SSSE3", // Conroe SSSE3 functions + sse4: "SSE4.1", // Penryn SSE4.1 functions + sse4a: "SSE4A", // AMD Barcelona microarchitecture SSE4a instructions + sse42: "SSE4.2", // Nehalem SSE4.2 functions + avx: "AVX", // AVX functions + avx2: "AVX2", // AVX functions + fma3: "FMA3", // Intel FMA 3 + fma4: "FMA4", // Bulldozer FMA4 functions + xop: "XOP", // Bulldozer XOP functions + f16c: "F16C", // Half-precision floating-point conversion + bmi1: "BMI1", // Bit Manipulation Instruction Set 1 + bmi2: "BMI2", // Bit Manipulation Instruction Set 2 + tbm: "TBM", // AMD Trailing Bit Manipulation + lzcnt: "LZCNT", // LZCNT instruction + popcnt: "POPCNT", // POPCNT instruction + aesni: "AESNI", // Advanced Encryption Standard New Instructions + clmul: "CLMUL", // Carry-less Multiplication + htt: "HTT", // Hyperthreading (enabled) + hle: "HLE", // Hardware Lock Elision + rtm: "RTM", // Restricted Transactional Memory + rdrand: "RDRAND", // RDRAND instruction is available + rdseed: "RDSEED", // RDSEED instruction is available + adx: "ADX", // Intel ADX (Multi-Precision Add-Carry Instruction Extensions) + sha: "SHA", // Intel SHA Extensions + avx512f: "AVX512F", // AVX-512 Foundation + avx512dq: "AVX512DQ", // AVX-512 Doubleword and Quadword Instructions + avx512ifma: "AVX512IFMA", // AVX-512 Integer Fused Multiply-Add Instructions + avx512pf: "AVX512PF", // AVX-512 Prefetch Instructions + avx512er: "AVX512ER", // AVX-512 Exponential and Reciprocal Instructions + avx512cd: "AVX512CD", // AVX-512 Conflict Detection Instructions + avx512bw: "AVX512BW", // AVX-512 Byte and Word Instructions + avx512vl: "AVX512VL", // AVX-512 Vector Length Extensions + avx512vbmi: "AVX512VBMI", // AVX-512 Vector Bit Manipulation Instructions + mpx: "MPX", // Intel MPX (Memory Protection Extensions) + erms: "ERMS", // Enhanced REP MOVSB/STOSB + rdtscp: "RDTSCP", // RDTSCP Instruction + cx16: "CX16", // CMPXCHG16B Instruction // Performance indicators - sse2slow: "SSE2SLOW", // SSE2 supported, but usually not faster - sse3slow: "SSE3SLOW", // SSE3 supported, but usually not faster - atom: "ATOM", // Atom processor, some SSSE3 instructions are slower + sse2slow: "SSE2SLOW", // SSE2 supported, but usually not faster + sse3slow: "SSE3SLOW", // SSE3 supported, but usually not faster + atom: "ATOM", // Atom processor, some SSSE3 instructions are slower } // CPUInfo contains information about the detected system CPU. type cpuInfo struct { - brandname string // Brand name reported by the CPU - vendorid vendor // Comparable CPU vendor ID - features flags // Features of the CPU - physicalcores int // Number of physical processor cores in your CPU. Will be 0 if undetectable. - threadspercore int // Number of threads per physical core. Will be 1 if undetectable. - logicalcores int // Number of physical cores times threads that can run on each core through the use of hyperthreading. Will be 0 if undetectable. - family int // CPU family number - model int // CPU model number - cacheline int // Cache line size in bytes. Will be 0 if undetectable. - cache struct { - l1i int // L1 Instruction Cache (per core or shared). Will be -1 if undetected - l1d int // L1 Data Cache (per core or shared). Will be -1 if undetected - l2 int // L2 Cache (per core or shared). Will be -1 if undetected - l3 int // L3 Instruction Cache (per core or shared). Will be -1 if undetected - } - maxFunc uint32 - maxExFunc uint32 + brandname string // Brand name reported by the CPU + vendorid vendor // Comparable CPU vendor ID + features flags // Features of the CPU + physicalcores int // Number of physical processor cores in your CPU. Will be 0 if undetectable. + threadspercore int // Number of threads per physical core. Will be 1 if undetectable. + logicalcores int // Number of physical cores times threads that can run on each core through the use of hyperthreading. Will be 0 if undetectable. + family int // CPU family number + model int // CPU model number + cacheline int // Cache line size in bytes. Will be 0 if undetectable. + cache struct { + l1i int // L1 Instruction Cache (per core or shared). Will be -1 if undetected + l1d int // L1 Data Cache (per core or shared). Will be -1 if undetected + l2 int // L2 Cache (per core or shared). Will be -1 if undetected + l3 int // L3 Instruction Cache (per core or shared). Will be -1 if undetected + } + maxFunc uint32 + maxExFunc uint32 } var cpuid func(op uint32) (eax, ebx, ecx, edx uint32) @@ -638,18 +638,18 @@ func physicalCores() int { // Except from http://en.wikipedia.org/wiki/CPUID#EAX.3D0:_Get_vendor_ID var vendorMapping = map[string]vendor{ - "AMDisbetter!": amd, - "AuthenticAMD": amd, - "CentaurHauls": via, - "GenuineIntel": intel, - "TransmetaCPU": transmeta, - "GenuineTMx86": transmeta, - "Geode by NSC": nsc, - "VIA VIA VIA ": via, - "KVMKVMKVMKVM": kvm, - "Microsoft Hv": msvm, - "VMwareVMware": vmware, - "XenVMMXenVMM": xenhvm, + "AMDisbetter!": amd, + "AuthenticAMD": amd, + "CentaurHauls": via, + "GenuineIntel": intel, + "TransmetaCPU": transmeta, + "GenuineTMx86": transmeta, + "Geode by NSC": nsc, + "VIA VIA VIA ": via, + "KVMKVMKVMKVM": kvm, + "Microsoft Hv": msvm, + "VMwareVMware": vmware, + "XenVMMXenVMM": xenhvm, } func vendorID() vendor { @@ -668,10 +668,10 @@ func cacheLine() int { } _, ebx, _, _ := cpuid(1) - cache := (ebx & 0xff00) >> 5 // cflush size + cache := (ebx & 0xff00) >> 5 // cflush size if cache == 0 && maxExtendedFunction() >= 0x80000006 { _, _, ecx, _ := cpuid(0x80000006) - cache = ecx & 0xff // cacheline size + cache = ecx & 0xff // cacheline size } // TODO: Read from Cache and TLB Information return int(cache) diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go index d1552e5..b33045d 100644 --- a/vendor/github.com/stretchr/testify/assert/assertions.go +++ b/vendor/github.com/stretchr/testify/assert/assertions.go @@ -181,7 +181,7 @@ func indentMessageLines(message string, longestLabelLen int) string { // no need to align first line because it starts at the correct location (after the label) if i != 0 { // append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab - outBuf.WriteString("\n\r\t" + strings.Repeat(" ", longestLabelLen +1) + "\t") + outBuf.WriteString("\n\r\t" + strings.Repeat(" ", longestLabelLen+1) + "\t") } outBuf.WriteString(scanner.Text()) } @@ -229,7 +229,7 @@ func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { } type labeledContent struct { - label string + label string content string } diff --git a/vendor/github.com/stretchr/testify/assert/assertions_test.go b/vendor/github.com/stretchr/testify/assert/assertions_test.go index fb23505..3e3861b 100644 --- a/vendor/github.com/stretchr/testify/assert/assertions_test.go +++ b/vendor/github.com/stretchr/testify/assert/assertions_test.go @@ -250,8 +250,8 @@ func TestEqualFormatting(t *testing.T) { msgAndArgs []interface{} want string }{ - {equalWant:"want", equalGot: "got", want: "\tassertions.go:[0-9]+: \r \r\tError Trace:\t\n\t\t\r\tError: \tNot equal: \n\t\t\r\t \texpected: \"want\"\n\t\t\r\t \treceived: \"got\"\n"}, - {equalWant:"want", equalGot: "got", msgAndArgs: []interface{}{"hello, %v!", "world"}, want: "\tassertions.go:[0-9]+: \r \r\tError Trace:\t\n\t\t\r\tError: \tNot equal: \n\t\t\r\t \texpected: \"want\"\n\t\t\r\t \treceived: \"got\"\n\t\t\r\tMessages: \thello, world!\n"}, + {equalWant: "want", equalGot: "got", want: "\tassertions.go:[0-9]+: \r \r\tError Trace:\t\n\t\t\r\tError: \tNot equal: \n\t\t\r\t \texpected: \"want\"\n\t\t\r\t \treceived: \"got\"\n"}, + {equalWant: "want", equalGot: "got", msgAndArgs: []interface{}{"hello, %v!", "world"}, want: "\tassertions.go:[0-9]+: \r \r\tError Trace:\t\n\t\t\r\tError: \tNot equal: \n\t\t\r\t \texpected: \"want\"\n\t\t\r\t \treceived: \"got\"\n\t\t\r\tMessages: \thello, world!\n"}, } { mockT := &bufferT{} Equal(mockT, currCase.equalWant, currCase.equalGot, currCase.msgAndArgs...) diff --git a/vendor/github.com/tjfoc/gmsm/sm4/sm4.go b/vendor/github.com/tjfoc/gmsm/sm4/sm4.go index a839332..76415d7 100644 --- a/vendor/github.com/tjfoc/gmsm/sm4/sm4.go +++ b/vendor/github.com/tjfoc/gmsm/sm4/sm4.go @@ -149,7 +149,7 @@ func cryptBlock(subkeys []uint32, b []uint32, r []byte, dst, src []byte, decrypt permuteInitialBlock(b, src) for i := 0; i < 32; i++ { if decrypt { - tm = b[0] ^ l1(p(b[1]^b[2]^b[3]^subkeys[31 - i])) + tm = b[0] ^ l1(p(b[1]^b[2]^b[3]^subkeys[31-i])) // tm = feistel1(b[0], b[1], b[2], b[3], subkeys[31-i]) } else { tm = b[0] ^ l1(p(b[1]^b[2]^b[3]^subkeys[i])) diff --git a/vendor/golang.org/x/crypto/ssh/kex.go b/vendor/golang.org/x/crypto/ssh/kex.go index c87fbeb..f91c277 100644 --- a/vendor/golang.org/x/crypto/ssh/kex.go +++ b/vendor/golang.org/x/crypto/ssh/kex.go @@ -383,8 +383,8 @@ func init() { // 4253 and Oakley Group 2 in RFC 2409. p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16) kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{ - g: new(big.Int).SetInt64(2), - p: p, + g: new(big.Int).SetInt64(2), + p: p, pMinus1: new(big.Int).Sub(p, bigOne), } @@ -393,8 +393,8 @@ func init() { p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16) kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{ - g: new(big.Int).SetInt64(2), - p: p, + g: new(big.Int).SetInt64(2), + p: p, pMinus1: new(big.Int).Sub(p, bigOne), } -- GitLab