Bladeren bron

support quic options (#3211)

fatedier 2 jaren geleden
bovenliggende
commit
7678938c08

+ 30 - 0
README.md

@@ -63,6 +63,7 @@ frp also has a P2P connect mode.
         * [For Each Proxy](#for-each-proxy)
     * [TCP Stream Multiplexing](#tcp-stream-multiplexing)
     * [Support KCP Protocol](#support-kcp-protocol)
+    * [Support QUIC Protocol](#support-quic-protocol)
     * [Connection Pooling](#connection-pooling)
     * [Load balancing](#load-balancing)
     * [Service Health Check](#service-health-check)
@@ -761,6 +762,35 @@ KCP mode uses UDP as the underlying transport. Using KCP in frp:
   protocol = kcp
   ```
 
+### Support QUIC Protocol
+
+QUIC is a new multiplexed transport built on top of UDP.
+
+Using QUIC in frp:
+
+1. Enable QUIC in frps:
+
+  ```ini
+  # frps.ini
+  [common]
+  bind_port = 7000
+  # Specify a UDP port for QUIC.
+  quic_bind_port = 7000
+  ```
+
+  The `quic_bind_port` number can be the same number as `bind_port`, since `bind_port` field specifies a TCP port.
+
+2. Configure `frpc.ini` to use QUIC to connect to frps:
+
+  ```ini
+  # frpc.ini
+  [common]
+  server_addr = x.x.x.x
+  # Same as the 'quic_bind_port' in frps.ini
+  server_port = 7000
+  protocol = quic
+  ```
+
 ### Connection Pooling
 
 By default, frps creates a new frpc connection to the backend service upon a user request. With connection pooling, frps keeps a certain number of pre-established connections, reducing the time needed to establish a connection.

+ 2 - 1
Release.md

@@ -1,6 +1,7 @@
 ### New
 
-* Add oidc_scope parameter to frpc when authentication_method = oidc .
+* Add `oidc_scope` parameter to frpc when `authentication_method = oidc`.
+* Support quic protocol between frpc and frps.
 
 
 ### Improve

+ 1 - 1
client/control.go

@@ -147,7 +147,7 @@ func (ctl *Control) HandleReqWorkConn(inMsg *msg.ReqWorkConn) {
 
 	var startMsg msg.StartWorkConn
 	if err = msg.ReadMsgInto(workConn, &startMsg); err != nil {
-		xl.Error("work connection closed before response StartWorkConn message: %v", err)
+		xl.Trace("work connection closed before response StartWorkConn message: %v", err)
 		workConn.Close()
 		return
 	}

+ 5 - 1
client/service.go

@@ -374,7 +374,11 @@ func (cm *ConnectionManager) OpenConnection() error {
 
 		conn, err := quic.DialAddr(
 			net.JoinHostPort(cm.cfg.ServerAddr, strconv.Itoa(cm.cfg.ServerPort)),
-			tlsConfig, nil)
+			tlsConfig, &quic.Config{
+				MaxIdleTimeout:     time.Duration(cm.cfg.QUICMaxIdleTimeout) * time.Second,
+				MaxIncomingStreams: int64(cm.cfg.QUICMaxIncomingStreams),
+				KeepAlivePeriod:    time.Duration(cm.cfg.QUICKeepalivePeriod) * time.Second,
+			})
 		if err != nil {
 			return err
 		}

+ 5 - 0
conf/frpc_full.ini

@@ -99,6 +99,11 @@ protocol = tcp
 # only when protocol = tcp or websocket, the value will be used.
 connect_server_local_ip = 0.0.0.0
 
+# quic protocol options
+# quic_keepalive_period = 10
+# quic_max_idle_timeout = 30
+# quic_max_incoming_streams = 100000
+
 # if tls_enable is true, frpc will connect frps by tls
 tls_enable = true
 

+ 4 - 0
conf/frps_full.ini

@@ -16,6 +16,10 @@ kcp_bind_port = 7000
 # udp port used for quic protocol.
 # if not set, quic is disabled in frps.
 # quic_bind_port = 7002
+# quic protocol options
+# quic_keepalive_period = 10
+# quic_max_idle_timeout = 30
+# quic_max_incoming_streams = 100000
 
 # specify which address proxy will listen for, default value is same with bind_addr
 # proxy_bind_addr = 127.0.0.1

+ 7 - 12
pkg/config/client.go

@@ -118,6 +118,10 @@ type ClientCommonConf struct {
 	// Valid values are "tcp", "kcp", "quic" and "websocket". By default, this value
 	// is "tcp".
 	Protocol string `ini:"protocol" json:"protocol"`
+	// QUIC protocol options
+	QUICKeepalivePeriod    int `ini:"quic_keepalive_period" json:"quic_keepalive_period" validate:"gte=0"`
+	QUICMaxIdleTimeout     int `ini:"quic_max_idle_timeout" json:"quic_max_idle_timeout" validate:"gte=0"`
+	QUICMaxIncomingStreams int `ini:"quic_max_incoming_streams" json:"quic_max_incoming_streams" validate:"gte=0"`
 	// TLSEnable specifies whether or not TLS should be used when communicating
 	// with the server. If "tls_cert_file" and "tls_key_file" are valid,
 	// client will load the supplied tls configuration.
@@ -172,30 +176,21 @@ func GetDefaultClientConf() ClientCommonConf {
 		LogWay:                  "console",
 		LogLevel:                "info",
 		LogMaxDays:              3,
-		DisableLogColor:         false,
 		AdminAddr:               "127.0.0.1",
-		AdminPort:               0,
-		AdminUser:               "",
-		AdminPwd:                "",
-		AssetsDir:               "",
 		PoolCount:               1,
 		TCPMux:                  true,
 		TCPMuxKeepaliveInterval: 60,
-		User:                    "",
-		DNSServer:               "",
 		LoginFailExit:           true,
 		Start:                   make([]string, 0),
 		Protocol:                "tcp",
-		TLSEnable:               false,
-		TLSCertFile:             "",
-		TLSKeyFile:              "",
-		TLSTrustedCaFile:        "",
+		QUICKeepalivePeriod:     10,
+		QUICMaxIdleTimeout:      30,
+		QUICMaxIncomingStreams:  100000,
 		HeartbeatInterval:       30,
 		HeartbeatTimeout:        90,
 		Metas:                   make(map[string]string),
 		UDPPacketSize:           1500,
 		IncludeConfigFiles:      make([]string, 0),
-		PprofEnable:             false,
 	}
 }
 

+ 3 - 0
pkg/config/client_test.go

@@ -278,6 +278,9 @@ func Test_LoadClientCommonConf(t *testing.T) {
 		User:                    "your_name",
 		LoginFailExit:           true,
 		Protocol:                "tcp",
+		QUICKeepalivePeriod:     10,
+		QUICMaxIdleTimeout:      30,
+		QUICMaxIncomingStreams:  100000,
 		TLSEnable:               true,
 		TLSCertFile:             "client.crt",
 		TLSKeyFile:              "client.key",

+ 7 - 20
pkg/config/server.go

@@ -50,6 +50,10 @@ type ServerCommonConf struct {
 	// Set this value to 0 will disable this feature.
 	// By default, the value is 0.
 	QUICBindPort int `ini:"quic_bind_port" json:"quic_bind_port" validate:"gte=0,lte=65535"`
+	// QUIC protocol options
+	QUICKeepalivePeriod    int `ini:"quic_keepalive_period" json:"quic_keepalive_period" validate:"gte=0"`
+	QUICMaxIdleTimeout     int `ini:"quic_max_idle_timeout" json:"quic_max_idle_timeout" validate:"gte=0"`
+	QUICMaxIncomingStreams int `ini:"quic_max_incoming_streams" json:"quic_max_incoming_streams" validate:"gte=0"`
 	// ProxyBindAddr specifies the address that the proxy binds to. This value
 	// may be the same as BindAddr.
 	ProxyBindAddr string `ini:"proxy_bind_addr" json:"proxy_bind_addr"`
@@ -199,43 +203,26 @@ func GetDefaultServerConf() ServerCommonConf {
 		ServerConfig:            auth.GetDefaultServerConf(),
 		BindAddr:                "0.0.0.0",
 		BindPort:                7000,
-		BindUDPPort:             0,
-		KCPBindPort:             0,
-		ProxyBindAddr:           "",
-		VhostHTTPPort:           0,
-		VhostHTTPSPort:          0,
-		TCPMuxHTTPConnectPort:   0,
-		TCPMuxPassthrough:       false,
+		QUICKeepalivePeriod:     10,
+		QUICMaxIdleTimeout:      30,
+		QUICMaxIncomingStreams:  100000,
 		VhostHTTPTimeout:        60,
 		DashboardAddr:           "0.0.0.0",
-		DashboardPort:           0,
-		DashboardUser:           "",
-		DashboardPwd:            "",
-		EnablePrometheus:        false,
-		AssetsDir:               "",
 		LogFile:                 "console",
 		LogWay:                  "console",
 		LogLevel:                "info",
 		LogMaxDays:              3,
-		DisableLogColor:         false,
 		DetailedErrorsToClient:  true,
-		SubDomainHost:           "",
 		TCPMux:                  true,
 		TCPMuxKeepaliveInterval: 60,
 		TCPKeepAlive:            7200,
 		AllowPorts:              make(map[int]struct{}),
 		MaxPoolCount:            5,
 		MaxPortsPerClient:       0,
-		TLSOnly:                 false,
-		TLSCertFile:             "",
-		TLSKeyFile:              "",
-		TLSTrustedCaFile:        "",
 		HeartbeatTimeout:        90,
 		UserConnTimeout:         10,
-		Custom404Page:           "",
 		HTTPPlugins:             make(map[string]plugin.HTTPPluginOptions),
 		UDPPacketSize:           1500,
-		PprofEnable:             false,
 	}
 }
 

+ 6 - 0
pkg/config/server_test.go

@@ -106,6 +106,9 @@ func Test_LoadServerCommonConf(t *testing.T) {
 				BindPort:               7009,
 				BindUDPPort:            7008,
 				KCPBindPort:            7007,
+				QUICKeepalivePeriod:    10,
+				QUICMaxIdleTimeout:     30,
+				QUICMaxIncomingStreams: 100000,
 				ProxyBindAddr:          "127.0.0.9",
 				VhostHTTPPort:          89,
 				VhostHTTPSPort:         449,
@@ -179,6 +182,9 @@ func Test_LoadServerCommonConf(t *testing.T) {
 				BindAddr:                "0.0.0.9",
 				BindPort:                7009,
 				BindUDPPort:             7008,
+				QUICKeepalivePeriod:     10,
+				QUICMaxIdleTimeout:      30,
+				QUICMaxIncomingStreams:  100000,
 				ProxyBindAddr:           "0.0.0.9",
 				VhostHTTPTimeout:        60,
 				DashboardAddr:           "0.0.0.0",

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

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

+ 5 - 1
server/service.go

@@ -214,7 +214,11 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) {
 		address := net.JoinHostPort(cfg.BindAddr, strconv.Itoa(cfg.QUICBindPort))
 		quicTLSCfg := tlsConfig.Clone()
 		quicTLSCfg.NextProtos = []string{"frp"}
-		svr.quicListener, err = quic.ListenAddr(address, quicTLSCfg, nil)
+		svr.quicListener, err = quic.ListenAddr(address, quicTLSCfg, &quic.Config{
+			MaxIdleTimeout:     time.Duration(cfg.QUICMaxIdleTimeout) * time.Second,
+			MaxIncomingStreams: int64(cfg.QUICMaxIncomingStreams),
+			KeepAlivePeriod:    time.Duration(cfg.QUICKeepalivePeriod) * time.Second,
+		})
 		if err != nil {
 			err = fmt.Errorf("listen on quic udp address %s error: %v", address, err)
 			return