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

all: privilege_allow_ports can be set in frps for ending abuse of ports

fatedier 8 жил өмнө
parent
commit
ecb6ad4885

+ 1 - 0
conf/frps.ini

@@ -15,6 +15,7 @@ log_max_days = 3
 # if you enable privilege mode, frpc can create a proxy without pre-configure in frps when privilege_token is correct
 privilege_mode = true
 privilege_token = 12345678
+privilege_allow_ports = 2000-3000,3001,3003,4000-50000
 # pool_count in each proxy will change to max_pool_count if they exceed the maximum value
 max_pool_count = 100
 

+ 17 - 6
src/frp/cmd/frps/control.go

@@ -194,6 +194,7 @@ func msgSender(s *server.ProxyServer, c *conn.Conn, msgSendChan chan interface{}
 // if success, ret equals 0, otherwise greater than 0
 func doLogin(req *msg.ControlReq, c *conn.Conn) (ret int64, info string) {
 	ret = 1
+	// check if PrivilegeMode is enabled
 	if req.PrivilegeMode && !server.PrivilegeMode {
 		info = fmt.Sprintf("ProxyName [%s], PrivilegeMode is disabled in frps", req.ProxyName)
 		log.Warn("info")
@@ -247,6 +248,16 @@ func doLogin(req *msg.ControlReq, c *conn.Conn) (ret int64, info string) {
 	if req.Type == consts.NewCtlConn {
 		if req.PrivilegeMode {
 			s = server.NewProxyServerFromCtlMsg(req)
+			// we check listen_port if privilege_allow_ports are set
+			// and PrivilegeMode is enabled
+			if s.Type == "tcp" {
+				_, ok := server.PrivilegeAllowPorts[s.ListenPort]
+				if !ok {
+					info = fmt.Sprintf("ProxyName [%s], remote_port [%d] isn't allowed", req.ProxyName, s.ListenPort)
+					log.Warn(info)
+					return
+				}
+			}
 			err := server.CreateProxy(s)
 			if err != nil {
 				info = fmt.Sprintf("ProxyName [%s], %v", req.ProxyName, err)
@@ -255,12 +266,6 @@ func doLogin(req *msg.ControlReq, c *conn.Conn) (ret int64, info string) {
 			}
 		}
 
-		if s.Status == consts.Working {
-			info = fmt.Sprintf("ProxyName [%s], already in use", req.ProxyName)
-			log.Warn(info)
-			return
-		}
-
 		// check if vhost_port is set
 		if s.Type == "http" && server.VhostHttpMuxer == nil {
 			info = fmt.Sprintf("ProxyName [%s], type [http] not support when vhost_http_port is not set", req.ProxyName)
@@ -285,6 +290,12 @@ func doLogin(req *msg.ControlReq, c *conn.Conn) (ret int64, info string) {
 			s.PoolCount = req.PoolCount
 		}
 
+		if s.Status == consts.Working {
+			info = fmt.Sprintf("ProxyName [%s], already in use", req.ProxyName)
+			log.Warn(info)
+			return
+		}
+
 		// start proxy and listen for user connections, no block
 		err := s.Start(c)
 		if err != nil {

+ 55 - 15
src/frp/models/server/config.go

@@ -30,21 +30,24 @@ import (
 
 // common config
 var (
-	ConfigFile       string = "./frps.ini"
-	BindAddr         string = "0.0.0.0"
-	BindPort         int64  = 7000
-	VhostHttpPort    int64  = 0 // if VhostHttpPort equals 0, don't listen a public port for http protocol
-	VhostHttpsPort   int64  = 0 // if VhostHttpsPort equals 0, don't listen a public port for https protocol
-	DashboardPort    int64  = 0 // if DashboardPort equals 0, dashboard is not available
-	LogFile          string = "console"
-	LogWay           string = "console" // console or file
-	LogLevel         string = "info"
-	LogMaxDays       int64  = 3
-	PrivilegeMode    bool   = false
-	PrivilegeToken   string = ""
-	MaxPoolCount     int64  = 100
-	HeartBeatTimeout int64  = 90
-	UserConnTimeout  int64  = 10
+	ConfigFile     string = "./frps.ini"
+	BindAddr       string = "0.0.0.0"
+	BindPort       int64  = 7000
+	VhostHttpPort  int64  = 0 // if VhostHttpPort equals 0, don't listen a public port for http protocol
+	VhostHttpsPort int64  = 0 // if VhostHttpsPort equals 0, don't listen a public port for https protocol
+	DashboardPort  int64  = 0 // if DashboardPort equals 0, dashboard is not available
+	LogFile        string = "console"
+	LogWay         string = "console" // console or file
+	LogLevel       string = "info"
+	LogMaxDays     int64  = 3
+	PrivilegeMode  bool   = false
+	PrivilegeToken string = ""
+
+	// if PrivilegeAllowPorts is not nil, tcp proxies which remote port exist in this map can be connected
+	PrivilegeAllowPorts map[int64]struct{}
+	MaxPoolCount        int64 = 100
+	HeartBeatTimeout    int64 = 90
+	UserConnTimeout     int64 = 10
 
 	VhostHttpMuxer    *vhost.HttpMuxer
 	VhostHttpsMuxer   *vhost.HttpsMuxer
@@ -155,6 +158,43 @@ func loadCommonConf(confFile string) error {
 		} else {
 			return fmt.Errorf("Parse conf error: privilege_token must be set if privilege_mode is enabled")
 		}
+
+		PrivilegeAllowPorts = make(map[int64]struct{})
+		tmpStr, ok = conf.Get("common", "privilege_allow_ports")
+		if ok {
+			// for example: 1000-2000,2001,2002,3000-4000
+			portRanges := strings.Split(tmpStr, ",")
+			for _, portRangeStr := range portRanges {
+				// 1000-2000 or 2001
+				portArray := strings.Split(portRangeStr, "-")
+				// lenght: only 1 or 2 is correct
+				rangeType := len(portArray)
+				if rangeType == 1 {
+					singlePort, err := strconv.ParseInt(portArray[0], 10, 64)
+					if err != nil {
+						return fmt.Errorf("Parse conf error: privilege_allow_ports is incorrect, %v", err)
+					}
+					PrivilegeAllowPorts[singlePort] = struct{}{}
+				} else if rangeType == 2 {
+					min, err := strconv.ParseInt(portArray[0], 10, 64)
+					if err != nil {
+						return fmt.Errorf("Parse conf error: privilege_allow_ports is incorrect, %v", err)
+					}
+					max, err := strconv.ParseInt(portArray[1], 10, 64)
+					if err != nil {
+						return fmt.Errorf("Parse conf error: privilege_allow_ports is incorrect, %v", err)
+					}
+					if max < min {
+						return fmt.Errorf("Parse conf error: privilege_allow_ports range incorrect")
+					}
+					for i := min; i <= max; i++ {
+						PrivilegeAllowPorts[i] = struct{}{}
+					}
+				} else {
+					return fmt.Errorf("Parse conf error: privilege_allow_ports is incorrect")
+				}
+			}
+		}
 	}
 
 	tmpStr, ok = conf.Get("common", "max_pool_count")