改了什么: - cmd/node/config.go: 零依赖 ini 配置加载([server] Addr/TunnelBind/JwtSecret/SweepSeconds + [tunnel] PortRange); -config node.ini 启用 - main.go: -config 与 -port-range flag; 配置来源优先级 显式 flag > 配置文件(非零项) > 内置默认(flag.Visit 判显式) - internal/node/portrange.go: PortRange 解析(20000-21000/单端口/容错) + listen(随机起点顺延探测, 占用即生效避免 TOCTOU) - node.go: TunnelPortRange 字段; listenTunnel 统一隧道建听——端口 0 且配置范围时范围内取空闲端口, 否则原路径(指定端口直监听/系统随机) - Start 日志打出端口范围; portrange_test.go 覆盖解析与占满/释放取端口 为什么: agent 注册隧道从不指定端口(ListenPort=0), 节点 net.Listen 落系统随机高位段, 云主机防火墙无法预开; 配置范围后临时/永久隧道都落在固定段内, 防火墙放行 5212+范围即可
76 lines
1.7 KiB
Go
76 lines
1.7 KiB
Go
package node
|
|
|
|
import (
|
|
"net"
|
|
"testing"
|
|
)
|
|
|
|
func TestParsePortRange(t *testing.T) {
|
|
cases := []struct {
|
|
in string
|
|
wantMin int
|
|
wantMax int
|
|
wantErr bool
|
|
}{
|
|
{"", 0, 0, false}, // 空 = 未配置
|
|
{"20000-21000", 20000, 21000, false},
|
|
{"20000 - 21000", 20000, 21000, false}, // 两侧空白
|
|
{"5900", 5900, 5900, false}, // 单端口
|
|
{"abc", 0, 0, true},
|
|
{"21000-20000", 0, 0, true}, // 逆序
|
|
{"0-100", 0, 0, true}, // 零起点无效
|
|
{"65536", 0, 0, true}, // 越界
|
|
}
|
|
for _, c := range cases {
|
|
r, err := ParsePortRange(c.in)
|
|
if c.wantErr {
|
|
if err == nil {
|
|
t.Errorf("ParsePortRange(%q) 期望报错, 得到 %v", c.in, r)
|
|
}
|
|
continue
|
|
}
|
|
if err != nil {
|
|
t.Errorf("ParsePortRange(%q) 意外报错: %v", c.in, err)
|
|
continue
|
|
}
|
|
if r.Min != c.wantMin || r.Max != c.wantMax {
|
|
t.Errorf("ParsePortRange(%q) = %v, 期望 %d-%d", c.in, r, c.wantMin, c.wantMax)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestPortRangeListen(t *testing.T) {
|
|
r, err := ParsePortRange("20000-20002")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// 占满 3 个端口后第 4 次应失败
|
|
var ls []net.Listener
|
|
defer func() {
|
|
for _, l := range ls {
|
|
l.Close()
|
|
}
|
|
}()
|
|
for i := 0; i < 3; i++ {
|
|
l, err := r.listen("127.0.0.1")
|
|
if err != nil {
|
|
t.Fatalf("第 %d 次取端口失败: %v", i+1, err)
|
|
}
|
|
ls = append(ls, l)
|
|
port := l.Addr().(*net.TCPAddr).Port
|
|
if port < 20000 || port > 20002 {
|
|
t.Fatalf("取得端口 %d 超出范围", port)
|
|
}
|
|
}
|
|
if _, err := r.listen("127.0.0.1"); err == nil {
|
|
t.Fatal("范围占满后应返回错误")
|
|
}
|
|
// 释放后应可再取
|
|
ls[0].Close()
|
|
l, err := r.listen("127.0.0.1")
|
|
if err != nil {
|
|
t.Fatalf("释放后再取失败: %v", err)
|
|
}
|
|
l.Close()
|
|
}
|