mirror of
https://github.com/TeaOSLab/EdgeNode.git
synced 2025-11-12 22:40:25 +08:00
优化Firewalld添加端口方法,自动聚合连续的端口号
This commit is contained in:
@@ -75,6 +75,24 @@ func (this *Firewalld) AllowPort(port int, protocol string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *Firewalld) AllowPortRangesPermanently(portRanges [][2]int, protocol string) error {
|
||||||
|
for _, portRange := range portRanges {
|
||||||
|
var port = this.PortRangeString(portRange, protocol)
|
||||||
|
|
||||||
|
{
|
||||||
|
var cmd = exec.Command(this.exe, "--add-port="+port, "--permanent")
|
||||||
|
this.pushCmd(cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
var cmd = exec.Command(this.exe, "--add-port="+port)
|
||||||
|
this.pushCmd(cmd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (this *Firewalld) RemovePort(port int, protocol string) error {
|
func (this *Firewalld) RemovePort(port int, protocol string) error {
|
||||||
if !this.isReady {
|
if !this.isReady {
|
||||||
return nil
|
return nil
|
||||||
@@ -84,6 +102,30 @@ func (this *Firewalld) RemovePort(port int, protocol string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *Firewalld) RemovePortRangePermanently(portRange [2]int, protocol string) error {
|
||||||
|
var port = this.PortRangeString(portRange, protocol)
|
||||||
|
|
||||||
|
{
|
||||||
|
var cmd = exec.Command(this.exe, "--remove-port="+port, "--permanent")
|
||||||
|
this.pushCmd(cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
var cmd = exec.Command(this.exe, "--remove-port="+port)
|
||||||
|
this.pushCmd(cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Firewalld) PortRangeString(portRange [2]int, protocol string) string {
|
||||||
|
if portRange[0] == portRange[1] {
|
||||||
|
return types.String(portRange[0]) + "/" + protocol
|
||||||
|
} else {
|
||||||
|
return types.String(portRange[0]) + "-" + types.String(portRange[1]) + "/" + protocol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (this *Firewalld) RejectSourceIP(ip string, timeoutSeconds int) error {
|
func (this *Firewalld) RejectSourceIP(ip string, timeoutSeconds int) error {
|
||||||
if !this.isReady {
|
if !this.isReady {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -5,11 +5,14 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
|
"github.com/TeaOSLab/EdgeNode/internal/firewalls"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/goman"
|
"github.com/TeaOSLab/EdgeNode/internal/goman"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
||||||
|
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
||||||
"github.com/iwind/TeaGo/Tea"
|
"github.com/iwind/TeaGo/Tea"
|
||||||
"github.com/iwind/TeaGo/lists"
|
"github.com/iwind/TeaGo/lists"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"regexp"
|
"regexp"
|
||||||
@@ -31,15 +34,19 @@ type ListenerManager struct {
|
|||||||
retryListenerMap map[string]*Listener // 需要重试的监听器 addr => Listener
|
retryListenerMap map[string]*Listener // 需要重试的监听器 addr => Listener
|
||||||
ticker *time.Ticker
|
ticker *time.Ticker
|
||||||
|
|
||||||
lastPortStrings string
|
firewalld *firewalls.Firewalld
|
||||||
|
lastPortStrings string
|
||||||
|
lastTCPPortRanges [][2]int
|
||||||
|
lastUDPPortRanges [][2]int
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewListenerManager 获取新对象
|
// NewListenerManager 获取新对象
|
||||||
func NewListenerManager() *ListenerManager {
|
func NewListenerManager() *ListenerManager {
|
||||||
manager := &ListenerManager{
|
var manager = &ListenerManager{
|
||||||
listenersMap: map[string]*Listener{},
|
listenersMap: map[string]*Listener{},
|
||||||
retryListenerMap: map[string]*Listener{},
|
retryListenerMap: map[string]*Listener{},
|
||||||
ticker: time.NewTicker(1 * time.Minute),
|
ticker: time.NewTicker(1 * time.Minute),
|
||||||
|
firewalld: firewalls.NewFirewalld(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// 提升测试效率
|
// 提升测试效率
|
||||||
@@ -147,7 +154,7 @@ func (this *ListenerManager) Start(node *nodeconfigs.NodeConfig) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 加入到firewalld
|
// 加入到firewalld
|
||||||
this.addToFirewalld(groupAddrs)
|
go this.addToFirewalld(groupAddrs)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -226,8 +233,14 @@ func (this *ListenerManager) addToFirewalld(groupAddrs []string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if this.firewalld == nil || !this.firewalld.IsReady() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 组合端口号
|
// 组合端口号
|
||||||
var ports = []string{}
|
var portStrings = []string{}
|
||||||
|
var udpPorts = []int{}
|
||||||
|
var tcpPorts = []int{}
|
||||||
for _, addr := range groupAddrs {
|
for _, addr := range groupAddrs {
|
||||||
var protocol = "tcp"
|
var protocol = "tcp"
|
||||||
if strings.HasPrefix(addr, "udp") {
|
if strings.HasPrefix(addr, "udp") {
|
||||||
@@ -237,52 +250,72 @@ func (this *ListenerManager) addToFirewalld(groupAddrs []string) {
|
|||||||
var lastIndex = strings.LastIndex(addr, ":")
|
var lastIndex = strings.LastIndex(addr, ":")
|
||||||
if lastIndex > 0 {
|
if lastIndex > 0 {
|
||||||
var portString = addr[lastIndex+1:]
|
var portString = addr[lastIndex+1:]
|
||||||
ports = append(ports, portString+"/"+protocol)
|
portStrings = append(portStrings, portString+"/"+protocol)
|
||||||
|
|
||||||
|
switch protocol {
|
||||||
|
case "tcp":
|
||||||
|
tcpPorts = append(tcpPorts, types.Int(portString))
|
||||||
|
case "udp":
|
||||||
|
udpPorts = append(udpPorts, types.Int(portString))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(ports) == 0 {
|
if len(portStrings) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查是否有变化
|
// 检查是否有变化
|
||||||
sort.Strings(ports)
|
sort.Strings(portStrings)
|
||||||
var newPortStrings = strings.Join(ports, ",")
|
var newPortStrings = strings.Join(portStrings, ",")
|
||||||
if newPortStrings == this.lastPortStrings {
|
if newPortStrings == this.lastPortStrings {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.lastPortStrings = newPortStrings
|
this.lastPortStrings = newPortStrings
|
||||||
|
|
||||||
firewallCmd, err := exec.LookPath("firewall-cmd")
|
remotelogs.Println("FIREWALLD", "opening ports automatically ...")
|
||||||
if err != nil || len(firewallCmd) == 0 {
|
defer func() {
|
||||||
return
|
remotelogs.Println("FIREWALLD", "open ports successfully")
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 合并端口
|
||||||
|
var tcpPortRanges = utils.MergePorts(tcpPorts)
|
||||||
|
var udpPortRanges = utils.MergePorts(udpPorts)
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
this.lastTCPPortRanges = tcpPortRanges
|
||||||
|
this.lastUDPPortRanges = udpPortRanges
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 删除老的不存在的端口
|
||||||
|
var tcpPortRangesMap = map[string]bool{}
|
||||||
|
var udpPortRangesMap = map[string]bool{}
|
||||||
|
for _, portRange := range tcpPortRanges {
|
||||||
|
tcpPortRangesMap[this.firewalld.PortRangeString(portRange, "tcp")] = true
|
||||||
|
}
|
||||||
|
for _, portRange := range udpPortRanges {
|
||||||
|
udpPortRangesMap[this.firewalld.PortRangeString(portRange, "udp")] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查状态
|
for _, portRange := range this.lastTCPPortRanges {
|
||||||
err = exec.Command(firewallCmd, "--state").Run()
|
var s = this.firewalld.PortRangeString(portRange, "tcp")
|
||||||
if err != nil {
|
_, ok := tcpPortRangesMap[s]
|
||||||
return
|
if ok {
|
||||||
}
|
continue
|
||||||
|
|
||||||
remotelogs.Println("FIREWALLD", "open ports automatically")
|
|
||||||
for _, port := range ports {
|
|
||||||
{
|
|
||||||
// TODO 需要支持sudo
|
|
||||||
var cmd = exec.Command(firewallCmd, "--add-port="+port, "--permanent")
|
|
||||||
err = cmd.Run()
|
|
||||||
if err != nil {
|
|
||||||
remotelogs.Warn("FIREWALLD", "'"+cmd.String()+"': "+err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// TODO 需要支持sudo
|
|
||||||
var cmd = exec.Command(firewallCmd, "--add-port="+port)
|
|
||||||
err = cmd.Run()
|
|
||||||
if err != nil {
|
|
||||||
remotelogs.Warn("FIREWALLD", "'"+cmd.String()+"': "+err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
remotelogs.Println("FIREWALLD", "remove port '"+s+"'")
|
||||||
|
_ = this.firewalld.RemovePortRangePermanently(portRange, "tcp")
|
||||||
}
|
}
|
||||||
|
for _, portRange := range this.lastUDPPortRanges {
|
||||||
|
var s = this.firewalld.PortRangeString(portRange, "udp")
|
||||||
|
_, ok := udpPortRangesMap[s]
|
||||||
|
if ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
remotelogs.Println("FIREWALLD", "remove port '"+s+"'")
|
||||||
|
_ = this.firewalld.RemovePortRangePermanently(portRange, "udp")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加新的
|
||||||
|
_ = this.firewalld.AllowPortRangesPermanently(tcpPortRanges, "tcp")
|
||||||
|
_ = this.firewalld.AllowPortRangesPermanently(udpPortRanges, "udp")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"github.com/iwind/TeaGo/logs"
|
"github.com/iwind/TeaGo/logs"
|
||||||
"net"
|
"net"
|
||||||
|
"sort"
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -38,3 +39,34 @@ func ParseAddrHost(addr string) string {
|
|||||||
}
|
}
|
||||||
return host
|
return host
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MergePorts 聚合端口
|
||||||
|
// 返回 [ [fromPort, toPort], ... ]
|
||||||
|
func MergePorts(ports []int) [][2]int {
|
||||||
|
if len(ports) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Ints(ports)
|
||||||
|
|
||||||
|
var result = [][2]int{}
|
||||||
|
var lastRange = [2]int{0, 0}
|
||||||
|
var lastPort = -1
|
||||||
|
for _, port := range ports {
|
||||||
|
if port <= 0 /** 只处理有效的端口 **/ || port == lastPort /** 去重 **/ {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if lastPort < 0 || port != lastPort+1 {
|
||||||
|
lastRange = [2]int{port, port}
|
||||||
|
result = append(result, lastRange)
|
||||||
|
} else { // 如果是连续的
|
||||||
|
lastRange[1] = port
|
||||||
|
result[len(result)-1] = lastRange
|
||||||
|
}
|
||||||
|
|
||||||
|
lastPort = port
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,3 +12,15 @@ func TestParseAddrHost(t *testing.T) {
|
|||||||
t.Log(addr + " => " + utils.ParseAddrHost(addr))
|
t.Log(addr + " => " + utils.ParseAddrHost(addr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMergePorts(t *testing.T) {
|
||||||
|
for _, ports := range [][]int{
|
||||||
|
{},
|
||||||
|
{80},
|
||||||
|
{80, 83, 85},
|
||||||
|
{80, 81, 83, 85, 86, 87, 88, 90},
|
||||||
|
{0, 0, 1, 1, 2, 2, 2, 3, 3, 3},
|
||||||
|
} {
|
||||||
|
t.Log(ports, "=>", utils.MergePorts(ports))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user