Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tunnelAllowedPort add port segments syntax. #409

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 53 additions & 5 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,19 @@ var defaultTunnelAllowedPort = []string{
"2401", "3690", "9418", // cvspserver, svn, git
}

type portSegment struct {
minPort int
maxPort int
}

type Config struct {
RcFile string // config file
LogFile string // path for log file
AlwaysProxy bool // whether we should alwyas use parent proxy
LoadBalance LoadBalanceMode // select load balance mode

TunnelAllowedPort map[string]bool // allowed ports to create tunnel
TunnelAllowedPortSegment []*portSegment // allowed port segments to create tunnel
TunnelAllowedPort map[string]bool // allowed ports to create tunnel

SshServer []string

Expand Down Expand Up @@ -98,6 +104,7 @@ func initConfig(rcFile string) {
config.DialTimeout = defaultDialTimeout
config.ReadTimeout = defaultReadTimeout

config.TunnelAllowedPortSegment = []*portSegment{}
config.TunnelAllowedPort = make(map[string]bool)
for _, port := range defaultTunnelAllowedPort {
config.TunnelAllowedPort[port] = true
Expand Down Expand Up @@ -379,14 +386,55 @@ func (p configParser) ParseAddrInPAC(val string) {
}
}

func (c Config) IsTunnelAllowedPort(s string) bool {
if config.TunnelAllowedPort[s] {
return true
}
if port, err := strconv.Atoi(s); err == nil {
for _, pSeg := range config.TunnelAllowedPortSegment {
if port >= pSeg.minPort && port <= pSeg.maxPort {
return true
}
}
}
return false
}

func (p configParser) ParseTunnelAllowedPort(val string) {
arr := strings.Split(val, ",")
for i, s := range arr {
arr[i] = strings.TrimSpace(s)
}
for i, s := range arr {
var min, max int
if strings.Contains(s, "-") {
if _, err := fmt.Sscanf(s, "%d-%d", &min, &max); err != nil || min > max {
Fatal("tunnel allowed port segments", err)
}
if min == max {
arr[i] = strconv.Itoa(min)
} else {
config.TunnelAllowedPortSegment = append(config.TunnelAllowedPortSegment, &portSegment{min, max})
arr[i] = ""
}
}
}
for _, s := range arr {
s = strings.TrimSpace(s)
if _, err := strconv.Atoi(s); err != nil {
Fatal("tunnel allowed ports", err)
if s != "" {
if _, err := strconv.Atoi(s); err != nil {
Fatal("tunnel allowed ports", err)
}
config.TunnelAllowedPort[s] = true
}
}
for s := range config.TunnelAllowedPort {
if p1, err := strconv.Atoi(s); err == nil {
for _, p2 := range config.TunnelAllowedPortSegment {
if p1 >= p2.minPort && p1 <= p2.maxPort {
delete(config.TunnelAllowedPort, s)
}
}
}
config.TunnelAllowedPort[s] = true
}
}

Expand Down
10 changes: 8 additions & 2 deletions config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ func TestParseListen(t *testing.T) {
func TestTunnelAllowedPort(t *testing.T) {
initConfig("")
parser := configParser{}
parser.ParseTunnelAllowedPort("1, 2, 3, 4, 5")
parser.ParseTunnelAllowedPort("1, 2, 3, 4, 5, 100-500, 600-888")
parser.ParseTunnelAllowedPort("6")
parser.ParseTunnelAllowedPort("7")
parser.ParseTunnelAllowedPort("8")
parser.ParseTunnelAllowedPort("1000-3333")

testData := []struct {
port string
Expand All @@ -41,12 +42,17 @@ func TestTunnelAllowedPort(t *testing.T) {
{"3", true},
{"5", true},
{"7", true},
{"342", true},
{"777", true},
{"2332", true},

{"523", false},
{"8080", false},
{"8388", false},
}

for _, td := range testData {
allowed := config.TunnelAllowedPort[td.port]
allowed := config.IsTunnelAllowedPort(td.port)
if allowed != td.allowed {
t.Errorf("port %s allowed %v, got %v\n", td.port, td.allowed, allowed)
}
Expand Down
4 changes: 2 additions & 2 deletions doc/sample-config/rc
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,11 @@ listen = http://127.0.0.1:7777
# 检测超时时间使用的网站,最好使用能快速访问的站点
#estimateTarget = example.com

# 允许建立隧道连接的端口,多个端口用逗号分隔,可重复多次
# 允许建立隧道连接的端口,多个端口用逗号分隔,可重复多次,支持端口段
# 默认总是允许下列服务的端口: ssh, http, https, rsync, imap, pop, jabber, cvs, git, svn
# 如需允许其他端口,请用该选项添加
# 限制隧道连接的端口可以防止将运行 COW 的服务器上只监听本机 ip 的服务暴露给外部
#tunnelAllowedPort = 80, 443
#tunnelAllowedPort = 80, 443, 100-500, 2333-6666

# GFW 会使 DNS 解析超时,也可能返回错误的地址,能连接但是读不到任何内容
# 下面两个值改小一点可以加速检测网站是否被墙,但网络情况差时可能误判
Expand Down
2 changes: 1 addition & 1 deletion doc/sample-config/rc-en
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ listen = http://127.0.0.1:7777
# ssh, http, https, rsync, imap, pop, jabber, cvs, git, svn
#
# Limiting ports for tunneling prevents exposing internal services to outside.
#tunnelAllowedPort = 80, 443
#tunnelAllowedPort = 80, 443, 100-500, 2333-6666

# GFW may timeout DNS query, or return wrong server address which can connect
# but blocks on read forever.
Expand Down
2 changes: 1 addition & 1 deletion proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ func (c *clientConn) serve() {
authed = true
}

if r.isConnect && !config.TunnelAllowedPort[r.URL.Port] {
if r.isConnect && !config.IsTunnelAllowedPort(r.URL.Port) {
sendErrorPage(c, statusForbidden, "Forbidden tunnel port",
genErrMsg(&r, nil, "Please contact proxy admin."))
return
Expand Down