mirror of https://github.com/fatedier/frp.git
				
				
				
			support bandwidth_limit set by server plugin (#3271)
* support bandwidth_limit set by server plugin * limiter at proxy level * bandwidth_limit_mode * updates tests for bandwidth_limit_mode default * bandwidth_limit_mode as string * add checkForSrv for bandwidth_limit_mode * bandwidth_limit flags for sub cmds * gci write
This commit is contained in:
		
							parent
							
								
									113e3b0b0d
								
							
						
					
					
						commit
						aa31d7ad0b
					
				|  | @ -713,10 +713,13 @@ type = tcp | |||
| local_port = 22 | ||||
| remote_port = 6000 | ||||
| bandwidth_limit = 1MB | ||||
| bandwidth_limit_mode = client | ||||
| ``` | ||||
| 
 | ||||
| Set `bandwidth_limit` in each proxy's configure to enable this feature. Supported units are `MB` and `KB`. | ||||
| 
 | ||||
| Set `bandwidth_limit_mode` to `client` or `server` to limit bandwidth on the client or server side. Default is `client`. | ||||
| 
 | ||||
| ### TCP Stream Multiplexing | ||||
| 
 | ||||
| frp supports tcp stream multiplexing since v0.10.0 like HTTP2 Multiplexing, in which case all logic connections to the same frpc are multiplexed into the same TCP connection. | ||||
|  |  | |||
|  | @ -54,7 +54,7 @@ type Proxy interface { | |||
| func NewProxy(ctx context.Context, pxyConf config.ProxyConf, clientCfg config.ClientCommonConf, serverUDPPort int) (pxy Proxy) { | ||||
| 	var limiter *rate.Limiter | ||||
| 	limitBytes := pxyConf.GetBaseInfo().BandwidthLimit.Bytes() | ||||
| 	if limitBytes > 0 { | ||||
| 	if limitBytes > 0 && pxyConf.GetBaseInfo().BandwidthLimitMode == config.BandwidthLimitModeClient { | ||||
| 		limiter = rate.NewLimiter(rate.Limit(float64(limitBytes)), int(limitBytes)) | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -39,6 +39,8 @@ func init() { | |||
| 	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") | ||||
| 	httpCmd.PersistentFlags().StringVarP(&bandwidthLimit, "bandwidth_limit", "", "", "bandwidth limit") | ||||
| 	httpCmd.PersistentFlags().StringVarP(&bandwidthLimitMode, "bandwidth_limit_mode", "", config.BandwidthLimitModeClient, "bandwidth limit mode") | ||||
| 
 | ||||
| 	rootCmd.AddCommand(httpCmd) | ||||
| } | ||||
|  | @ -70,6 +72,12 @@ var httpCmd = &cobra.Command{ | |||
| 		cfg.HostHeaderRewrite = hostHeaderRewrite | ||||
| 		cfg.UseEncryption = useEncryption | ||||
| 		cfg.UseCompression = useCompression | ||||
| 		cfg.BandwidthLimit, err = config.NewBandwidthQuantity(bandwidthLimit) | ||||
| 		if err != nil { | ||||
| 			fmt.Println(err) | ||||
| 			os.Exit(1) | ||||
| 		} | ||||
| 		cfg.BandwidthLimitMode = bandwidthLimitMode | ||||
| 
 | ||||
| 		err = cfg.CheckForCli() | ||||
| 		if err != nil { | ||||
|  |  | |||
|  | @ -35,6 +35,8 @@ func init() { | |||
| 	httpsCmd.PersistentFlags().StringVarP(&subDomain, "sd", "", "", "sub domain") | ||||
| 	httpsCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption") | ||||
| 	httpsCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression") | ||||
| 	httpsCmd.PersistentFlags().StringVarP(&bandwidthLimit, "bandwidth_limit", "", "", "bandwidth limit") | ||||
| 	httpsCmd.PersistentFlags().StringVarP(&bandwidthLimitMode, "bandwidth_limit_mode", "", config.BandwidthLimitModeClient, "bandwidth limit mode") | ||||
| 
 | ||||
| 	rootCmd.AddCommand(httpsCmd) | ||||
| } | ||||
|  | @ -62,6 +64,12 @@ var httpsCmd = &cobra.Command{ | |||
| 		cfg.SubDomain = subDomain | ||||
| 		cfg.UseEncryption = useEncryption | ||||
| 		cfg.UseCompression = useCompression | ||||
| 		cfg.BandwidthLimit, err = config.NewBandwidthQuantity(bandwidthLimit) | ||||
| 		if err != nil { | ||||
| 			fmt.Println(err) | ||||
| 			os.Exit(1) | ||||
| 		} | ||||
| 		cfg.BandwidthLimitMode = bandwidthLimitMode | ||||
| 
 | ||||
| 		err = cfg.CheckForCli() | ||||
| 		if err != nil { | ||||
|  |  | |||
|  | @ -60,6 +60,8 @@ var ( | |||
| 	remotePort         int | ||||
| 	useEncryption      bool | ||||
| 	useCompression     bool | ||||
| 	bandwidthLimit     string | ||||
| 	bandwidthLimitMode string | ||||
| 	customDomains      string | ||||
| 	subDomain          string | ||||
| 	httpUser           string | ||||
|  |  | |||
|  | @ -37,6 +37,8 @@ func init() { | |||
| 	stcpCmd.PersistentFlags().IntVarP(&bindPort, "bind_port", "", 0, "bind port") | ||||
| 	stcpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption") | ||||
| 	stcpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression") | ||||
| 	stcpCmd.PersistentFlags().StringVarP(&bandwidthLimit, "bandwidth_limit", "", "", "bandwidth limit") | ||||
| 	stcpCmd.PersistentFlags().StringVarP(&bandwidthLimitMode, "bandwidth_limit_mode", "", config.BandwidthLimitModeClient, "bandwidth limit mode") | ||||
| 
 | ||||
| 	rootCmd.AddCommand(stcpCmd) | ||||
| } | ||||
|  | @ -70,6 +72,12 @@ var stcpCmd = &cobra.Command{ | |||
| 			cfg.Sk = sk | ||||
| 			cfg.LocalIP = localIP | ||||
| 			cfg.LocalPort = localPort | ||||
| 			cfg.BandwidthLimit, err = config.NewBandwidthQuantity(bandwidthLimit) | ||||
| 			if err != nil { | ||||
| 				fmt.Println(err) | ||||
| 				os.Exit(1) | ||||
| 			} | ||||
| 			cfg.BandwidthLimitMode = bandwidthLimitMode | ||||
| 			err = cfg.CheckForCli() | ||||
| 			if err != nil { | ||||
| 				fmt.Println(err) | ||||
|  |  | |||
|  | @ -37,6 +37,8 @@ func init() { | |||
| 	sudpCmd.PersistentFlags().IntVarP(&bindPort, "bind_port", "", 0, "bind port") | ||||
| 	sudpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption") | ||||
| 	sudpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression") | ||||
| 	sudpCmd.PersistentFlags().StringVarP(&bandwidthLimit, "bandwidth_limit", "", "", "bandwidth limit") | ||||
| 	sudpCmd.PersistentFlags().StringVarP(&bandwidthLimitMode, "bandwidth_limit_mode", "", config.BandwidthLimitModeClient, "bandwidth limit mode") | ||||
| 
 | ||||
| 	rootCmd.AddCommand(sudpCmd) | ||||
| } | ||||
|  | @ -70,6 +72,12 @@ var sudpCmd = &cobra.Command{ | |||
| 			cfg.Sk = sk | ||||
| 			cfg.LocalIP = localIP | ||||
| 			cfg.LocalPort = localPort | ||||
| 			cfg.BandwidthLimit, err = config.NewBandwidthQuantity(bandwidthLimit) | ||||
| 			if err != nil { | ||||
| 				fmt.Println(err) | ||||
| 				os.Exit(1) | ||||
| 			} | ||||
| 			cfg.BandwidthLimitMode = bandwidthLimitMode | ||||
| 			err = cfg.CheckForCli() | ||||
| 			if err != nil { | ||||
| 				fmt.Println(err) | ||||
|  |  | |||
|  | @ -33,6 +33,8 @@ func init() { | |||
| 	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") | ||||
| 	tcpCmd.PersistentFlags().StringVarP(&bandwidthLimit, "bandwidth_limit", "", "", "bandwidth limit") | ||||
| 	tcpCmd.PersistentFlags().StringVarP(&bandwidthLimitMode, "bandwidth_limit_mode", "", config.BandwidthLimitModeClient, "bandwidth limit mode") | ||||
| 
 | ||||
| 	rootCmd.AddCommand(tcpCmd) | ||||
| } | ||||
|  | @ -59,6 +61,12 @@ var tcpCmd = &cobra.Command{ | |||
| 		cfg.RemotePort = remotePort | ||||
| 		cfg.UseEncryption = useEncryption | ||||
| 		cfg.UseCompression = useCompression | ||||
| 		cfg.BandwidthLimit, err = config.NewBandwidthQuantity(bandwidthLimit) | ||||
| 		if err != nil { | ||||
| 			fmt.Println(err) | ||||
| 			os.Exit(1) | ||||
| 		} | ||||
| 		cfg.BandwidthLimitMode = bandwidthLimitMode | ||||
| 
 | ||||
| 		err = cfg.CheckForCli() | ||||
| 		if err != nil { | ||||
|  |  | |||
|  | @ -36,6 +36,8 @@ func init() { | |||
| 	tcpMuxCmd.PersistentFlags().StringVarP(&multiplexer, "mux", "", "", "multiplexer") | ||||
| 	tcpMuxCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption") | ||||
| 	tcpMuxCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression") | ||||
| 	tcpMuxCmd.PersistentFlags().StringVarP(&bandwidthLimit, "bandwidth_limit", "", "", "bandwidth limit") | ||||
| 	tcpMuxCmd.PersistentFlags().StringVarP(&bandwidthLimitMode, "bandwidth_limit_mode", "", config.BandwidthLimitModeClient, "bandwidth limit mode") | ||||
| 
 | ||||
| 	rootCmd.AddCommand(tcpMuxCmd) | ||||
| } | ||||
|  | @ -64,6 +66,12 @@ var tcpMuxCmd = &cobra.Command{ | |||
| 		cfg.Multiplexer = multiplexer | ||||
| 		cfg.UseEncryption = useEncryption | ||||
| 		cfg.UseCompression = useCompression | ||||
| 		cfg.BandwidthLimit, err = config.NewBandwidthQuantity(bandwidthLimit) | ||||
| 		if err != nil { | ||||
| 			fmt.Println(err) | ||||
| 			os.Exit(1) | ||||
| 		} | ||||
| 		cfg.BandwidthLimitMode = bandwidthLimitMode | ||||
| 
 | ||||
| 		err = cfg.CheckForCli() | ||||
| 		if err != nil { | ||||
|  |  | |||
|  | @ -33,6 +33,8 @@ func init() { | |||
| 	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") | ||||
| 	udpCmd.PersistentFlags().StringVarP(&bandwidthLimit, "bandwidth_limit", "", "", "bandwidth limit") | ||||
| 	udpCmd.PersistentFlags().StringVarP(&bandwidthLimitMode, "bandwidth_limit_mode", "", config.BandwidthLimitModeClient, "bandwidth limit mode") | ||||
| 
 | ||||
| 	rootCmd.AddCommand(udpCmd) | ||||
| } | ||||
|  | @ -59,6 +61,12 @@ var udpCmd = &cobra.Command{ | |||
| 		cfg.RemotePort = remotePort | ||||
| 		cfg.UseEncryption = useEncryption | ||||
| 		cfg.UseCompression = useCompression | ||||
| 		cfg.BandwidthLimit, err = config.NewBandwidthQuantity(bandwidthLimit) | ||||
| 		if err != nil { | ||||
| 			fmt.Println(err) | ||||
| 			os.Exit(1) | ||||
| 		} | ||||
| 		cfg.BandwidthLimitMode = bandwidthLimitMode | ||||
| 
 | ||||
| 		err = cfg.CheckForCli() | ||||
| 		if err != nil { | ||||
|  |  | |||
|  | @ -37,6 +37,8 @@ func init() { | |||
| 	xtcpCmd.PersistentFlags().IntVarP(&bindPort, "bind_port", "", 0, "bind port") | ||||
| 	xtcpCmd.PersistentFlags().BoolVarP(&useEncryption, "ue", "", false, "use encryption") | ||||
| 	xtcpCmd.PersistentFlags().BoolVarP(&useCompression, "uc", "", false, "use compression") | ||||
| 	xtcpCmd.PersistentFlags().StringVarP(&bandwidthLimit, "bandwidth_limit", "", "", "bandwidth limit") | ||||
| 	xtcpCmd.PersistentFlags().StringVarP(&bandwidthLimitMode, "bandwidth_limit_mode", "", config.BandwidthLimitModeClient, "bandwidth limit mode") | ||||
| 
 | ||||
| 	rootCmd.AddCommand(xtcpCmd) | ||||
| } | ||||
|  | @ -70,6 +72,12 @@ var xtcpCmd = &cobra.Command{ | |||
| 			cfg.Sk = sk | ||||
| 			cfg.LocalIP = localIP | ||||
| 			cfg.LocalPort = localPort | ||||
| 			cfg.BandwidthLimit, err = config.NewBandwidthQuantity(bandwidthLimit) | ||||
| 			if err != nil { | ||||
| 				fmt.Println(err) | ||||
| 				os.Exit(1) | ||||
| 			} | ||||
| 			cfg.BandwidthLimitMode = bandwidthLimitMode | ||||
| 			err = cfg.CheckForCli() | ||||
| 			if err != nil { | ||||
| 				fmt.Println(err) | ||||
|  |  | |||
|  | @ -154,6 +154,8 @@ local_ip = 127.0.0.1 | |||
| local_port = 22 | ||||
| # limit bandwidth for this proxy, unit is KB and MB | ||||
| bandwidth_limit = 1MB | ||||
| # where to limit bandwidth, can be 'client' or 'server', default is 'client' | ||||
| bandwidth_limit_mode = client | ||||
| # true or false, if true, messages between frps and frpc will be encrypted, default is false | ||||
| use_encryption = false | ||||
| # if true, message will be compressed | ||||
|  |  | |||
|  | @ -110,6 +110,8 @@ Create new proxy | |||
|         "proxy_type": <string>, | ||||
|         "use_encryption": <bool>, | ||||
|         "use_compression": <bool>, | ||||
|         "bandwidth_limit": <string>, | ||||
|         "bandwidth_limit_mode": <string>, | ||||
|         "group": <string>, | ||||
|         "group_key": <string>, | ||||
| 
 | ||||
|  |  | |||
|  | @ -74,6 +74,7 @@ var testClientBytesWithFull = []byte(` | |||
| 		local_ip = 127.0.0.9 | ||||
| 		local_port = 29 | ||||
| 		bandwidth_limit = 19MB | ||||
| 		bandwidth_limit_mode = server | ||||
| 		use_encryption | ||||
| 		use_compression | ||||
| 		remote_port = 6009 | ||||
|  | @ -316,6 +317,7 @@ func Test_LoadClientBasicConf(t *testing.T) { | |||
| 				Group:              "test_group", | ||||
| 				GroupKey:           "123456", | ||||
| 				BandwidthLimit:     MustBandwidthQuantity("19MB"), | ||||
| 				BandwidthLimitMode: BandwidthLimitModeServer, | ||||
| 				Metas: map[string]string{ | ||||
| 					"var1": "123", | ||||
| 					"var2": "234", | ||||
|  | @ -342,6 +344,7 @@ func Test_LoadClientBasicConf(t *testing.T) { | |||
| 					LocalIP:   "127.0.0.9", | ||||
| 					LocalPort: 29, | ||||
| 				}, | ||||
| 				BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 			}, | ||||
| 			RemotePort: 9, | ||||
| 		}, | ||||
|  | @ -353,6 +356,7 @@ func Test_LoadClientBasicConf(t *testing.T) { | |||
| 					LocalIP:   "127.0.0.9", | ||||
| 					LocalPort: 6010, | ||||
| 				}, | ||||
| 				BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 			}, | ||||
| 			RemotePort: 6010, | ||||
| 		}, | ||||
|  | @ -364,6 +368,7 @@ func Test_LoadClientBasicConf(t *testing.T) { | |||
| 					LocalIP:   "127.0.0.9", | ||||
| 					LocalPort: 6011, | ||||
| 				}, | ||||
| 				BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 			}, | ||||
| 			RemotePort: 6011, | ||||
| 		}, | ||||
|  | @ -375,6 +380,7 @@ func Test_LoadClientBasicConf(t *testing.T) { | |||
| 					LocalIP:   "127.0.0.9", | ||||
| 					LocalPort: 6019, | ||||
| 				}, | ||||
| 				BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 			}, | ||||
| 			RemotePort: 6019, | ||||
| 		}, | ||||
|  | @ -388,6 +394,7 @@ func Test_LoadClientBasicConf(t *testing.T) { | |||
| 					LocalIP:   "114.114.114.114", | ||||
| 					LocalPort: 59, | ||||
| 				}, | ||||
| 				BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 			}, | ||||
| 			RemotePort: 6009, | ||||
| 		}, | ||||
|  | @ -401,6 +408,7 @@ func Test_LoadClientBasicConf(t *testing.T) { | |||
| 					LocalIP:   "114.114.114.114", | ||||
| 					LocalPort: 6000, | ||||
| 				}, | ||||
| 				BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 			}, | ||||
| 			RemotePort: 6000, | ||||
| 		}, | ||||
|  | @ -414,6 +422,7 @@ func Test_LoadClientBasicConf(t *testing.T) { | |||
| 					LocalIP:   "114.114.114.114", | ||||
| 					LocalPort: 6010, | ||||
| 				}, | ||||
| 				BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 			}, | ||||
| 			RemotePort: 6010, | ||||
| 		}, | ||||
|  | @ -427,6 +436,7 @@ func Test_LoadClientBasicConf(t *testing.T) { | |||
| 					LocalIP:   "114.114.114.114", | ||||
| 					LocalPort: 6011, | ||||
| 				}, | ||||
| 				BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 			}, | ||||
| 			RemotePort: 6011, | ||||
| 		}, | ||||
|  | @ -447,6 +457,7 @@ func Test_LoadClientBasicConf(t *testing.T) { | |||
| 					HealthCheckIntervalS: 19, | ||||
| 					HealthCheckURL:       "http://127.0.0.9:89/status", | ||||
| 				}, | ||||
| 				BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 			}, | ||||
| 			DomainConf: DomainConf{ | ||||
| 				CustomDomains: []string{"web02.yourdomain.com"}, | ||||
|  | @ -471,6 +482,7 @@ func Test_LoadClientBasicConf(t *testing.T) { | |||
| 					LocalPort: 8009, | ||||
| 				}, | ||||
| 				ProxyProtocolVersion: "v2", | ||||
| 				BandwidthLimitMode:   BandwidthLimitModeClient, | ||||
| 			}, | ||||
| 			DomainConf: DomainConf{ | ||||
| 				CustomDomains: []string{"web02.yourdomain.com"}, | ||||
|  | @ -485,6 +497,7 @@ func Test_LoadClientBasicConf(t *testing.T) { | |||
| 					LocalIP:   "127.0.0.1", | ||||
| 					LocalPort: 22, | ||||
| 				}, | ||||
| 				BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 			}, | ||||
| 			Role: "server", | ||||
| 			Sk:   "abcdefg", | ||||
|  | @ -497,6 +510,7 @@ func Test_LoadClientBasicConf(t *testing.T) { | |||
| 					LocalIP:   "127.0.0.1", | ||||
| 					LocalPort: 22, | ||||
| 				}, | ||||
| 				BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 			}, | ||||
| 			Role: "server", | ||||
| 			Sk:   "abcdefg", | ||||
|  | @ -509,6 +523,7 @@ func Test_LoadClientBasicConf(t *testing.T) { | |||
| 					LocalIP:   "127.0.0.1", | ||||
| 					LocalPort: 10701, | ||||
| 				}, | ||||
| 				BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 			}, | ||||
| 			DomainConf: DomainConf{ | ||||
| 				CustomDomains: []string{"tunnel1"}, | ||||
|  | @ -527,6 +542,7 @@ func Test_LoadClientBasicConf(t *testing.T) { | |||
| 						"plugin_unix_path": "/var/run/docker.sock", | ||||
| 					}, | ||||
| 				}, | ||||
| 				BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 			}, | ||||
| 			RemotePort: 6003, | ||||
| 		}, | ||||
|  | @ -542,6 +558,7 @@ func Test_LoadClientBasicConf(t *testing.T) { | |||
| 						"plugin_http_passwd": "abc", | ||||
| 					}, | ||||
| 				}, | ||||
| 				BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 			}, | ||||
| 			RemotePort: 6004, | ||||
| 		}, | ||||
|  | @ -557,6 +574,7 @@ func Test_LoadClientBasicConf(t *testing.T) { | |||
| 						"plugin_passwd": "abc", | ||||
| 					}, | ||||
| 				}, | ||||
| 				BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 			}, | ||||
| 			RemotePort: 6005, | ||||
| 		}, | ||||
|  | @ -574,6 +592,7 @@ func Test_LoadClientBasicConf(t *testing.T) { | |||
| 						"plugin_http_passwd":  "abc", | ||||
| 					}, | ||||
| 				}, | ||||
| 				BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 			}, | ||||
| 			RemotePort: 6006, | ||||
| 		}, | ||||
|  | @ -592,6 +611,7 @@ func Test_LoadClientBasicConf(t *testing.T) { | |||
| 						"plugin_header_X-From-Where": "frp", | ||||
| 					}, | ||||
| 				}, | ||||
| 				BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 			}, | ||||
| 			DomainConf: DomainConf{ | ||||
| 				CustomDomains: []string{"test.yourdomain.com"}, | ||||
|  | @ -610,6 +630,7 @@ func Test_LoadClientBasicConf(t *testing.T) { | |||
| 						"plugin_header_X-From-Where": "frp", | ||||
| 					}, | ||||
| 				}, | ||||
| 				BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 			}, | ||||
| 			DomainConf: DomainConf{ | ||||
| 				CustomDomains: []string{"test.yourdomain.com"}, | ||||
|  |  | |||
|  | @ -141,6 +141,10 @@ type BaseProxyConf struct { | |||
| 	// BandwidthLimit limit the bandwidth
 | ||||
| 	// 0 means no limit
 | ||||
| 	BandwidthLimit BandwidthQuantity `ini:"bandwidth_limit" json:"bandwidth_limit"` | ||||
| 	// BandwidthLimitMode specifies whether to limit the bandwidth on the
 | ||||
| 	// client or server side. Valid values include "client" and "server".
 | ||||
| 	// By default, this value is "client".
 | ||||
| 	BandwidthLimitMode string `ini:"bandwidth_limit_mode" json:"bandwidth_limit_mode"` | ||||
| 
 | ||||
| 	// meta info for each proxy
 | ||||
| 	Metas map[string]string `ini:"-" json:"metas"` | ||||
|  | @ -319,6 +323,7 @@ func defaultBaseProxyConf(proxyType string) BaseProxyConf { | |||
| 		LocalSvrConf: LocalSvrConf{ | ||||
| 			LocalIP: "127.0.0.1", | ||||
| 		}, | ||||
| 		BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -335,6 +340,7 @@ func (cfg *BaseProxyConf) compare(cmp *BaseProxyConf) bool { | |||
| 		cfg.GroupKey != cmp.GroupKey || | ||||
| 		cfg.ProxyProtocolVersion != cmp.ProxyProtocolVersion || | ||||
| 		!cfg.BandwidthLimit.Equal(&cmp.BandwidthLimit) || | ||||
| 		cfg.BandwidthLimitMode != cmp.BandwidthLimitMode || | ||||
| 		!reflect.DeepEqual(cfg.Metas, cmp.Metas) { | ||||
| 		return false | ||||
| 	} | ||||
|  | @ -389,6 +395,8 @@ func (cfg *BaseProxyConf) marshalToMsg(pMsg *msg.NewProxy) { | |||
| 	pMsg.ProxyType = cfg.ProxyType | ||||
| 	pMsg.UseEncryption = cfg.UseEncryption | ||||
| 	pMsg.UseCompression = cfg.UseCompression | ||||
| 	pMsg.BandwidthLimit = cfg.BandwidthLimit.String() | ||||
| 	pMsg.BandwidthLimitMode = cfg.BandwidthLimitMode | ||||
| 	pMsg.Group = cfg.Group | ||||
| 	pMsg.GroupKey = cfg.GroupKey | ||||
| 	pMsg.Metas = cfg.Metas | ||||
|  | @ -399,6 +407,8 @@ func (cfg *BaseProxyConf) unmarshalFromMsg(pMsg *msg.NewProxy) { | |||
| 	cfg.ProxyType = pMsg.ProxyType | ||||
| 	cfg.UseEncryption = pMsg.UseEncryption | ||||
| 	cfg.UseCompression = pMsg.UseCompression | ||||
| 	cfg.BandwidthLimit, _ = NewBandwidthQuantity(pMsg.BandwidthLimit) | ||||
| 	cfg.BandwidthLimitMode = pMsg.BandwidthLimitMode | ||||
| 	cfg.Group = pMsg.Group | ||||
| 	cfg.GroupKey = pMsg.GroupKey | ||||
| 	cfg.Metas = pMsg.Metas | ||||
|  | @ -411,6 +421,10 @@ func (cfg *BaseProxyConf) checkForCli() (err error) { | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if cfg.BandwidthLimitMode != "client" && cfg.BandwidthLimitMode != "server" { | ||||
| 		return fmt.Errorf("bandwidth_limit_mode should be client or server") | ||||
| 	} | ||||
| 
 | ||||
| 	if err = cfg.LocalSvrConf.checkForCli(); err != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | @ -420,6 +434,13 @@ func (cfg *BaseProxyConf) checkForCli() (err error) { | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (cfg *BaseProxyConf) checkForSvr() (err error) { | ||||
| 	if cfg.BandwidthLimitMode != "client" && cfg.BandwidthLimitMode != "server" { | ||||
| 		return fmt.Errorf("bandwidth_limit_mode should be client or server") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // DomainConf
 | ||||
| func (cfg *DomainConf) check() (err error) { | ||||
| 	if len(cfg.CustomDomains) == 0 && cfg.SubDomain == "" { | ||||
|  | @ -557,6 +578,9 @@ func (cfg *TCPProxyConf) CheckForCli() (err error) { | |||
| } | ||||
| 
 | ||||
| func (cfg *TCPProxyConf) CheckForSvr(serverCfg ServerCommonConf) error { | ||||
| 	if err := cfg.BaseProxyConf.checkForSvr(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
|  | @ -632,6 +656,10 @@ func (cfg *TCPMuxProxyConf) CheckForCli() (err error) { | |||
| } | ||||
| 
 | ||||
| func (cfg *TCPMuxProxyConf) CheckForSvr(serverCfg ServerCommonConf) (err error) { | ||||
| 	if err := cfg.BaseProxyConf.checkForSvr(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	if cfg.Multiplexer != consts.HTTPConnectTCPMultiplexer { | ||||
| 		return fmt.Errorf("proxy [%s] incorrect multiplexer [%s]", cfg.ProxyName, cfg.Multiplexer) | ||||
| 	} | ||||
|  | @ -703,6 +731,9 @@ func (cfg *UDPProxyConf) CheckForCli() (err error) { | |||
| } | ||||
| 
 | ||||
| func (cfg *UDPProxyConf) CheckForSvr(serverCfg ServerCommonConf) error { | ||||
| 	if err := cfg.BaseProxyConf.checkForSvr(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
|  | @ -788,6 +819,10 @@ func (cfg *HTTPProxyConf) CheckForCli() (err error) { | |||
| } | ||||
| 
 | ||||
| func (cfg *HTTPProxyConf) CheckForSvr(serverCfg ServerCommonConf) (err error) { | ||||
| 	if err := cfg.BaseProxyConf.checkForSvr(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	if serverCfg.VhostHTTPPort == 0 { | ||||
| 		return fmt.Errorf("type [http] not support when vhost_http_port is not set") | ||||
| 	} | ||||
|  | @ -860,6 +895,10 @@ func (cfg *HTTPSProxyConf) CheckForCli() (err error) { | |||
| } | ||||
| 
 | ||||
| func (cfg *HTTPSProxyConf) CheckForSvr(serverCfg ServerCommonConf) (err error) { | ||||
| 	if err := cfg.BaseProxyConf.checkForSvr(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	if serverCfg.VhostHTTPSPort == 0 { | ||||
| 		return fmt.Errorf("type [https] not support when vhost_https_port is not set") | ||||
| 	} | ||||
|  | @ -932,6 +971,9 @@ func (cfg *SUDPProxyConf) CheckForCli() (err error) { | |||
| } | ||||
| 
 | ||||
| func (cfg *SUDPProxyConf) CheckForSvr(serverCfg ServerCommonConf) error { | ||||
| 	if err := cfg.BaseProxyConf.checkForSvr(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
|  | @ -998,6 +1040,9 @@ func (cfg *STCPProxyConf) CheckForCli() (err error) { | |||
| } | ||||
| 
 | ||||
| func (cfg *STCPProxyConf) CheckForSvr(serverCfg ServerCommonConf) error { | ||||
| 	if err := cfg.BaseProxyConf.checkForSvr(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
|  | @ -1064,5 +1109,8 @@ func (cfg *XTCPProxyConf) CheckForCli() (err error) { | |||
| } | ||||
| 
 | ||||
| func (cfg *XTCPProxyConf) CheckForSvr(serverCfg ServerCommonConf) error { | ||||
| 	if err := cfg.BaseProxyConf.checkForSvr(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  |  | |||
|  | @ -58,6 +58,7 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) { | |||
| 				local_ip = 127.0.0.9 | ||||
| 				local_port = 29 | ||||
| 				bandwidth_limit = 19MB | ||||
| 				bandwidth_limit_mode = server | ||||
| 				use_encryption | ||||
| 				use_compression | ||||
| 				remote_port = 6009 | ||||
|  | @ -78,6 +79,7 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) { | |||
| 					Group:              "test_group", | ||||
| 					GroupKey:           "123456", | ||||
| 					BandwidthLimit:     MustBandwidthQuantity("19MB"), | ||||
| 					BandwidthLimitMode: BandwidthLimitModeServer, | ||||
| 					Metas: map[string]string{ | ||||
| 						"var1": "123", | ||||
| 						"var2": "234", | ||||
|  | @ -114,6 +116,7 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) { | |||
| 						LocalIP:   "127.0.0.9", | ||||
| 						LocalPort: 29, | ||||
| 					}, | ||||
| 					BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 				}, | ||||
| 				RemotePort: 9, | ||||
| 			}, | ||||
|  | @ -139,6 +142,7 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) { | |||
| 						LocalIP:   "114.114.114.114", | ||||
| 						LocalPort: 59, | ||||
| 					}, | ||||
| 					BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 				}, | ||||
| 				RemotePort: 6009, | ||||
| 			}, | ||||
|  | @ -182,6 +186,7 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) { | |||
| 						HealthCheckIntervalS: 19, | ||||
| 						HealthCheckURL:       "http://127.0.0.9:89/status", | ||||
| 					}, | ||||
| 					BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 				}, | ||||
| 				DomainConf: DomainConf{ | ||||
| 					CustomDomains: []string{"web02.yourdomain.com"}, | ||||
|  | @ -220,6 +225,7 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) { | |||
| 						LocalPort: 8009, | ||||
| 					}, | ||||
| 					ProxyProtocolVersion: "v2", | ||||
| 					BandwidthLimitMode:   BandwidthLimitModeClient, | ||||
| 				}, | ||||
| 				DomainConf: DomainConf{ | ||||
| 					CustomDomains: []string{"web02.yourdomain.com"}, | ||||
|  | @ -246,6 +252,7 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) { | |||
| 						LocalIP:   "127.0.0.1", | ||||
| 						LocalPort: 22, | ||||
| 					}, | ||||
| 					BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 				}, | ||||
| 				Role: "server", | ||||
| 				Sk:   "abcdefg", | ||||
|  | @ -270,6 +277,7 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) { | |||
| 						LocalIP:   "127.0.0.1", | ||||
| 						LocalPort: 22, | ||||
| 					}, | ||||
| 					BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 				}, | ||||
| 				Role: "server", | ||||
| 				Sk:   "abcdefg", | ||||
|  | @ -293,6 +301,7 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) { | |||
| 						LocalIP:   "127.0.0.1", | ||||
| 						LocalPort: 10701, | ||||
| 					}, | ||||
| 					BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 				}, | ||||
| 				DomainConf: DomainConf{ | ||||
| 					CustomDomains: []string{"tunnel1"}, | ||||
|  | @ -347,6 +356,7 @@ func Test_RangeProxy_UnmarshalFromIni(t *testing.T) { | |||
| 							LocalIP:   "127.0.0.9", | ||||
| 							LocalPort: 6010, | ||||
| 						}, | ||||
| 						BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 					}, | ||||
| 					RemotePort: 6010, | ||||
| 				}, | ||||
|  | @ -358,6 +368,7 @@ func Test_RangeProxy_UnmarshalFromIni(t *testing.T) { | |||
| 							LocalIP:   "127.0.0.9", | ||||
| 							LocalPort: 6011, | ||||
| 						}, | ||||
| 						BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 					}, | ||||
| 					RemotePort: 6011, | ||||
| 				}, | ||||
|  | @ -369,6 +380,7 @@ func Test_RangeProxy_UnmarshalFromIni(t *testing.T) { | |||
| 							LocalIP:   "127.0.0.9", | ||||
| 							LocalPort: 6019, | ||||
| 						}, | ||||
| 						BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 					}, | ||||
| 					RemotePort: 6019, | ||||
| 				}, | ||||
|  | @ -396,6 +408,7 @@ func Test_RangeProxy_UnmarshalFromIni(t *testing.T) { | |||
| 							LocalIP:   "114.114.114.114", | ||||
| 							LocalPort: 6000, | ||||
| 						}, | ||||
| 						BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 					}, | ||||
| 					RemotePort: 6000, | ||||
| 				}, | ||||
|  | @ -409,6 +422,7 @@ func Test_RangeProxy_UnmarshalFromIni(t *testing.T) { | |||
| 							LocalIP:   "114.114.114.114", | ||||
| 							LocalPort: 6010, | ||||
| 						}, | ||||
| 						BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 					}, | ||||
| 					RemotePort: 6010, | ||||
| 				}, | ||||
|  | @ -422,6 +436,7 @@ func Test_RangeProxy_UnmarshalFromIni(t *testing.T) { | |||
| 							LocalIP:   "114.114.114.114", | ||||
| 							LocalPort: 6011, | ||||
| 						}, | ||||
| 						BandwidthLimitMode: BandwidthLimitModeClient, | ||||
| 					}, | ||||
| 					RemotePort: 6011, | ||||
| 				}, | ||||
|  |  | |||
|  | @ -24,6 +24,9 @@ import ( | |||
| const ( | ||||
| 	MB = 1024 * 1024 | ||||
| 	KB = 1024 | ||||
| 
 | ||||
| 	BandwidthLimitModeClient = "client" | ||||
| 	BandwidthLimitModeServer = "server" | ||||
| ) | ||||
| 
 | ||||
| type BandwidthQuantity struct { | ||||
|  |  | |||
|  | @ -14,7 +14,9 @@ | |||
| 
 | ||||
| package msg | ||||
| 
 | ||||
| import "net" | ||||
| import ( | ||||
| 	"net" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	TypeLogin                 = 'o' | ||||
|  | @ -87,6 +89,8 @@ type NewProxy struct { | |||
| 	ProxyType          string            `json:"proxy_type,omitempty"` | ||||
| 	UseEncryption      bool              `json:"use_encryption,omitempty"` | ||||
| 	UseCompression     bool              `json:"use_compression,omitempty"` | ||||
| 	BandwidthLimit     string            `json:"bandwidth_limit,omitempty"` | ||||
| 	BandwidthLimitMode string            `json:"bandwidth_limit_mode,omitempty"` | ||||
| 	Group              string            `json:"group,omitempty"` | ||||
| 	GroupKey           string            `json:"group_key,omitempty"` | ||||
| 	Metas              map[string]string `json:"metas,omitempty"` | ||||
|  |  | |||
|  | @ -20,8 +20,10 @@ import ( | |||
| 	"strings" | ||||
| 
 | ||||
| 	frpIo "github.com/fatedier/golib/io" | ||||
| 	"golang.org/x/time/rate" | ||||
| 
 | ||||
| 	"github.com/fatedier/frp/pkg/config" | ||||
| 	"github.com/fatedier/frp/pkg/util/limit" | ||||
| 	frpNet "github.com/fatedier/frp/pkg/util/net" | ||||
| 	"github.com/fatedier/frp/pkg/util/util" | ||||
| 	"github.com/fatedier/frp/pkg/util/vhost" | ||||
|  | @ -135,6 +137,10 @@ func (pxy *HTTPProxy) GetConf() config.ProxyConf { | |||
| 	return pxy.cfg | ||||
| } | ||||
| 
 | ||||
| func (pxy *HTTPProxy) GetLimiter() *rate.Limiter { | ||||
| 	return pxy.limiter | ||||
| } | ||||
| 
 | ||||
| func (pxy *HTTPProxy) GetRealConn(remoteAddr string) (workConn net.Conn, err error) { | ||||
| 	xl := pxy.xl | ||||
| 	rAddr, errRet := net.ResolveTCPAddr("tcp", remoteAddr) | ||||
|  | @ -160,6 +166,13 @@ func (pxy *HTTPProxy) GetRealConn(remoteAddr string) (workConn net.Conn, err err | |||
| 	if pxy.cfg.UseCompression { | ||||
| 		rwc = frpIo.WithCompression(rwc) | ||||
| 	} | ||||
| 
 | ||||
| 	if pxy.GetLimiter() != nil { | ||||
| 		rwc = frpIo.WrapReadWriteCloser(limit.NewReader(rwc, pxy.GetLimiter()), limit.NewWriter(rwc, pxy.GetLimiter()), func() error { | ||||
| 			return rwc.Close() | ||||
| 		}) | ||||
| 	} | ||||
| 
 | ||||
| 	workConn = frpNet.WrapReadWriteCloserToConn(rwc, tmpConn) | ||||
| 	workConn = frpNet.WrapStatsConn(workConn, pxy.updateStatsAfterClosedConn) | ||||
| 	metrics.Server.OpenConnection(pxy.GetName(), pxy.GetConf().GetBaseInfo().ProxyType) | ||||
|  |  | |||
|  | @ -17,6 +17,8 @@ package proxy | |||
| import ( | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"golang.org/x/time/rate" | ||||
| 
 | ||||
| 	"github.com/fatedier/frp/pkg/config" | ||||
| 	"github.com/fatedier/frp/pkg/util/util" | ||||
| 	"github.com/fatedier/frp/pkg/util/vhost" | ||||
|  | @ -74,6 +76,10 @@ func (pxy *HTTPSProxy) GetConf() config.ProxyConf { | |||
| 	return pxy.cfg | ||||
| } | ||||
| 
 | ||||
| func (pxy *HTTPSProxy) GetLimiter() *rate.Limiter { | ||||
| 	return pxy.limiter | ||||
| } | ||||
| 
 | ||||
| func (pxy *HTTPSProxy) Close() { | ||||
| 	pxy.BaseProxy.Close() | ||||
| } | ||||
|  |  | |||
|  | @ -24,10 +24,12 @@ import ( | |||
| 	"time" | ||||
| 
 | ||||
| 	frpIo "github.com/fatedier/golib/io" | ||||
| 	"golang.org/x/time/rate" | ||||
| 
 | ||||
| 	"github.com/fatedier/frp/pkg/config" | ||||
| 	"github.com/fatedier/frp/pkg/msg" | ||||
| 	plugin "github.com/fatedier/frp/pkg/plugin/server" | ||||
| 	"github.com/fatedier/frp/pkg/util/limit" | ||||
| 	frpNet "github.com/fatedier/frp/pkg/util/net" | ||||
| 	"github.com/fatedier/frp/pkg/util/xlog" | ||||
| 	"github.com/fatedier/frp/server/controller" | ||||
|  | @ -45,6 +47,7 @@ type Proxy interface { | |||
| 	GetUsedPortsNum() int | ||||
| 	GetResourceController() *controller.ResourceController | ||||
| 	GetUserInfo() plugin.UserInfo | ||||
| 	GetLimiter() *rate.Limiter | ||||
| 	Close() | ||||
| } | ||||
| 
 | ||||
|  | @ -56,6 +59,7 @@ type BaseProxy struct { | |||
| 	poolCount     int | ||||
| 	getWorkConnFn GetWorkConnFn | ||||
| 	serverCfg     config.ServerCommonConf | ||||
| 	limiter       *rate.Limiter | ||||
| 	userInfo      plugin.UserInfo | ||||
| 
 | ||||
| 	mu  sync.RWMutex | ||||
|  | @ -187,6 +191,13 @@ func NewProxy(ctx context.Context, userInfo plugin.UserInfo, rc *controller.Reso | |||
| 	getWorkConnFn GetWorkConnFn, pxyConf config.ProxyConf, serverCfg config.ServerCommonConf, | ||||
| ) (pxy Proxy, err error) { | ||||
| 	xl := xlog.FromContextSafe(ctx).Spawn().AppendPrefix(pxyConf.GetBaseInfo().ProxyName) | ||||
| 
 | ||||
| 	var limiter *rate.Limiter | ||||
| 	limitBytes := pxyConf.GetBaseInfo().BandwidthLimit.Bytes() | ||||
| 	if limitBytes > 0 && pxyConf.GetBaseInfo().BandwidthLimitMode == config.BandwidthLimitModeServer { | ||||
| 		limiter = rate.NewLimiter(rate.Limit(float64(limitBytes)), int(limitBytes)) | ||||
| 	} | ||||
| 
 | ||||
| 	basePxy := BaseProxy{ | ||||
| 		name:          pxyConf.GetBaseInfo().ProxyName, | ||||
| 		rc:            rc, | ||||
|  | @ -194,6 +205,7 @@ func NewProxy(ctx context.Context, userInfo plugin.UserInfo, rc *controller.Reso | |||
| 		poolCount:     poolCount, | ||||
| 		getWorkConnFn: getWorkConnFn, | ||||
| 		serverCfg:     serverCfg, | ||||
| 		limiter:       limiter, | ||||
| 		xl:            xl, | ||||
| 		ctx:           xlog.NewContext(ctx, xl), | ||||
| 		userInfo:      userInfo, | ||||
|  | @ -287,6 +299,13 @@ func HandleUserTCPConnection(pxy Proxy, userConn net.Conn, serverCfg config.Serv | |||
| 	if cfg.UseCompression { | ||||
| 		local = frpIo.WithCompression(local) | ||||
| 	} | ||||
| 
 | ||||
| 	if pxy.GetLimiter() != nil { | ||||
| 		local = frpIo.WrapReadWriteCloser(limit.NewReader(local, pxy.GetLimiter()), limit.NewWriter(local, pxy.GetLimiter()), func() error { | ||||
| 			return local.Close() | ||||
| 		}) | ||||
| 	} | ||||
| 
 | ||||
| 	xl.Debug("join connections, workConn(l[%s] r[%s]) userConn(l[%s] r[%s])", workConn.LocalAddr().String(), | ||||
| 		workConn.RemoteAddr().String(), userConn.LocalAddr().String(), userConn.RemoteAddr().String()) | ||||
| 
 | ||||
|  |  | |||
|  | @ -15,6 +15,8 @@ | |||
| package proxy | ||||
| 
 | ||||
| import ( | ||||
| 	"golang.org/x/time/rate" | ||||
| 
 | ||||
| 	"github.com/fatedier/frp/pkg/config" | ||||
| ) | ||||
| 
 | ||||
|  | @ -41,6 +43,10 @@ func (pxy *STCPProxy) GetConf() config.ProxyConf { | |||
| 	return pxy.cfg | ||||
| } | ||||
| 
 | ||||
| func (pxy *STCPProxy) GetLimiter() *rate.Limiter { | ||||
| 	return pxy.limiter | ||||
| } | ||||
| 
 | ||||
| func (pxy *STCPProxy) Close() { | ||||
| 	pxy.BaseProxy.Close() | ||||
| 	pxy.rc.VisitorManager.CloseListener(pxy.GetName()) | ||||
|  |  | |||
|  | @ -15,6 +15,8 @@ | |||
| package proxy | ||||
| 
 | ||||
| import ( | ||||
| 	"golang.org/x/time/rate" | ||||
| 
 | ||||
| 	"github.com/fatedier/frp/pkg/config" | ||||
| ) | ||||
| 
 | ||||
|  | @ -42,6 +44,10 @@ func (pxy *SUDPProxy) GetConf() config.ProxyConf { | |||
| 	return pxy.cfg | ||||
| } | ||||
| 
 | ||||
| func (pxy *SUDPProxy) GetLimiter() *rate.Limiter { | ||||
| 	return pxy.limiter | ||||
| } | ||||
| 
 | ||||
| func (pxy *SUDPProxy) Close() { | ||||
| 	pxy.BaseProxy.Close() | ||||
| 	pxy.rc.VisitorManager.CloseListener(pxy.GetName()) | ||||
|  |  | |||
|  | @ -19,6 +19,8 @@ import ( | |||
| 	"net" | ||||
| 	"strconv" | ||||
| 
 | ||||
| 	"golang.org/x/time/rate" | ||||
| 
 | ||||
| 	"github.com/fatedier/frp/pkg/config" | ||||
| ) | ||||
| 
 | ||||
|  | @ -74,6 +76,10 @@ func (pxy *TCPProxy) GetConf() config.ProxyConf { | |||
| 	return pxy.cfg | ||||
| } | ||||
| 
 | ||||
| func (pxy *TCPProxy) GetLimiter() *rate.Limiter { | ||||
| 	return pxy.limiter | ||||
| } | ||||
| 
 | ||||
| func (pxy *TCPProxy) Close() { | ||||
| 	pxy.BaseProxy.Close() | ||||
| 	if pxy.cfg.Group == "" { | ||||
|  |  | |||
|  | @ -19,6 +19,8 @@ import ( | |||
| 	"net" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"golang.org/x/time/rate" | ||||
| 
 | ||||
| 	"github.com/fatedier/frp/pkg/config" | ||||
| 	"github.com/fatedier/frp/pkg/consts" | ||||
| 	"github.com/fatedier/frp/pkg/util/util" | ||||
|  | @ -94,6 +96,10 @@ func (pxy *TCPMuxProxy) GetConf() config.ProxyConf { | |||
| 	return pxy.cfg | ||||
| } | ||||
| 
 | ||||
| func (pxy *TCPMuxProxy) GetLimiter() *rate.Limiter { | ||||
| 	return pxy.limiter | ||||
| } | ||||
| 
 | ||||
| func (pxy *TCPMuxProxy) Close() { | ||||
| 	pxy.BaseProxy.Close() | ||||
| } | ||||
|  |  | |||
|  | @ -24,10 +24,12 @@ import ( | |||
| 
 | ||||
| 	"github.com/fatedier/golib/errors" | ||||
| 	frpIo "github.com/fatedier/golib/io" | ||||
| 	"golang.org/x/time/rate" | ||||
| 
 | ||||
| 	"github.com/fatedier/frp/pkg/config" | ||||
| 	"github.com/fatedier/frp/pkg/msg" | ||||
| 	"github.com/fatedier/frp/pkg/proto/udp" | ||||
| 	"github.com/fatedier/frp/pkg/util/limit" | ||||
| 	frpNet "github.com/fatedier/frp/pkg/util/net" | ||||
| 	"github.com/fatedier/frp/server/metrics" | ||||
| ) | ||||
|  | @ -198,6 +200,12 @@ func (pxy *UDPProxy) Run() (remoteAddr string, err error) { | |||
| 				rwc = frpIo.WithCompression(rwc) | ||||
| 			} | ||||
| 
 | ||||
| 			if pxy.GetLimiter() != nil { | ||||
| 				rwc = frpIo.WrapReadWriteCloser(limit.NewReader(rwc, pxy.GetLimiter()), limit.NewWriter(rwc, pxy.GetLimiter()), func() error { | ||||
| 					return rwc.Close() | ||||
| 				}) | ||||
| 			} | ||||
| 
 | ||||
| 			pxy.workConn = frpNet.WrapReadWriteCloserToConn(rwc, workConn) | ||||
| 			ctx, cancel := context.WithCancel(context.Background()) | ||||
| 			go workConnReaderFn(pxy.workConn) | ||||
|  | @ -225,6 +233,10 @@ func (pxy *UDPProxy) GetConf() config.ProxyConf { | |||
| 	return pxy.cfg | ||||
| } | ||||
| 
 | ||||
| func (pxy *UDPProxy) GetLimiter() *rate.Limiter { | ||||
| 	return pxy.limiter | ||||
| } | ||||
| 
 | ||||
| func (pxy *UDPProxy) Close() { | ||||
| 	pxy.mu.Lock() | ||||
| 	defer pxy.mu.Unlock() | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ import ( | |||
| 	"fmt" | ||||
| 
 | ||||
| 	"github.com/fatedier/golib/errors" | ||||
| 	"golang.org/x/time/rate" | ||||
| 
 | ||||
| 	"github.com/fatedier/frp/pkg/config" | ||||
| 	"github.com/fatedier/frp/pkg/msg" | ||||
|  | @ -88,6 +89,10 @@ func (pxy *XTCPProxy) GetConf() config.ProxyConf { | |||
| 	return pxy.cfg | ||||
| } | ||||
| 
 | ||||
| func (pxy *XTCPProxy) GetLimiter() *rate.Limiter { | ||||
| 	return pxy.limiter | ||||
| } | ||||
| 
 | ||||
| func (pxy *XTCPProxy) Close() { | ||||
| 	pxy.BaseProxy.Close() | ||||
| 	pxy.rc.NatHoleController.CloseClient(pxy.GetName()) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue