1
0
Эх сурвалжийг харах

Merge pull request #2869 from fatedier/dev

bump version to v0.41.0
fatedier 3 жил өмнө
parent
commit
10f2620131

+ 2 - 2
.circleci/config.yml

@@ -2,14 +2,14 @@ version: 2
 jobs:
   go-version-latest:
     docker:
-      - image: cimg/go:1.17-node
+      - image: cimg/go:1.18-node
     steps:
       - checkout
       - run: make
       - run: make alltest
   go-version-last:
     docker:
-      - image: cimg/go:1.16-node
+      - image: cimg/go:1.17-node
     steps:
       - checkout
       - run: make

+ 1 - 1
.github/workflows/build-and-push-image.yml

@@ -17,7 +17,7 @@ jobs:
       - name: Set up Go 1.x
         uses: actions/setup-go@v2
         with:
-          go-version: 1.17
+          go-version: 1.18
 
       - run: |
           # https://github.com/actions/setup-go/issues/107

+ 1 - 1
.github/workflows/goreleaser.yml

@@ -15,7 +15,7 @@ jobs:
       - name: Set up Go
         uses: actions/setup-go@v2
         with:
-          go-version: 1.17
+          go-version: 1.18
           
       - run: |
           # https://github.com/actions/setup-go/issues/107

+ 4 - 2
.github/workflows/stale.yml

@@ -12,11 +12,11 @@ jobs:
   stale:
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/stale@v3
+    - uses: actions/stale@v5
       with:
         repo-token: ${{ secrets.GITHUB_TOKEN }}
         stale-issue-message: 'Issues go stale after 30d of inactivity. Stale issues rot after an additional 7d of inactivity and eventually close.'
-        stale-pr-message: 'Issues go stale after 30d of inactivity. Stale issues rot after an additional 7d of inactivity and eventually close.'
+        stale-pr-message: "PRs go stale after 30d of inactivity. Stale PRs rot after an additional 7d of inactivity and eventually close."
         stale-issue-label: 'lifecycle/stale'
         exempt-issue-labels: 'bug,doc,enhancement,future,proposal,question,testing,todo,easy,help wanted,assigned'
         stale-pr-label: 'lifecycle/stale'
@@ -24,3 +24,5 @@ jobs:
         days-before-stale: 30
         days-before-close: 7
         debug-only: ${{ github.event.inputs.debug-only }}
+        exempt-all-pr-milestones: true
+        exempt-all-pr-assignees: true

+ 4 - 1
.goreleaser.yml

@@ -1,7 +1,10 @@
 builds:
   - skip: true
 checksum:
-  name_template: 'checksums.txt'
+  name_template: '{{ .ProjectName }}_{{ .Version }}_sha256_checksums.txt'
+  algorithm: sha256
+  extra_files:
+  - glob: ./release/packages/*
 release:
   # Same as for github
   # Note: it can only be one: either github, gitlab or gitea

+ 3 - 8
Release.md

@@ -1,13 +1,8 @@
 ### New
 
-* Added `dial_server_timeout` in frpc to specify connect timeout to frps.
-* Additional EndpointParams can be set for OIDC.
-* Added CloseProxy operation in server plugin.
+* Support go http pprof.
 
 ### Improve
 
-* Added some randomness in reconnect delay.
-
-### Fix
-
-* TLS server name is ignored when `tls_trusted_ca_file` isn’t set.
+* Change underlying TCP connection keepalive interval to 2 hours.
+* Create new connection to server for `sudp` visitor when needed, to avoid frequent reconnections.

+ 12 - 2
client/admin.go

@@ -17,6 +17,7 @@ package client
 import (
 	"net"
 	"net/http"
+	"net/http/pprof"
 	"time"
 
 	"github.com/fatedier/frp/assets"
@@ -26,8 +27,8 @@ import (
 )
 
 var (
-	httpServerReadTimeout  = 10 * time.Second
-	httpServerWriteTimeout = 10 * time.Second
+	httpServerReadTimeout  = 60 * time.Second
+	httpServerWriteTimeout = 60 * time.Second
 )
 
 func (svr *Service) RunAdminServer(address string) (err error) {
@@ -36,6 +37,15 @@ func (svr *Service) RunAdminServer(address string) (err error) {
 
 	router.HandleFunc("/healthz", svr.healthz)
 
+	// debug
+	if svr.cfg.PprofEnable {
+		router.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
+		router.HandleFunc("/debug/pprof/profile", pprof.Profile)
+		router.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
+		router.HandleFunc("/debug/pprof/trace", pprof.Trace)
+		router.PathPrefix("/debug/pprof/").HandlerFunc(pprof.Index)
+	}
+
 	subRouter := router.NewRoute().Subrouter()
 	user, passwd := svr.cfg.AdminUser, svr.cfg.AdminPwd
 	subRouter.Use(frpNet.NewHTTPAuthMiddleware(user, passwd).Middleware)

+ 1 - 0
client/control.go

@@ -252,6 +252,7 @@ func (ctl *Control) connectServer() (conn net.Conn, err error) {
 		dialOptions = append(dialOptions,
 			libdial.WithProtocol(protocol),
 			libdial.WithTimeout(time.Duration(ctl.clientCfg.DialServerTimeout)*time.Second),
+			libdial.WithKeepAlive(time.Duration(ctl.clientCfg.DialServerKeepAlive)*time.Second),
 			libdial.WithProxy(proxyType, addr),
 			libdial.WithProxyAuth(auth),
 			libdial.WithTLSConfig(tlsConfig),

+ 1 - 0
client/service.go

@@ -243,6 +243,7 @@ func (svr *Service) login() (conn net.Conn, session *fmux.Session, err error) {
 	dialOptions = append(dialOptions,
 		libdial.WithProtocol(protocol),
 		libdial.WithTimeout(time.Duration(svr.cfg.DialServerTimeout)*time.Second),
+		libdial.WithKeepAlive(time.Duration(svr.cfg.DialServerKeepAlive)*time.Second),
 		libdial.WithProxy(proxyType, addr),
 		libdial.WithProxyAuth(auth),
 		libdial.WithTLSConfig(tlsConfig),

+ 28 - 15
client/visitor.go

@@ -377,29 +377,33 @@ func (sv *SUDPVisitor) Run() (err error) {
 func (sv *SUDPVisitor) dispatcher() {
 	xl := xlog.FromContextSafe(sv.ctx)
 
+	var (
+		visitorConn net.Conn
+		err         error
+
+		firstPacket *msg.UDPPacket
+	)
+
 	for {
-		// loop for get frpc to frps tcp conn
-		// setup worker
-		// wait worker to finished
-		// retry or exit
-		visitorConn, err := sv.getNewVisitorConn()
-		if err != nil {
-			// check if proxy is closed
-			// if checkCloseCh is close, we will return, other case we will continue to reconnect
-			select {
-			case <-sv.checkCloseCh:
+		select {
+		case firstPacket = <-sv.sendCh:
+			if firstPacket == nil {
 				xl.Info("frpc sudp visitor proxy is closed")
 				return
-			default:
 			}
+		case <-sv.checkCloseCh:
+			xl.Info("frpc sudp visitor proxy is closed")
+			return
+		}
 
-			time.Sleep(3 * time.Second)
-
+		visitorConn, err = sv.getNewVisitorConn()
+		if err != nil {
 			xl.Warn("newVisitorConn to frps error: %v, try to reconnect", err)
 			continue
 		}
 
-		sv.worker(visitorConn)
+		// visitorConn always be closed when worker done.
+		sv.worker(visitorConn, firstPacket)
 
 		select {
 		case <-sv.checkCloseCh:
@@ -407,9 +411,10 @@ func (sv *SUDPVisitor) dispatcher() {
 		default:
 		}
 	}
+
 }
 
-func (sv *SUDPVisitor) worker(workConn net.Conn) {
+func (sv *SUDPVisitor) worker(workConn net.Conn, firstPacket *msg.UDPPacket) {
 	xl := xlog.FromContextSafe(sv.ctx)
 	xl.Debug("starting sudp proxy worker")
 
@@ -463,6 +468,14 @@ func (sv *SUDPVisitor) worker(workConn net.Conn) {
 		}()
 
 		var errRet error
+		if firstPacket != nil {
+			if errRet = msg.WriteMsg(conn, firstPacket); errRet != nil {
+				xl.Warn("sender goroutine for udp work connection closed: %v", errRet)
+				return
+			}
+			xl.Trace("send udp package to workConn: %s", firstPacket.Content)
+		}
+
 		for {
 			select {
 			case udpMsg, ok := <-sv.sendCh:

+ 10 - 1
conf/frpc_full.ini

@@ -9,6 +9,10 @@ server_port = 7000
 # The maximum amount of time a dial to server will wait for a connect to complete. Default value is 10 seconds.
 # dial_server_timeout = 10
 
+# dial_server_keepalive specifies the interval between keep-alive probes for an active network connection between frpc and frps.
+# If negative, keep-alive probes are disabled.
+# dial_server_keepalive = 7200
+
 # if you want to connect frps by http proxy or socks5 proxy or ntlm proxy, you can set http_proxy here or in global environment variables
 # it only works when protocol is tcp
 # http_proxy = http://user:passwd@192.168.1.128:8080
@@ -69,7 +73,8 @@ admin_pwd = admin
 pool_count = 5
 
 # if tcp stream multiplexing is used, default is true, it must be same with frps
-tcp_mux = true
+# tcp_mux = true
+
 # specify keep alive interval for tcp mux.
 # only valid if tcp_mux is true.
 # tcp_mux_keepalive_interval = 60
@@ -126,6 +131,10 @@ udp_packet_size = 1500
 # If DisableCustomTLSFirstByte is true, frpc will not send that custom byte.
 disable_custom_tls_first_byte = false
 
+# Enable golang pprof handlers in admin listener.
+# Admin port must be set first.
+pprof_enable = false
+
 # 'ssh' is the unique proxy name
 # if user in [common] section is not empty, it will be changed to {user}.{proxy} such as 'your_name.ssh'
 [ssh]

+ 10 - 2
conf/frps_full.ini

@@ -86,7 +86,6 @@ oidc_audience =
 # By default, this value is false.
 oidc_skip_expiry_check = false
 
-
 # oidc_skip_issuer_check specifies whether to skip checking if the OIDC token's issuer claim matches the issuer specified in OidcIssuer.
 # By default, this value is false.
 oidc_skip_issuer_check = false
@@ -120,11 +119,16 @@ tls_only = false
 subdomain_host = frps.com
 
 # if tcp stream multiplexing is used, default is true
-tcp_mux = true
+# tcp_mux = true
+
 # specify keep alive interval for tcp mux.
 # only valid if tcp_mux is true.
 # tcp_mux_keepalive_interval = 60
 
+# tcp_keepalive specifies the interval between keep-alive probes for an active network connection between frpc and frps.
+# If negative, keep-alive probes are disabled.
+# tcp_keepalive = 7200
+
 # custom 404 page for HTTP requests
 # custom_404_page = /path/to/404.html
 
@@ -133,6 +137,10 @@ tcp_mux = true
 # It affects the udp and sudp proxy.
 udp_packet_size = 1500
 
+# Enable golang pprof handlers in dashboard listener.
+# Dashboard port must be set first
+pprof_enable = false
+
 [plugin.user-manager]
 addr = 127.0.0.1:9000
 path = /handler

+ 1 - 1
go.mod

@@ -6,7 +6,7 @@ require (
 	github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
 	github.com/coreos/go-oidc v2.2.1+incompatible
 	github.com/fatedier/beego v0.0.0-20171024143340-6c6a4f5bd5eb
-	github.com/fatedier/golib v0.1.1-0.20220218075713-264f72dfbfd9
+	github.com/fatedier/golib v0.1.1-0.20220321042308-c306138b83ac
 	github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible
 	github.com/go-playground/validator/v10 v10.6.1
 	github.com/google/uuid v1.2.0

+ 2 - 4
go.sum

@@ -88,10 +88,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
 github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
 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.1.1-0.20220218073251-9509a597216b h1:5r5/G3NFsFK+7svxvxZYA8yy8Ubs4hWIq+QYYMgEBe8=
-github.com/fatedier/golib v0.1.1-0.20220218073251-9509a597216b/go.mod h1:fLV0TLwHqrnB/L3jbNl67Gn6PCLggDGHniX1wLrA2Qo=
-github.com/fatedier/golib v0.1.1-0.20220218075713-264f72dfbfd9 h1:AOGf9Z1ri+3MiyGIAYXe+shEXx6/uVGJlufb6ZfnZls=
-github.com/fatedier/golib v0.1.1-0.20220218075713-264f72dfbfd9/go.mod h1:fLV0TLwHqrnB/L3jbNl67Gn6PCLggDGHniX1wLrA2Qo=
+github.com/fatedier/golib v0.1.1-0.20220321042308-c306138b83ac h1:td1FJwN/oz8+9GldeEm3YdBX0Husc0FSPywLesZxi4w=
+github.com/fatedier/golib v0.1.1-0.20220321042308-c306138b83ac/go.mod h1:fLV0TLwHqrnB/L3jbNl67Gn6PCLggDGHniX1wLrA2Qo=
 github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible h1:ssXat9YXFvigNge/IkkZvFMn8yeYKFX+uI6wn2mLJ74=
 github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible/go.mod h1:YpCOaxj7vvMThhIQ9AfTOPW2sfztQR5WDfs7AflSy4s=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=

+ 8 - 0
pkg/config/client.go

@@ -40,6 +40,9 @@ type ClientCommonConf struct {
 	ServerPort int `ini:"server_port" json:"server_port"`
 	// The maximum amount of time a dial to server will wait for a connect to complete.
 	DialServerTimeout int64 `ini:"dial_server_timeout" json:"dial_server_timeout"`
+	// DialServerKeepAlive specifies the interval between keep-alive probes for an active network connection between frpc and frps.
+	// If negative, keep-alive probes are disabled.
+	DialServerKeepAlive int64 `ini:"dial_server_keepalive" json:"dial_server_keepalive"`
 	// ConnectServerLocalIP specifies the address of the client bind when it connect to server.
 	// By default, this value is empty.
 	// this value only use in TCP/Websocket protocol. Not support in KCP protocol.
@@ -151,6 +154,9 @@ type ClientCommonConf struct {
 	UDPPacketSize int64 `ini:"udp_packet_size" json:"udp_packet_size"`
 	// Include other config files for proxies.
 	IncludeConfigFiles []string `ini:"includes" json:"includes"`
+	// Enable golang pprof handlers in admin listener.
+	// Admin port must be set first.
+	PprofEnable bool `ini:"pprof_enable" json:"pprof_enable"`
 }
 
 // GetDefaultClientConf returns a client configuration with default values.
@@ -160,6 +166,7 @@ func GetDefaultClientConf() ClientCommonConf {
 		ServerAddr:              "0.0.0.0",
 		ServerPort:              7000,
 		DialServerTimeout:       10,
+		DialServerKeepAlive:     7200,
 		HTTPProxy:               os.Getenv("http_proxy"),
 		LogFile:                 "console",
 		LogWay:                  "console",
@@ -188,6 +195,7 @@ func GetDefaultClientConf() ClientCommonConf {
 		Metas:                   make(map[string]string),
 		UDPPacketSize:           1500,
 		IncludeConfigFiles:      make([]string, 0),
+		PprofEnable:             false,
 	}
 }
 

+ 1 - 0
pkg/config/client_test.go

@@ -262,6 +262,7 @@ func Test_LoadClientCommonConf(t *testing.T) {
 		ServerAddr:              "0.0.0.9",
 		ServerPort:              7009,
 		DialServerTimeout:       10,
+		DialServerKeepAlive:     7200,
 		HTTPProxy:               "http://user:passwd@192.168.1.128:8080",
 		LogFile:                 "./frpc.log9",
 		LogWay:                  "file",

+ 8 - 0
pkg/config/server.go

@@ -121,6 +121,9 @@ type ServerCommonConf struct {
 	// TCPMuxKeepaliveInterval specifies the keep alive interval for TCP stream multipler.
 	// If TCPMux is true, heartbeat of application layer is unnecessary because it can only rely on heartbeat in TCPMux.
 	TCPMuxKeepaliveInterval int64 `ini:"tcp_mux_keepalive_interval" json:"tcp_mux_keepalive_interval"`
+	// TCPKeepAlive specifies the interval between keep-alive probes for an active network connection between frpc and frps.
+	// If negative, keep-alive probes are disabled.
+	TCPKeepAlive int64 `ini:"tcp_keepalive" json:"tcp_keepalive"`
 	// Custom404Page specifies a path to a custom 404 page to display. If this
 	// value is "", a default page will be displayed. By default, this value is
 	// "".
@@ -167,6 +170,9 @@ type ServerCommonConf struct {
 	// UDPPacketSize specifies the UDP packet size
 	// By default, this value is 1500
 	UDPPacketSize int64 `ini:"udp_packet_size" json:"udp_packet_size"`
+	// Enable golang pprof handlers in dashboard listener.
+	// Dashboard port must be set first.
+	PprofEnable bool `ini:"pprof_enable" json:"pprof_enable"`
 }
 
 // GetDefaultServerConf returns a server configuration with reasonable
@@ -198,6 +204,7 @@ func GetDefaultServerConf() ServerCommonConf {
 		SubDomainHost:           "",
 		TCPMux:                  true,
 		TCPMuxKeepaliveInterval: 60,
+		TCPKeepAlive:            7200,
 		AllowPorts:              make(map[int]struct{}),
 		MaxPoolCount:            5,
 		MaxPortsPerClient:       0,
@@ -210,6 +217,7 @@ func GetDefaultServerConf() ServerCommonConf {
 		Custom404Page:           "",
 		HTTPPlugins:             make(map[string]plugin.HTTPPluginOptions),
 		UDPPacketSize:           1500,
+		PprofEnable:             false,
 	}
 }
 

+ 2 - 0
pkg/config/server_test.go

@@ -140,6 +140,7 @@ func Test_LoadServerCommonConf(t *testing.T) {
 				SubDomainHost:           "frps.com",
 				TCPMux:                  true,
 				TCPMuxKeepaliveInterval: 60,
+				TCPKeepAlive:            7200,
 				UDPPacketSize:           1509,
 
 				HTTPPlugins: map[string]plugin.HTTPPluginOptions{
@@ -191,6 +192,7 @@ func Test_LoadServerCommonConf(t *testing.T) {
 				DetailedErrorsToClient:  true,
 				TCPMux:                  true,
 				TCPMuxKeepaliveInterval: 60,
+				TCPKeepAlive:            7200,
 				AllowPorts:              make(map[int]struct{}),
 				MaxPoolCount:            5,
 				HeartbeatTimeout:        90,

+ 1 - 1
pkg/util/version/version.go

@@ -19,7 +19,7 @@ import (
 	"strings"
 )
 
-var version string = "0.40.0"
+var version string = "0.41.0"
 
 func Full() string {
 	return version

+ 12 - 2
server/dashboard.go

@@ -17,6 +17,7 @@ package server
 import (
 	"net"
 	"net/http"
+	"net/http/pprof"
 	"time"
 
 	"github.com/fatedier/frp/assets"
@@ -27,8 +28,8 @@ import (
 )
 
 var (
-	httpServerReadTimeout  = 10 * time.Second
-	httpServerWriteTimeout = 10 * time.Second
+	httpServerReadTimeout  = 60 * time.Second
+	httpServerWriteTimeout = 60 * time.Second
 )
 
 func (svr *Service) RunDashboardServer(address string) (err error) {
@@ -36,6 +37,15 @@ func (svr *Service) RunDashboardServer(address string) (err error) {
 	router := mux.NewRouter()
 	router.HandleFunc("/healthz", svr.Healthz)
 
+	// debug
+	if svr.cfg.PprofEnable {
+		router.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
+		router.HandleFunc("/debug/pprof/profile", pprof.Profile)
+		router.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
+		router.HandleFunc("/debug/pprof/trace", pprof.Trace)
+		router.PathPrefix("/debug/pprof/").HandlerFunc(pprof.Index)
+	}
+
 	subRouter := router.NewRoute().Subrouter()
 
 	user, passwd := svr.cfg.DashboardUser, svr.cfg.DashboardPwd

+ 1 - 0
server/service.go

@@ -186,6 +186,7 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
 	}
 
 	svr.muxer = mux.NewMux(ln)
+	svr.muxer.SetKeepAlive(time.Duration(cfg.TCPKeepAlive) * time.Second)
 	go svr.muxer.Serve()
 	ln = svr.muxer.DefaultListener()