mirror of
https://gitee.com/IrisVega/frp.git
synced 2024-11-01 22:31:29 +08:00
new feature: range section for mapping range ports
This commit is contained in:
parent
eede31c064
commit
ce8fde793c
@ -22,6 +22,7 @@ import (
|
|||||||
|
|
||||||
"github.com/fatedier/frp/models/consts"
|
"github.com/fatedier/frp/models/consts"
|
||||||
"github.com/fatedier/frp/models/msg"
|
"github.com/fatedier/frp/models/msg"
|
||||||
|
"github.com/fatedier/frp/utils/util"
|
||||||
|
|
||||||
ini "github.com/vaughan0/go-ini"
|
ini "github.com/vaughan0/go-ini"
|
||||||
)
|
)
|
||||||
@ -770,6 +771,38 @@ func (cfg *XtcpProxyConf) Check() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ParseRangeSection(name string, section ini.Section) (sections map[string]ini.Section, err error) {
|
||||||
|
localPorts, errRet := util.ParseRangeNumbers(section["local_port"])
|
||||||
|
if errRet != nil {
|
||||||
|
err = fmt.Errorf("Parse conf error: range section [%s] local_port invalid, %v", name, errRet)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
remotePorts, errRet := util.ParseRangeNumbers(section["remote_port"])
|
||||||
|
if errRet != nil {
|
||||||
|
err = fmt.Errorf("Parse conf error: range section [%s] remote_port invalid, %v", name, errRet)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(localPorts) != len(remotePorts) {
|
||||||
|
err = fmt.Errorf("Parse conf error: range section [%s] local ports number should be same with remote ports number", name)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(localPorts) == 0 {
|
||||||
|
err = fmt.Errorf("Parse conf error: range section [%s] local_port and remote_port is necessary")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sections = make(map[string]ini.Section)
|
||||||
|
for i, port := range localPorts {
|
||||||
|
subName := fmt.Sprintf("%s_%d", name, i)
|
||||||
|
subSection := copySection(section)
|
||||||
|
subSection["local_port"] = fmt.Sprintf("%d", port)
|
||||||
|
subSection["remote_port"] = fmt.Sprintf("%d", remotePorts[i])
|
||||||
|
sections[subName] = subSection
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// if len(startProxy) is 0, start all
|
// if len(startProxy) is 0, start all
|
||||||
// otherwise just start proxies in startProxy map
|
// otherwise just start proxies in startProxy map
|
||||||
func LoadProxyConfFromFile(prefix string, conf ini.File, startProxy map[string]struct{}) (
|
func LoadProxyConfFromFile(prefix string, conf ini.File, startProxy map[string]struct{}) (
|
||||||
@ -786,22 +819,51 @@ func LoadProxyConfFromFile(prefix string, conf ini.File, startProxy map[string]s
|
|||||||
proxyConfs = make(map[string]ProxyConf)
|
proxyConfs = make(map[string]ProxyConf)
|
||||||
visitorConfs = make(map[string]ProxyConf)
|
visitorConfs = make(map[string]ProxyConf)
|
||||||
for name, section := range conf {
|
for name, section := range conf {
|
||||||
|
if name == "common" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
_, shouldStart := startProxy[name]
|
_, shouldStart := startProxy[name]
|
||||||
if name != "common" && (startAll || shouldStart) {
|
if !startAll && !shouldStart {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
subSections := make(map[string]ini.Section)
|
||||||
|
|
||||||
|
if strings.HasPrefix(name, "range:") {
|
||||||
|
// range section
|
||||||
|
rangePrefix := strings.TrimSpace(strings.TrimPrefix(name, "range:"))
|
||||||
|
subSections, err = ParseRangeSection(rangePrefix, section)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
subSections[name] = section
|
||||||
|
}
|
||||||
|
|
||||||
|
for subName, subSection := range subSections {
|
||||||
// some proxy or visotr configure may be used this prefix
|
// some proxy or visotr configure may be used this prefix
|
||||||
section["prefix"] = prefix
|
subSection["prefix"] = prefix
|
||||||
cfg, err := NewProxyConfFromFile(name, section)
|
cfg, err := NewProxyConfFromFile(subName, subSection)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return proxyConfs, visitorConfs, err
|
return proxyConfs, visitorConfs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
role := section["role"]
|
role := subSection["role"]
|
||||||
if role == "visitor" {
|
if role == "visitor" {
|
||||||
visitorConfs[prefix+name] = cfg
|
visitorConfs[prefix+subName] = cfg
|
||||||
} else {
|
} else {
|
||||||
proxyConfs[prefix+name] = cfg
|
proxyConfs[prefix+subName] = cfg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func copySection(section ini.Section) (out ini.Section) {
|
||||||
|
out = make(ini.Section)
|
||||||
|
for k, v := range section {
|
||||||
|
out[k] = v
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
@ -20,6 +20,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
ini "github.com/vaughan0/go-ini"
|
ini "github.com/vaughan0/go-ini"
|
||||||
|
|
||||||
|
"github.com/fatedier/frp/utils/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ServerCommonCfg *ServerCommonConf
|
var ServerCommonCfg *ServerCommonConf
|
||||||
@ -238,43 +240,14 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) {
|
|||||||
allowPortsStr, ok := conf.Get("common", "privilege_allow_ports")
|
allowPortsStr, ok := conf.Get("common", "privilege_allow_ports")
|
||||||
if ok {
|
if ok {
|
||||||
// e.g. 1000-2000,2001,2002,3000-4000
|
// e.g. 1000-2000,2001,2002,3000-4000
|
||||||
portRanges := strings.Split(allowPortsStr, ",")
|
ports, errRet := util.ParseRangeNumbers(allowPortsStr)
|
||||||
for _, portRangeStr := range portRanges {
|
|
||||||
// 1000-2000 or 2001
|
|
||||||
portArray := strings.Split(portRangeStr, "-")
|
|
||||||
// length: only 1 or 2 is correct
|
|
||||||
rangeType := len(portArray)
|
|
||||||
if rangeType == 1 {
|
|
||||||
// single port
|
|
||||||
singlePort, errRet := strconv.ParseInt(portArray[0], 10, 64)
|
|
||||||
if errRet != nil {
|
if errRet != nil {
|
||||||
err = fmt.Errorf("Parse conf error: privilege_allow_ports is incorrect, %v", errRet)
|
err = fmt.Errorf("Parse conf error: privilege_allow_ports: %v", errRet)
|
||||||
return
|
|
||||||
}
|
|
||||||
cfg.PrivilegeAllowPorts[int(singlePort)] = struct{}{}
|
|
||||||
} else if rangeType == 2 {
|
|
||||||
// range ports
|
|
||||||
min, errRet := strconv.ParseInt(portArray[0], 10, 64)
|
|
||||||
if errRet != nil {
|
|
||||||
err = fmt.Errorf("Parse conf error: privilege_allow_ports is incorrect, %v", errRet)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
max, errRet := strconv.ParseInt(portArray[1], 10, 64)
|
|
||||||
if errRet != nil {
|
|
||||||
err = fmt.Errorf("Parse conf error: privilege_allow_ports is incorrect, %v", errRet)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if max < min {
|
|
||||||
err = fmt.Errorf("Parse conf error: privilege_allow_ports range incorrect")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for i := min; i <= max; i++ {
|
|
||||||
cfg.PrivilegeAllowPorts[int(i)] = struct{}{}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err = fmt.Errorf("Parse conf error: privilege_allow_ports is incorrect")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, port := range ports {
|
||||||
|
cfg.PrivilegeAllowPorts[int(port)] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ import (
|
|||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RandId return a rand string used in frp.
|
// RandId return a rand string used in frp.
|
||||||
@ -54,3 +56,48 @@ func CanonicalAddr(host string, port int) (addr string) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ParseRangeNumbers(rangeStr string) (numbers []int64, err error) {
|
||||||
|
rangeStr = strings.TrimSpace(rangeStr)
|
||||||
|
numbers = make([]int64, 0)
|
||||||
|
// e.g. 1000-2000,2001,2002,3000-4000
|
||||||
|
numRanges := strings.Split(rangeStr, ",")
|
||||||
|
for _, numRangeStr := range numRanges {
|
||||||
|
// 1000-2000 or 2001
|
||||||
|
numArray := strings.Split(numRangeStr, "-")
|
||||||
|
// length: only 1 or 2 is correct
|
||||||
|
rangeType := len(numArray)
|
||||||
|
if rangeType == 1 {
|
||||||
|
// single number
|
||||||
|
singleNum, errRet := strconv.ParseInt(strings.TrimSpace(numArray[0]), 10, 64)
|
||||||
|
if errRet != nil {
|
||||||
|
err = fmt.Errorf("range number is invalid, %v", errRet)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
numbers = append(numbers, singleNum)
|
||||||
|
} else if rangeType == 2 {
|
||||||
|
// range numbers
|
||||||
|
min, errRet := strconv.ParseInt(strings.TrimSpace(numArray[0]), 10, 64)
|
||||||
|
if errRet != nil {
|
||||||
|
err = fmt.Errorf("range number is invalid, %v", errRet)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
max, errRet := strconv.ParseInt(strings.TrimSpace(numArray[1]), 10, 64)
|
||||||
|
if errRet != nil {
|
||||||
|
err = fmt.Errorf("range number is invalid, %v", errRet)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if max < min {
|
||||||
|
err = fmt.Errorf("range number is invalid")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for i := min; i <= max; i++ {
|
||||||
|
numbers = append(numbers, i)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = fmt.Errorf("range number is invalid")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
@ -20,3 +20,29 @@ func TestGetAuthKey(t *testing.T) {
|
|||||||
t.Log(key)
|
t.Log(key)
|
||||||
assert.Equal("6df41a43725f0c770fd56379e12acf8c", key)
|
assert.Equal("6df41a43725f0c770fd56379e12acf8c", key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseRangeNumbers(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
numbers, err := ParseRangeNumbers("2-5")
|
||||||
|
if assert.NoError(err) {
|
||||||
|
assert.Equal([]int64{2, 3, 4, 5}, numbers)
|
||||||
|
}
|
||||||
|
|
||||||
|
numbers, err = ParseRangeNumbers("1")
|
||||||
|
if assert.NoError(err) {
|
||||||
|
assert.Equal([]int64{1}, numbers)
|
||||||
|
}
|
||||||
|
|
||||||
|
numbers, err = ParseRangeNumbers("3-5,8")
|
||||||
|
if assert.NoError(err) {
|
||||||
|
assert.Equal([]int64{3, 4, 5, 8}, numbers)
|
||||||
|
}
|
||||||
|
|
||||||
|
numbers, err = ParseRangeNumbers(" 3-5,8, 10-12 ")
|
||||||
|
if assert.NoError(err) {
|
||||||
|
assert.Equal([]int64{3, 4, 5, 8, 10, 11, 12}, numbers)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = ParseRangeNumbers("3-a")
|
||||||
|
assert.Error(err)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user