diff --git a/.github/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE index f9f7faec..8ca17c08 100644 --- a/.github/ISSUE_TEMPLATE +++ b/.github/ISSUE_TEMPLATE @@ -1,7 +1,4 @@ Issue is only used for submiting bug report and documents typo. If there are same issues or answers can be found in documents, we will close it directly. -(为了节约时间,提高处理问题的效率,不按照格式填写的 issue 将会直接关闭。) -(请不要在 issue 评论中出现无意义的 **加1**,**我也是** 等内容,将会被直接删除。) -(由于个人精力有限,和系统环境,网络环境等相关的求助问题请转至其他论坛或社交平台。) Use the commands below to provide key information from your environment: You do NOT have to include this information if this is a FEATURE REQUEST diff --git a/.gitignore b/.gitignore index 02ab6b2d..bf34f139 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ _testmain.go # Self bin/ packages/ +release/ test/bin/ vendor/ diff --git a/.travis.yml b/.travis.yml index 3e5b993a..fe365a30 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,8 +2,8 @@ sudo: false language: go go: - - 1.12.x - 1.13.x + - 1.14.x install: - make diff --git a/Makefile.cross-compiles b/Makefile.cross-compiles index a7dffad8..b849c94f 100644 --- a/Makefile.cross-compiles +++ b/Makefile.cross-compiles @@ -1,4 +1,5 @@ export PATH := $(GOPATH)/bin:$(PATH) +export GO111MODULE=on LDFLAGS := -s -w all: build @@ -6,32 +7,32 @@ all: build build: app app: - env CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./frpc_darwin_amd64 ./cmd/frpc - env CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./frps_darwin_amd64 ./cmd/frps - env CGO_ENABLED=0 GOOS=freebsd GOARCH=386 go build -ldflags "$(LDFLAGS)" -o ./frpc_freebsd_386 ./cmd/frpc - env CGO_ENABLED=0 GOOS=freebsd GOARCH=386 go build -ldflags "$(LDFLAGS)" -o ./frps_freebsd_386 ./cmd/frps - env CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./frpc_freebsd_amd64 ./cmd/frpc - env CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./frps_freebsd_amd64 ./cmd/frps - env CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -ldflags "$(LDFLAGS)" -o ./frpc_linux_386 ./cmd/frpc - env CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -ldflags "$(LDFLAGS)" -o ./frps_linux_386 ./cmd/frps - env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./frpc_linux_amd64 ./cmd/frpc - env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./frps_linux_amd64 ./cmd/frps - env CGO_ENABLED=0 GOOS=linux GOARCH=arm go build -ldflags "$(LDFLAGS)" -o ./frpc_linux_arm ./cmd/frpc - env CGO_ENABLED=0 GOOS=linux GOARCH=arm go build -ldflags "$(LDFLAGS)" -o ./frps_linux_arm ./cmd/frps - env CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags "$(LDFLAGS)" -o ./frpc_linux_arm64 ./cmd/frpc - env CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags "$(LDFLAGS)" -o ./frps_linux_arm64 ./cmd/frps - env CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags "$(LDFLAGS)" -o ./frpc_windows_386.exe ./cmd/frpc - env CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags "$(LDFLAGS)" -o ./frps_windows_386.exe ./cmd/frps - env CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./frpc_windows_amd64.exe ./cmd/frpc - env CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./frps_windows_amd64.exe ./cmd/frps - env CGO_ENABLED=0 GOOS=linux GOARCH=mips64 go build -ldflags "$(LDFLAGS)" -o ./frpc_linux_mips64 ./cmd/frpc - env CGO_ENABLED=0 GOOS=linux GOARCH=mips64 go build -ldflags "$(LDFLAGS)" -o ./frps_linux_mips64 ./cmd/frps - env CGO_ENABLED=0 GOOS=linux GOARCH=mips64le go build -ldflags "$(LDFLAGS)" -o ./frpc_linux_mips64le ./cmd/frpc - env CGO_ENABLED=0 GOOS=linux GOARCH=mips64le go build -ldflags "$(LDFLAGS)" -o ./frps_linux_mips64le ./cmd/frps - env CGO_ENABLED=0 GOOS=linux GOARCH=mips GOMIPS=softfloat go build -ldflags "$(LDFLAGS)" -o ./frpc_linux_mips ./cmd/frpc - env CGO_ENABLED=0 GOOS=linux GOARCH=mips GOMIPS=softfloat go build -ldflags "$(LDFLAGS)" -o ./frps_linux_mips ./cmd/frps - env CGO_ENABLED=0 GOOS=linux GOARCH=mipsle GOMIPS=softfloat go build -ldflags "$(LDFLAGS)" -o ./frpc_linux_mipsle ./cmd/frpc - env CGO_ENABLED=0 GOOS=linux GOARCH=mipsle GOMIPS=softfloat go build -ldflags "$(LDFLAGS)" -o ./frps_linux_mipsle ./cmd/frps + env CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./release/frpc_darwin_amd64 ./cmd/frpc + env CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./release/frps_darwin_amd64 ./cmd/frps + env CGO_ENABLED=0 GOOS=freebsd GOARCH=386 go build -ldflags "$(LDFLAGS)" -o ./release/frpc_freebsd_386 ./cmd/frpc + env CGO_ENABLED=0 GOOS=freebsd GOARCH=386 go build -ldflags "$(LDFLAGS)" -o ./release/frps_freebsd_386 ./cmd/frps + env CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./release/frpc_freebsd_amd64 ./cmd/frpc + env CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./release/frps_freebsd_amd64 ./cmd/frps + env CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -ldflags "$(LDFLAGS)" -o ./release/frpc_linux_386 ./cmd/frpc + env CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -ldflags "$(LDFLAGS)" -o ./release/frps_linux_386 ./cmd/frps + env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./release/frpc_linux_amd64 ./cmd/frpc + env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./release/frps_linux_amd64 ./cmd/frps + env CGO_ENABLED=0 GOOS=linux GOARCH=arm go build -ldflags "$(LDFLAGS)" -o ./release/frpc_linux_arm ./cmd/frpc + env CGO_ENABLED=0 GOOS=linux GOARCH=arm go build -ldflags "$(LDFLAGS)" -o ./release/frps_linux_arm ./cmd/frps + env CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags "$(LDFLAGS)" -o ./release/frpc_linux_arm64 ./cmd/frpc + env CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags "$(LDFLAGS)" -o ./release/frps_linux_arm64 ./cmd/frps + env CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags "$(LDFLAGS)" -o ./release/frpc_windows_386.exe ./cmd/frpc + env CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags "$(LDFLAGS)" -o ./release/frps_windows_386.exe ./cmd/frps + env CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./release/frpc_windows_amd64.exe ./cmd/frpc + env CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./release/frps_windows_amd64.exe ./cmd/frps + env CGO_ENABLED=0 GOOS=linux GOARCH=mips64 go build -ldflags "$(LDFLAGS)" -o ./release/frpc_linux_mips64 ./cmd/frpc + env CGO_ENABLED=0 GOOS=linux GOARCH=mips64 go build -ldflags "$(LDFLAGS)" -o ./release/frps_linux_mips64 ./cmd/frps + env CGO_ENABLED=0 GOOS=linux GOARCH=mips64le go build -ldflags "$(LDFLAGS)" -o ./release/frpc_linux_mips64le ./cmd/frpc + env CGO_ENABLED=0 GOOS=linux GOARCH=mips64le go build -ldflags "$(LDFLAGS)" -o ./release/frps_linux_mips64le ./cmd/frps + env CGO_ENABLED=0 GOOS=linux GOARCH=mips GOMIPS=softfloat go build -ldflags "$(LDFLAGS)" -o ./release/frpc_linux_mips ./cmd/frpc + env CGO_ENABLED=0 GOOS=linux GOARCH=mips GOMIPS=softfloat go build -ldflags "$(LDFLAGS)" -o ./release/frps_linux_mips ./cmd/frps + env CGO_ENABLED=0 GOOS=linux GOARCH=mipsle GOMIPS=softfloat go build -ldflags "$(LDFLAGS)" -o ./release/frpc_linux_mipsle ./cmd/frpc + env CGO_ENABLED=0 GOOS=linux GOARCH=mipsle GOMIPS=softfloat go build -ldflags "$(LDFLAGS)" -o ./release/frps_linux_mipsle ./cmd/frps temp: env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o ./frps_linux_amd64 ./cmd/frps diff --git a/README.md b/README.md index f39b9515..beb94391 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ Put `frpc` and `frpc.ini` onto your server B in LAN (that can't be connected fro ### Access your computer in LAN by SSH -1. Modify `frps.ini` on server A: +1. Modify `frps.ini` on server A and set the `bind_port` to be connected to frp clients: ```ini # frps.ini @@ -117,6 +117,8 @@ Put `frpc` and `frpc.ini` onto your server B in LAN (that can't be connected fro remote_port = 6000 ``` +Note that `local_port` (listened on client) and `remote_port` (exposed on server) are for traffic goes in/out the frp system, whereas `server_port` is used between frps. + 4. Start `frpc` on server B: `./frpc -c ./frpc.ini` @@ -933,6 +935,8 @@ plugin_http_passwd = abc Read the [document](/doc/server_plugin.md). +Find more plugins in [gofrp/plugin](https://github.com/gofrp/plugin). + ## Development Plan * Log HTTP request information in frps. diff --git a/README_zh.md b/README_zh.md index 0d167018..678638d3 100644 --- a/README_zh.md +++ b/README_zh.md @@ -89,7 +89,7 @@ master 分支用于发布稳定版本,dev 分支用于开发,您可以尝试 ### 通过 ssh 访问公司内网机器 -1. 修改 frps.ini 文件,这里使用了最简化的配置: +1. 修改 frps.ini 文件,这里使用了最简化的配置,设置了 frp 服务器端接收客户端流量的端口: ```ini # frps.ini @@ -101,7 +101,7 @@ master 分支用于发布稳定版本,dev 分支用于开发,您可以尝试 `./frps -c ./frps.ini` -3. 修改 frpc.ini 文件,假设 frps 所在服务器的公网 IP 为 x.x.x.x; +3. 修改 frpc.ini 文件,假设 frps 所在服务器的公网 IP 为 x.x.x.x: ```ini # frpc.ini @@ -116,6 +116,9 @@ master 分支用于发布稳定版本,dev 分支用于开发,您可以尝试 remote_port = 6000 ``` +注意,`local_port`(客户端侦听)和 `remote_port`(服务器端暴露)是用来出入 frp 系统的两端,`server_port` 则是服务器用来与客户端通讯的。 + + 4. 启动 frpc: `./frpc -c ./frpc.ini` @@ -983,6 +986,8 @@ plugin_http_passwd = abc [使用说明](/doc/server_plugin_zh.md) +从 [gofrp/plugin](https://github.com/gofrp/plugin) 中寻找更多插件。 + ## 开发计划 计划在后续版本中加入的功能与优化,排名不分先后,如果有其他功能建议欢迎在 [issues](https://github.com/fatedier/frp/issues) 中反馈。 @@ -1006,8 +1011,6 @@ frp 是一个免费且开源的项目,我们欢迎任何人为其开发和进 如果您觉得 frp 对你有帮助,欢迎给予我们一定的捐助来维持项目的长期发展。 -frp 交流群:606194980 (QQ 群号) - ### 知识星球 如果您想学习 frp 相关的知识和技术,或者寻求任何帮助,都可以通过微信扫描下方的二维码付费加入知识星球的官方社群: diff --git a/client/control.go b/client/control.go index f415f65f..3da61712 100644 --- a/client/control.go +++ b/client/control.go @@ -183,6 +183,7 @@ func (ctl *Control) HandleNewProxyResp(inMsg *msg.NewProxyResp) { func (ctl *Control) Close() error { ctl.pm.Close() ctl.conn.Close() + ctl.vm.Close() if ctl.session != nil { ctl.session.Close() } diff --git a/client/service.go b/client/service.go index 297d3a36..b6ea0634 100644 --- a/client/service.go +++ b/client/service.go @@ -142,12 +142,34 @@ func (svr *Service) keepControllerWorking() { maxDelayTime := 20 * time.Second delayTime := time.Second + // if frpc reconnect frps, we need to limit retry times in 1min + // current retry logic is sleep 0s, 0s, 0s, 1s, 2s, 4s, 8s, ... + // when exceed 1min, we will reset delay and counts + cutoffTime := time.Now().Add(time.Minute) + reconnectDelay := time.Second + reconnectCounts := 1 + for { <-svr.ctl.ClosedDoneCh() if atomic.LoadUint32(&svr.exit) != 0 { return } + // the first three retry with no delay + if reconnectCounts > 3 { + time.Sleep(reconnectDelay) + reconnectDelay *= 2 + } + reconnectCounts++ + + now := time.Now() + if now.After(cutoffTime) { + // reset + cutoffTime = now.Add(time.Minute) + reconnectDelay = time.Second + reconnectCounts = 1 + } + for { xl.Info("try to reconnect to server...") conn, session, err := svr.login() @@ -166,6 +188,9 @@ func (svr *Service) keepControllerWorking() { ctl := NewControl(svr.ctx, svr.runId, conn, session, svr.cfg, svr.pxyCfgs, svr.visitorCfgs, svr.serverUDPPort, svr.authSetter) ctl.Run() svr.ctlMu.Lock() + if svr.ctl != nil { + svr.ctl.Close() + } svr.ctl = ctl svr.ctlMu.Unlock() break diff --git a/client/visitor_manager.go b/client/visitor_manager.go index 3b9351e7..ea32eac0 100644 --- a/client/visitor_manager.go +++ b/client/visitor_manager.go @@ -33,6 +33,8 @@ type VisitorManager struct { mu sync.Mutex ctx context.Context + + stopCh chan struct{} } func NewVisitorManager(ctx context.Context, ctl *Control) *VisitorManager { @@ -42,22 +44,32 @@ func NewVisitorManager(ctx context.Context, ctl *Control) *VisitorManager { visitors: make(map[string]Visitor), checkInterval: 10 * time.Second, ctx: ctx, + stopCh: make(chan struct{}), } } func (vm *VisitorManager) Run() { xl := xlog.FromContextSafe(vm.ctx) + + ticker := time.NewTicker(vm.checkInterval) + defer ticker.Stop() + for { - time.Sleep(vm.checkInterval) - vm.mu.Lock() - for _, cfg := range vm.cfgs { - name := cfg.GetBaseInfo().ProxyName - if _, exist := vm.visitors[name]; !exist { - xl.Info("try to start visitor [%s]", name) - vm.startVisitor(cfg) + select { + case <-vm.stopCh: + xl.Info("gracefully shutdown visitor manager") + return + case <-ticker.C: + vm.mu.Lock() + for _, cfg := range vm.cfgs { + name := cfg.GetBaseInfo().ProxyName + if _, exist := vm.visitors[name]; !exist { + xl.Info("try to start visitor [%s]", name) + vm.startVisitor(cfg) + } } + vm.mu.Unlock() } - vm.mu.Unlock() } } @@ -126,4 +138,9 @@ func (vm *VisitorManager) Close() { for _, v := range vm.visitors { v.Close() } + select { + case <-vm.stopCh: + default: + close(vm.stopCh) + } } diff --git a/doc/server_plugin.md b/doc/server_plugin.md index 7d9be120..599aa6e3 100644 --- a/doc/server_plugin.md +++ b/doc/server_plugin.md @@ -1,27 +1,28 @@ -### Manage Plugin +### Server Plugin -frp manage plugin is aim to extend frp's ability without modifing self code. +frp server plugin is aimed to extend frp's ability without modifying the Golang code. -It runs as a process and listen on a port to provide RPC interface. Before frps doing some operations, frps will send RPC requests to manage plugin and do operations by it's response. +An external server should run in a different process receiving RPC calls from frps. +Before frps is doing some operations, it will send RPC requests to notify the external RPC server and act according to its response. ### RPC request -Support HTTP first. +RPC requests are based on JSON over HTTP. -When manage plugin accept the operation request, it can give three different responses. +When a server plugin accepts an operation request, it can respond with three different responses: -* Reject operation and return the reason. +* Reject operation and return a reason. * Allow operation and keep original content. * Allow operation and return modified content. ### Interface -HTTP path can be configured for each manage plugin in frps. Assume here is `/handler`. +HTTP path can be configured for each manage plugin in frps. We'll assume for this example that it's `/handler`. -Request +A request to the RPC server will look like: ``` -POST /handler +POST /handler?version=0.1.0&op=Login { "version": "0.1.0", "op": "Login", @@ -30,15 +31,15 @@ POST /handler } } -Request Header +Request Header: X-Frp-Reqid: for tracing ``` -Response +The response can look like any of the following: -Error if not return 200 http code. +* Non-200 HTTP response status code (this will automatically tell frps that the request should fail) -Reject opeartion +* Reject operation: ``` { @@ -47,7 +48,7 @@ Reject opeartion } ``` -Allow operation and keep original content +* Allow operation and keep original content: ``` { @@ -56,7 +57,7 @@ Allow operation and keep original content } ``` -Allow opeartion and modify content +* Allow operation and modify content ``` { @@ -69,7 +70,7 @@ Allow opeartion and modify content ### Operation -Now it supports `Login` and `NewProxy`. +Currently `Login`, `NewProxy`, `Ping` and `NewWorkConn` operations are supported. #### Login @@ -102,6 +103,7 @@ Create new proxy "user": { "user": , "metas": mapstring + "run_id": }, "proxy_name": , "proxy_type": , @@ -122,14 +124,58 @@ Create new proxy "host_header_rewrite": , "headers": mapstring, + // stcp only + "sk": , + + // tcpmux only + "multiplexer": + "metas": mapstring } } ``` -### manage plugin configure +#### Ping + +Heartbeat from frpc + +``` +{ + "content": { + "user": { + "user": , + "metas": mapstring + "run_id": + }, + "timestamp": , + "privilege_key": + } +} +``` + +#### NewWorkConn + +New work connection received from frpc (RPC sent after `run_id` is matched with an existing frp connection) + +``` +{ + "content": { + "user": { + "user": , + "metas": mapstring + "run_id": + }, + "run_id": + "timestamp": , + "privilege_key": + } +} +``` + +### Server Plugin Configuration ```ini +# frps.ini [common] bind_port = 7000 @@ -144,15 +190,19 @@ path = /handler ops = NewProxy ``` -addr: plugin listen on. -path: http request url path. -ops: opeartions plugin needs handle. +addr: the address where the external RPC service listens on. +path: http request url path for the POST request. +ops: operations plugin needs to handle (e.g. "Login", "NewProxy", ...). -### meta data +### Metadata -Meta data will be sent to manage plugin in each RCP request. +Metadata will be sent to the server plugin in each RPC request. -Meta data start with `meta_`. It can be configured in `common` and each proxy. +There are 2 types of metadata entries - 1 under `[common]` and the other under each proxy configuration. +Metadata entries under `[common]` will be sent in `Login` under the key `metas`, and in any other RPC request under `user.metas`. +Metadata entries under each proxy configuration will be sent in `NewProxy` op only, under `metas`. + +Metadata entries start with `meta_`. This is an example of metadata entries in `[common]` and under the proxy named `[ssh]`: ``` # frpc.ini diff --git a/go.sum b/go.sum index fc1f5452..94a7f930 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,7 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -15,6 +16,7 @@ github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHo github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatedier/beego v0.0.0-20171024143340-6c6a4f5bd5eb h1:wCrNShQidLmvVWn/0PikGmpdP0vtQmnvyRg3ZBEhczw= github.com/fatedier/beego v0.0.0-20171024143340-6c6a4f5bd5eb/go.mod h1:wx3gB6dbIfBRcucp94PI9Bt3I0F2c/MyNEWuhzpWiwk= github.com/fatedier/golib v0.0.0-20181107124048-ff8cd814b049 h1:teH578mf2ii42NHhIp3PhgvjU5bv+NFMq9fSQR8NaG8= github.com/fatedier/golib v0.0.0-20181107124048-ff8cd814b049/go.mod h1:DqIrnl0rp3Zybg9zbJmozTy1n8fYJoX+QoAj9slIkKM= @@ -30,8 +32,10 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/snappy v0.0.0-20170215233205-553a64147049 h1:K9KHZbXKpGydfDN0aZrsoHpLJlZsBrGMFWbgLDGnPZk= github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= @@ -40,6 +44,7 @@ github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ= github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -50,9 +55,12 @@ github.com/klauspost/reedsolomon v1.9.1 h1:kYrT1MlR4JH6PqOpC+okdb9CDTcwEC/BqpzK4 github.com/klauspost/reedsolomon v1.9.1/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -66,6 +74,7 @@ github.com/pires/go-proxyproto v0.0.0-20190111085350-4d51b51e3bfc/go.mod h1:6/gX github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU= github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= @@ -84,11 +93,15 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/rakyll/statik v0.1.1 h1:fCLHsIMajHqD5RKigbFXpvX3dN7c80Pm12+NCrI3kvg= github.com/rakyll/statik v0.1.1/go.mod h1:OEi9wJV/fMUAGx1eNjq75DKDsJVuEv1U0oYdX6GX8Zs= +github.com/rodaine/table v1.0.0 h1:UaCJG5Axc/cNXVGXqnCrffm1KxP0OfYLe1HuJLf5sFY= github.com/rodaine/table v1.0.0/go.mod h1:YAUzwPOji0DUJNEvggdxyQcUAl4g3hDRcFlyjnnR51I= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -96,10 +109,15 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/templexxx/cpufeat v0.0.0-20170927014610-3794dfbfb047 h1:K+jtWCOuZgCra7eXZ/VWn2FbJmrA/D058mTXhh2rq+8= github.com/templexxx/cpufeat v0.0.0-20170927014610-3794dfbfb047/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU= +github.com/templexxx/xor v0.0.0-20170926022130-0af8e873c554 h1:pexgSe+JCFuxG+uoMZLO+ce8KHtdHGhst4cs6rw3gmk= github.com/templexxx/xor v0.0.0-20170926022130-0af8e873c554/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4= +github.com/tjfoc/gmsm v0.0.0-20171124023159-98aa888b79d8 h1:6CNSDqI1wiE+JqyOy5Qt/yo/DoNI2/QmmOZeiCid2Nw= github.com/tjfoc/gmsm v0.0.0-20171124023159-98aa888b79d8/go.mod h1:XxO4hdhhrzAd+G4CjDqaOkd0hUzmtPR/d3EiBBMn/wc= +github.com/vaughan0/go-ini v0.0.0-20130923145212-a98ad7ee00ec h1:DGmKwyZwEB8dI7tbLt/I/gQuP559o/0FrAkHKlQM/Ks= github.com/vaughan0/go-ini v0.0.0-20130923145212-a98ad7ee00ec/go.mod h1:owBmyHYMLkxyrugmfwE/DLJyW8Ro9mkphwuVErQ0iUw= +github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae h1:J0GxkO96kL4WF+AIT3M4mfUVinOCPgf2uUWYFUzN0sM= github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= @@ -127,10 +145,13 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/square/go-jose.v2 v2.4.1 h1:H0TmLt7/KmzlrDOpa1F+zr0Tk90PbJYBfsVUmRLrf9Y= gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= diff --git a/models/plugin/server/http.go b/models/plugin/server/http.go index a3c243a0..81c54ec2 100644 --- a/models/plugin/server/http.go +++ b/models/plugin/server/http.go @@ -21,6 +21,7 @@ import ( "fmt" "io/ioutil" "net/http" + "net/url" "reflect" ) @@ -78,7 +79,10 @@ func (p *httpPlugin) do(ctx context.Context, r *Request, res *Response) error { if err != nil { return err } - req, err := http.NewRequest("POST", p.url, bytes.NewReader(buf)) + v := url.Values{} + v.Set("version", r.Version) + v.Set("op", r.Op) + req, err := http.NewRequest("POST", p.url+"?"+v.Encode(), bytes.NewReader(buf)) if err != nil { return err } diff --git a/models/plugin/server/manager.go b/models/plugin/server/manager.go index 94642932..c427f0a1 100644 --- a/models/plugin/server/manager.go +++ b/models/plugin/server/manager.go @@ -24,14 +24,18 @@ import ( ) type Manager struct { - loginPlugins []Plugin - newProxyPlugins []Plugin + loginPlugins []Plugin + newProxyPlugins []Plugin + pingPlugins []Plugin + newWorkConnPlugins []Plugin } func NewManager() *Manager { return &Manager{ - loginPlugins: make([]Plugin, 0), - newProxyPlugins: make([]Plugin, 0), + loginPlugins: make([]Plugin, 0), + newProxyPlugins: make([]Plugin, 0), + pingPlugins: make([]Plugin, 0), + newWorkConnPlugins: make([]Plugin, 0), } } @@ -42,9 +46,19 @@ func (m *Manager) Register(p Plugin) { if p.IsSupport(OpNewProxy) { m.newProxyPlugins = append(m.newProxyPlugins, p) } + if p.IsSupport(OpPing) { + m.pingPlugins = append(m.pingPlugins, p) + } + if p.IsSupport(OpNewWorkConn) { + m.pingPlugins = append(m.pingPlugins, p) + } } func (m *Manager) Login(content *LoginContent) (*LoginContent, error) { + if len(m.loginPlugins) == 0 { + return content, nil + } + var ( res = &Response{ Reject: false, @@ -75,6 +89,10 @@ func (m *Manager) Login(content *LoginContent) (*LoginContent, error) { } func (m *Manager) NewProxy(content *NewProxyContent) (*NewProxyContent, error) { + if len(m.newProxyPlugins) == 0 { + return content, nil + } + var ( res = &Response{ Reject: false, @@ -103,3 +121,71 @@ func (m *Manager) NewProxy(content *NewProxyContent) (*NewProxyContent, error) { } return content, nil } + +func (m *Manager) Ping(content *PingContent) (*PingContent, error) { + if len(m.pingPlugins) == 0 { + return content, nil + } + + var ( + res = &Response{ + Reject: false, + Unchange: true, + } + retContent interface{} + err error + ) + reqid, _ := util.RandId() + xl := xlog.New().AppendPrefix("reqid: " + reqid) + ctx := xlog.NewContext(context.Background(), xl) + ctx = NewReqidContext(ctx, reqid) + + for _, p := range m.pingPlugins { + res, retContent, err = p.Handle(ctx, OpPing, *content) + if err != nil { + xl.Warn("send Ping request to plugin [%s] error: %v", p.Name(), err) + return nil, errors.New("send Ping request to plugin error") + } + if res.Reject { + return nil, fmt.Errorf("%s", res.RejectReason) + } + if !res.Unchange { + content = retContent.(*PingContent) + } + } + return content, nil +} + +func (m *Manager) NewWorkConn(content *NewWorkConnContent) (*NewWorkConnContent, error) { + if len(m.newWorkConnPlugins) == 0 { + return content, nil + } + + var ( + res = &Response{ + Reject: false, + Unchange: true, + } + retContent interface{} + err error + ) + reqid, _ := util.RandId() + xl := xlog.New().AppendPrefix("reqid: " + reqid) + ctx := xlog.NewContext(context.Background(), xl) + ctx = NewReqidContext(ctx, reqid) + + for _, p := range m.pingPlugins { + res, retContent, err = p.Handle(ctx, OpPing, *content) + if err != nil { + xl.Warn("send NewWorkConn request to plugin [%s] error: %v", p.Name(), err) + return nil, errors.New("send NewWorkConn request to plugin error") + } + if res.Reject { + return nil, fmt.Errorf("%s", res.RejectReason) + } + if !res.Unchange { + content = retContent.(*NewWorkConnContent) + } + } + return content, nil +} diff --git a/models/plugin/server/plugin.go b/models/plugin/server/plugin.go index fd16b145..a89a16b0 100644 --- a/models/plugin/server/plugin.go +++ b/models/plugin/server/plugin.go @@ -21,8 +21,10 @@ import ( const ( APIVersion = "0.1.0" - OpLogin = "Login" - OpNewProxy = "NewProxy" + OpLogin = "Login" + OpNewProxy = "NewProxy" + OpPing = "Ping" + OpNewWorkConn = "NewWorkConn" ) type Plugin interface { diff --git a/models/plugin/server/types.go b/models/plugin/server/types.go index 4e392b71..017236d0 100644 --- a/models/plugin/server/types.go +++ b/models/plugin/server/types.go @@ -38,9 +38,20 @@ type LoginContent struct { type UserInfo struct { User string `json:"user"` Metas map[string]string `json:"metas"` + RunId string `json:"run_id"` } type NewProxyContent struct { User UserInfo `json:"user"` msg.NewProxy } + +type PingContent struct { + User UserInfo `json:"user"` + msg.Ping +} + +type NewWorkConnContent struct { + User UserInfo `json:"user"` + msg.NewWorkConn +} diff --git a/package.sh b/package.sh index 7b0612ab..e7556db7 100755 --- a/package.sh +++ b/package.sh @@ -1,5 +1,5 @@ # compile for version -make +#make if [ $? -ne 0 ]; then echo "make error" exit 1 @@ -9,14 +9,16 @@ frp_version=`./bin/frps --version` echo "build version: $frp_version" # cross_compiles -make -f ./Makefile.cross-compiles +#make -f ./Makefile.cross-compiles -rm -rf ./packages -mkdir ./packages +rm -rf ./release/packages +mkdir -p ./release/packages os_all='linux windows darwin freebsd' arch_all='386 amd64 arm arm64 mips64 mips64le mips mipsle' +cd ./release + for os in $os_all; do for arch in $arch_all; do frp_dir_name="frp_${frp_version}_${os}_${arch}" @@ -43,8 +45,8 @@ for os in $os_all; do mv ./frpc_${os}_${arch} ${frp_path}/frpc mv ./frps_${os}_${arch} ${frp_path}/frps fi - cp ./LICENSE ${frp_path} - cp -rf ./conf/* ${frp_path} + cp ../LICENSE ${frp_path} + cp -rf ../conf/* ${frp_path} # packages cd ./packages @@ -57,3 +59,5 @@ for os in $os_all; do rm -rf ${frp_path} done done + +cd - diff --git a/server/control.go b/server/control.go index f4ed481d..4d7529e3 100644 --- a/server/control.go +++ b/server/control.go @@ -422,6 +422,7 @@ func (ctl *Control) manager() { User: plugin.UserInfo{ User: ctl.loginMsg.User, Metas: ctl.loginMsg.Metas, + RunId: ctl.loginMsg.RunId, }, NewProxy: *m, } @@ -449,10 +450,23 @@ func (ctl *Control) manager() { ctl.CloseProxy(m) xl.Info("close proxy [%s] success", m.ProxyName) case *msg.Ping: - if err := ctl.authVerifier.VerifyPing(m); err != nil { + content := &plugin.PingContent{ + User: plugin.UserInfo{ + User: ctl.loginMsg.User, + Metas: ctl.loginMsg.Metas, + RunId: ctl.loginMsg.RunId, + }, + Ping: *m, + } + retContent, err := ctl.pluginManager.Ping(content) + if err == nil { + m = &retContent.Ping + err = ctl.authVerifier.VerifyPing(m) + } + if err != nil { xl.Warn("received invalid ping: %v", err) ctl.sendCh <- &msg.Pong{ - Error: "invalid authentication in ping", + Error: util.GenerateResponseErrorString("invalid ping", err, ctl.serverCfg.DetailedErrorsToClient), } return } diff --git a/server/service.go b/server/service.go index 43870733..d3c31699 100644 --- a/server/service.go +++ b/server/service.go @@ -457,13 +457,27 @@ func (svr *Service) RegisterWorkConn(workConn net.Conn, newMsg *msg.NewWorkConn) xl.Warn("No client control found for run id [%s]", newMsg.RunId) return fmt.Errorf("no client control found for run id [%s]", newMsg.RunId) } - // Check auth. - if err := svr.authVerifier.VerifyNewWorkConn(newMsg); err != nil { - xl.Warn("Invalid authentication in NewWorkConn message on run id [%s]", newMsg.RunId) + // server plugin hook + content := &plugin.NewWorkConnContent{ + User: plugin.UserInfo{ + User: ctl.loginMsg.User, + Metas: ctl.loginMsg.Metas, + RunId: ctl.loginMsg.RunId, + }, + NewWorkConn: *newMsg, + } + retContent, err := svr.pluginManager.NewWorkConn(content) + if err == nil { + newMsg = &retContent.NewWorkConn + // Check auth. + err = svr.authVerifier.VerifyNewWorkConn(newMsg) + } + if err != nil { + xl.Warn("invalid NewWorkConn with run id [%s]", newMsg.RunId) msg.WriteMsg(workConn, &msg.StartWorkConn{ - Error: "invalid authentication in NewWorkConn", + Error: util.GenerateResponseErrorString("invalid NewWorkConn", err, ctl.serverCfg.DetailedErrorsToClient), }) - return fmt.Errorf("invalid authentication in NewWorkConn message on run id [%s]", newMsg.RunId) + return fmt.Errorf("invalid NewWorkConn with run id [%s]", newMsg.RunId) } return ctl.RegisterWorkConn(workConn) } diff --git a/utils/version/version.go b/utils/version/version.go index cdcd0bf0..32779e58 100644 --- a/utils/version/version.go +++ b/utils/version/version.go @@ -19,7 +19,7 @@ import ( "strings" ) -var version string = "0.32.0" +var version string = "0.32.1" func Full() string { return version