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

This commit is contained in:
fatedier 2016-07-31 02:17:10 +08:00
parent 785dcaad44
commit ecb6ad4885
3 changed files with 73 additions and 21 deletions

View File

@ -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

View File

@ -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 {

View File

@ -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")