mirror of
				https://github.com/TeaOSLab/EdgeAPI.git
				synced 2025-11-04 07:50:25 +08:00 
			
		
		
		
	实现基础的DDoS防护
This commit is contained in:
		
							
								
								
									
										2
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
									
									
									
									
								
							@@ -242,6 +242,8 @@ github.com/iwind/TeaGo v0.0.0-20220322141208-22f88d04004d h1:e8fkTKras/RXQWECApM
 | 
			
		||||
github.com/iwind/TeaGo v0.0.0-20220322141208-22f88d04004d/go.mod h1:HRHK0zoC/og3c9/hKosD9yYVMTnnzm3PgXUdhRYHaLc=
 | 
			
		||||
github.com/iwind/TeaGo v0.0.0-20220408064305-92be81dc2f7c h1:ugjYZ74FJGWlfDKKraNgMyDTeS4vbXHe89JGUVQIJMo=
 | 
			
		||||
github.com/iwind/TeaGo v0.0.0-20220408064305-92be81dc2f7c/go.mod h1:HRHK0zoC/og3c9/hKosD9yYVMTnnzm3PgXUdhRYHaLc=
 | 
			
		||||
github.com/iwind/TeaGo v0.0.0-20220408111647-f36b9bba3570 h1:zqz2FiMMkSHXWO1EsTRJDPTwX9xQ4uuyD5GAE4JGlhM=
 | 
			
		||||
github.com/iwind/TeaGo v0.0.0-20220408111647-f36b9bba3570/go.mod h1:HRHK0zoC/og3c9/hKosD9yYVMTnnzm3PgXUdhRYHaLc=
 | 
			
		||||
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3 h1:aBSonas7vFcgTj9u96/bWGILGv1ZbUSTLiOzcI1ZT6c=
 | 
			
		||||
github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3/go.mod h1:H5Q7SXwbx3a97ecJkaS2sD77gspzE7HFUafBO0peEyA=
 | 
			
		||||
github.com/jarcoal/httpmock v1.0.5/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,7 @@ import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
 | 
			
		||||
	_ "github.com/go-sql-driver/mysql"
 | 
			
		||||
	"github.com/iwind/TeaGo/Tea"
 | 
			
		||||
	"github.com/iwind/TeaGo/dbs"
 | 
			
		||||
@@ -180,7 +181,7 @@ func (this *NodeClusterDAO) CreateCluster(tx *dbs.Tx, adminId int64, name string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateCluster 修改集群
 | 
			
		||||
func (this *NodeClusterDAO) UpdateCluster(tx *dbs.Tx, clusterId int64, name string, grantId int64, installDir string, timezone string, nodeMaxThreads int32, nodeTCPMaxConnections int32, autoOpenPorts bool) error {
 | 
			
		||||
func (this *NodeClusterDAO) UpdateCluster(tx *dbs.Tx, clusterId int64, name string, grantId int64, installDir string, timezone string, nodeMaxThreads int32, autoOpenPorts bool) error {
 | 
			
		||||
	if clusterId <= 0 {
 | 
			
		||||
		return errors.New("invalid clusterId")
 | 
			
		||||
	}
 | 
			
		||||
@@ -195,11 +196,6 @@ func (this *NodeClusterDAO) UpdateCluster(tx *dbs.Tx, clusterId int64, name stri
 | 
			
		||||
		nodeMaxThreads = 0
 | 
			
		||||
	}
 | 
			
		||||
	op.NodeMaxThreads = nodeMaxThreads
 | 
			
		||||
 | 
			
		||||
	if nodeTCPMaxConnections < 0 {
 | 
			
		||||
		nodeTCPMaxConnections = 0
 | 
			
		||||
	}
 | 
			
		||||
	op.NodeTCPMaxConnections = nodeTCPMaxConnections
 | 
			
		||||
	op.AutoOpenPorts = autoOpenPorts
 | 
			
		||||
 | 
			
		||||
	err := this.Save(tx, op)
 | 
			
		||||
@@ -922,7 +918,7 @@ func (this *NodeClusterDAO) FindClusterBasicInfo(tx *dbs.Tx, clusterId int64, ca
 | 
			
		||||
	cluster, err := this.Query(tx).
 | 
			
		||||
		Pk(clusterId).
 | 
			
		||||
		State(NodeClusterStateEnabled).
 | 
			
		||||
		Result("timeZone", "nodeMaxThreads", "nodeTCPMaxConnections", "cachePolicyId", "httpFirewallPolicyId", "autoOpenPorts", "webp", "isOn").
 | 
			
		||||
		Result("id", "timeZone", "nodeMaxThreads", "cachePolicyId", "httpFirewallPolicyId", "autoOpenPorts", "webp", "isOn", "ddosProtection").
 | 
			
		||||
		Find()
 | 
			
		||||
	if err != nil || cluster == nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
@@ -992,6 +988,45 @@ func (this *NodeClusterDAO) FindClusterWebPPolicy(tx *dbs.Tx, clusterId int64, c
 | 
			
		||||
	return policy, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FindClusterDDoSProtection 获取集群的DDoS设置
 | 
			
		||||
func (this *NodeClusterDAO) FindClusterDDoSProtection(tx *dbs.Tx, clusterId int64) (*ddosconfigs.ProtectionConfig, error) {
 | 
			
		||||
	one, err := this.Query(tx).
 | 
			
		||||
		Result("ddosProtection").
 | 
			
		||||
		Pk(clusterId).
 | 
			
		||||
		Find()
 | 
			
		||||
	if one == nil || err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return one.(*NodeCluster).DecodeDDoSProtection(), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateClusterDDoSProtection 设置集群的DDOS设置
 | 
			
		||||
func (this *NodeClusterDAO) UpdateClusterDDoSProtection(tx *dbs.Tx, clusterId int64, ddosProtection *ddosconfigs.ProtectionConfig) error {
 | 
			
		||||
	if clusterId <= 0 {
 | 
			
		||||
		return ErrNotFound
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var op = NewNodeClusterOperator()
 | 
			
		||||
	op.Id = clusterId
 | 
			
		||||
 | 
			
		||||
	if ddosProtection == nil {
 | 
			
		||||
		op.DdosProtection = "{}"
 | 
			
		||||
	} else {
 | 
			
		||||
		ddosProtectionJSON, err := json.Marshal(ddosProtection)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		op.DdosProtection = ddosProtectionJSON
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := this.Save(tx, op)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeDDosProtectionChanged)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NotifyUpdate 通知更新
 | 
			
		||||
func (this *NodeClusterDAO) NotifyUpdate(tx *dbs.Tx, clusterId int64) error {
 | 
			
		||||
	return SharedNodeTaskDAO.CreateClusterTask(tx, nodeconfigs.NodeRoleNode, clusterId, 0, NodeTaskTypeConfigChanged)
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@ type NodeCluster struct {
 | 
			
		||||
	SystemServices       dbs.JSON `field:"systemServices"`       // 系统服务设置
 | 
			
		||||
	TimeZone             string   `field:"timeZone"`             // 时区
 | 
			
		||||
	NodeMaxThreads       uint32   `field:"nodeMaxThreads"`       // 节点最大线程数
 | 
			
		||||
	NodeTCPMaxConnections uint32   `field:"nodeTCPMaxConnections"` // TCP最大连接数
 | 
			
		||||
	DdosProtection       dbs.JSON `field:"ddosProtection"`       // DDOS端口
 | 
			
		||||
	AutoOpenPorts        uint8    `field:"autoOpenPorts"`        // 是否自动尝试开放端口
 | 
			
		||||
	IsPinned             bool     `field:"isPinned"`             // 是否置顶
 | 
			
		||||
	Webp                 dbs.JSON `field:"webp"`                 // WebP设置
 | 
			
		||||
@@ -63,7 +63,7 @@ type NodeClusterOperator struct {
 | 
			
		||||
	SystemServices       interface{} // 系统服务设置
 | 
			
		||||
	TimeZone             interface{} // 时区
 | 
			
		||||
	NodeMaxThreads       interface{} // 节点最大线程数
 | 
			
		||||
	NodeTCPMaxConnections interface{} // TCP最大连接数
 | 
			
		||||
	DdosProtection       interface{} // DDOS端口
 | 
			
		||||
	AutoOpenPorts        interface{} // 是否自动尝试开放端口
 | 
			
		||||
	IsPinned             interface{} // 是否置顶
 | 
			
		||||
	Webp                 interface{} // WebP设置
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@ package models
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DecodeDNSConfig 解析DNS配置
 | 
			
		||||
@@ -21,3 +22,26 @@ func (this *NodeCluster) DecodeDNSConfig() (*dnsconfigs.ClusterDNSConfig, error)
 | 
			
		||||
	}
 | 
			
		||||
	return dnsConfig, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DecodeDDoSProtection 解析DDOS Protection设置
 | 
			
		||||
func (this *NodeCluster) DecodeDDoSProtection() *ddosconfigs.ProtectionConfig {
 | 
			
		||||
	if IsNull(this.DdosProtection) {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var result = &ddosconfigs.ProtectionConfig{}
 | 
			
		||||
	err := json.Unmarshal(this.DdosProtection, &result)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		// ignore err
 | 
			
		||||
	}
 | 
			
		||||
	return result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HasDDoSProtection 检查是否有DDOS设置
 | 
			
		||||
func (this *NodeCluster) HasDDoSProtection() bool {
 | 
			
		||||
	var config = this.DecodeDDoSProtection()
 | 
			
		||||
	if config != nil {
 | 
			
		||||
		return config.IsOn()
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@ import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
 | 
			
		||||
	_ "github.com/go-sql-driver/mysql"
 | 
			
		||||
@@ -973,6 +974,7 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap *utils
 | 
			
		||||
	clusterIds = append(clusterIds, node.DecodeSecondaryClusterIds()...)
 | 
			
		||||
	var clusterIndex = 0
 | 
			
		||||
	config.WebPImagePolicies = map[int64]*nodeconfigs.WebPImagePolicy{}
 | 
			
		||||
	var allowIPMaps = map[string]bool{}
 | 
			
		||||
	for _, clusterId := range clusterIds {
 | 
			
		||||
		nodeCluster, err := SharedNodeClusterDAO.FindClusterBasicInfo(tx, clusterId, cacheMap)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
@@ -982,6 +984,21 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap *utils
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// 节点IP地址
 | 
			
		||||
		nodeIPAddresses, err := SharedNodeIPAddressDAO.FindAllAccessibleIPAddressesWithClusterId(tx, nodeconfigs.NodeRoleNode, clusterId, cacheMap)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		for _, address := range nodeIPAddresses {
 | 
			
		||||
			var ip = address.Ip
 | 
			
		||||
			_, ok := allowIPMaps[ip]
 | 
			
		||||
			if !ok {
 | 
			
		||||
				allowIPMaps[ip] = true
 | 
			
		||||
				config.AllowedIPs = append(config.AllowedIPs, ip)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// 防火墙
 | 
			
		||||
		var httpFirewallPolicyId = int64(nodeCluster.HttpFirewallPolicyId)
 | 
			
		||||
		if httpFirewallPolicyId > 0 {
 | 
			
		||||
			firewallPolicy, err := SharedHTTPFirewallPolicyDAO.ComposeFirewallPolicy(tx, httpFirewallPolicyId, cacheMap)
 | 
			
		||||
@@ -1016,7 +1033,7 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap *utils
 | 
			
		||||
		// 最大线程数、TCP连接数
 | 
			
		||||
		if clusterIndex == 0 {
 | 
			
		||||
			config.MaxThreads = int(nodeCluster.NodeMaxThreads)
 | 
			
		||||
			config.TCPMaxConnections = int(nodeCluster.NodeTCPMaxConnections)
 | 
			
		||||
			config.DDOSProtection = nodeCluster.DecodeDDoSProtection()
 | 
			
		||||
			config.AutoOpenPorts = nodeCluster.AutoOpenPorts == 1
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -1148,6 +1165,16 @@ func (this *NodeDAO) ComposeNodeConfig(tx *dbs.Tx, nodeId int64, cacheMap *utils
 | 
			
		||||
	}
 | 
			
		||||
	config.OCSPVersion = ocspVersion
 | 
			
		||||
 | 
			
		||||
	// DDOS Protection
 | 
			
		||||
	var ddosProtection = node.DecodeDDoSProtection()
 | 
			
		||||
	if ddosProtection != nil {
 | 
			
		||||
		if config.DDOSProtection == nil {
 | 
			
		||||
			config.DDOSProtection = ddosProtection
 | 
			
		||||
		} else {
 | 
			
		||||
			config.DDOSProtection.Merge(ddosProtection)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 初始化扩展配置
 | 
			
		||||
	err = this.composeExtConfig(tx, config, clusterIds, cacheMap)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -1794,6 +1821,53 @@ func (this *NodeDAO) FindParentNodeConfigs(tx *dbs.Tx, nodeId int64, groupId int
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FindNodeDDoSProtection 获取节点的DDOS设置
 | 
			
		||||
func (this *NodeDAO) FindNodeDDoSProtection(tx *dbs.Tx, nodeId int64) (*ddosconfigs.ProtectionConfig, error) {
 | 
			
		||||
	one, err := this.Query(tx).
 | 
			
		||||
		Result("ddosProtection").
 | 
			
		||||
		Pk(nodeId).
 | 
			
		||||
		Find()
 | 
			
		||||
	if one == nil || err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return one.(*Node).DecodeDDoSProtection(), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateNodeDDoSProtection 设置集群的DDOS设置
 | 
			
		||||
func (this *NodeDAO) UpdateNodeDDoSProtection(tx *dbs.Tx, nodeId int64, ddosProtection *ddosconfigs.ProtectionConfig) error {
 | 
			
		||||
	if nodeId <= 0 {
 | 
			
		||||
		return ErrNotFound
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var op = NewNodeOperator()
 | 
			
		||||
	op.Id = nodeId
 | 
			
		||||
 | 
			
		||||
	if ddosProtection == nil {
 | 
			
		||||
		op.DdosProtection = "{}"
 | 
			
		||||
	} else {
 | 
			
		||||
		ddosProtectionJSON, err := json.Marshal(ddosProtection)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		op.DdosProtection = ddosProtectionJSON
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := this.Save(tx, op)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	clusterId, err := this.FindNodeClusterId(tx, nodeId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if clusterId > 0 {
 | 
			
		||||
		return SharedNodeTaskDAO.CreateNodeTask(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, 0, NodeTaskTypeDDosProtectionChanged, 0)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NotifyUpdate 通知节点相关更新
 | 
			
		||||
func (this *NodeDAO) NotifyUpdate(tx *dbs.Tx, nodeId int64) error {
 | 
			
		||||
	// 这里只需要通知单个集群即可,因为节点是公用的,更新一个就相当于更新了所有
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@ import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAPI/internal/db/models/dns"
 | 
			
		||||
	dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAPI/internal/utils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
 | 
			
		||||
	_ "github.com/go-sql-driver/mysql"
 | 
			
		||||
@@ -375,7 +376,15 @@ func (this *NodeIPAddressDAO) ListEnabledIPAddresses(tx *dbs.Tx, role string, no
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FindAllAccessibleIPAddressesWithClusterId 列出所有的正在启用的IP地址
 | 
			
		||||
func (this *NodeIPAddressDAO) FindAllAccessibleIPAddressesWithClusterId(tx *dbs.Tx, role string, clusterId int64) (result []*NodeIPAddress, err error) {
 | 
			
		||||
func (this *NodeIPAddressDAO) FindAllAccessibleIPAddressesWithClusterId(tx *dbs.Tx, role string, clusterId int64, cacheMap *utils.CacheMap) (result []*NodeIPAddress, err error) {
 | 
			
		||||
	var cacheKey = this.Table + ":FindAllAccessibleIPAddressesWithClusterId:" + role + ":" + types.String(clusterId)
 | 
			
		||||
	if cacheMap != nil {
 | 
			
		||||
		cache, ok := cacheMap.Get(cacheKey)
 | 
			
		||||
		if ok {
 | 
			
		||||
			return cache.([]*NodeIPAddress), nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, err = this.Query(tx).
 | 
			
		||||
		State(NodeIPAddressStateEnabled).
 | 
			
		||||
		Attr("role", role).
 | 
			
		||||
@@ -385,6 +394,14 @@ func (this *NodeIPAddressDAO) FindAllAccessibleIPAddressesWithClusterId(tx *dbs.
 | 
			
		||||
		Param("clusterId", clusterId).
 | 
			
		||||
		Slice(&result).
 | 
			
		||||
		FindAll()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if cacheMap != nil {
 | 
			
		||||
		cacheMap.Put(cacheKey, result)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -31,6 +31,8 @@ type Node struct {
 | 
			
		||||
	State                  uint8    `field:"state"`                  // 状态
 | 
			
		||||
	ConnectedAPINodes      dbs.JSON `field:"connectedAPINodes"`      // 当前连接的API节点
 | 
			
		||||
	MaxCPU                 uint32   `field:"maxCPU"`                 // 可以使用的最多CPU
 | 
			
		||||
	MaxThreads             uint32   `field:"maxThreads"`             // 最大线程数
 | 
			
		||||
	DdosProtection         dbs.JSON `field:"ddosProtection"`         // DDOS配置
 | 
			
		||||
	DnsRoutes              dbs.JSON `field:"dnsRoutes"`              // DNS线路设置
 | 
			
		||||
	MaxCacheDiskCapacity   dbs.JSON `field:"maxCacheDiskCapacity"`   // 硬盘缓存容量
 | 
			
		||||
	MaxCacheMemoryCapacity dbs.JSON `field:"maxCacheMemoryCapacity"` // 内存缓存容量
 | 
			
		||||
@@ -66,6 +68,8 @@ type NodeOperator struct {
 | 
			
		||||
	State                  interface{} // 状态
 | 
			
		||||
	ConnectedAPINodes      interface{} // 当前连接的API节点
 | 
			
		||||
	MaxCPU                 interface{} // 可以使用的最多CPU
 | 
			
		||||
	MaxThreads             interface{} // 最大线程数
 | 
			
		||||
	DdosProtection         interface{} // DDOS配置
 | 
			
		||||
	DnsRoutes              interface{} // DNS线路设置
 | 
			
		||||
	MaxCacheDiskCapacity   interface{} // 硬盘缓存容量
 | 
			
		||||
	MaxCacheMemoryCapacity interface{} // 内存缓存容量
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,8 @@ package models
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
@@ -97,6 +99,7 @@ func (this *Node) DecodeSecondaryClusterIds() []int64 {
 | 
			
		||||
	return result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AllClusterIds 获取所属集群IDs
 | 
			
		||||
func (this *Node) AllClusterIds() []int64 {
 | 
			
		||||
	var result = []int64{}
 | 
			
		||||
 | 
			
		||||
@@ -108,3 +111,60 @@ func (this *Node) AllClusterIds() []int64 {
 | 
			
		||||
 | 
			
		||||
	return result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DecodeDDoSProtection 解析DDoS Protection设置
 | 
			
		||||
func (this *Node) DecodeDDoSProtection() *ddosconfigs.ProtectionConfig {
 | 
			
		||||
	if IsNull(this.DdosProtection) {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var result = &ddosconfigs.ProtectionConfig{}
 | 
			
		||||
	err := json.Unmarshal(this.DdosProtection, &result)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		// ignore err
 | 
			
		||||
	}
 | 
			
		||||
	return result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HasDDoSProtection 检查是否有DDOS设置
 | 
			
		||||
func (this *Node) HasDDoSProtection() bool {
 | 
			
		||||
	var config = this.DecodeDDoSProtection()
 | 
			
		||||
	if config != nil {
 | 
			
		||||
		return !config.IsPriorEmpty()
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *Node) DecodeMaxCacheDiskCapacity() *shared.SizeCapacity {
 | 
			
		||||
	if this.MaxCacheDiskCapacity.IsNull() {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// ignore error
 | 
			
		||||
	capacity, _ := shared.DecodeSizeCapacityJSON(this.MaxCacheDiskCapacity)
 | 
			
		||||
	return capacity
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *Node) DecodeMaxCacheMemoryCapacity() *shared.SizeCapacity {
 | 
			
		||||
	if this.MaxCacheMemoryCapacity.IsNull() {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// ignore error
 | 
			
		||||
	capacity, _ := shared.DecodeSizeCapacityJSON(this.MaxCacheMemoryCapacity)
 | 
			
		||||
	return capacity
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DecodeDNSResolver 解析DNS解析主机配置
 | 
			
		||||
func (this *Node) DecodeDNSResolver() *nodeconfigs.DNSResolverConfig {
 | 
			
		||||
	if this.DnsResolver.IsNull() {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var resolverConfig = nodeconfigs.DefaultDNSResolverConfig()
 | 
			
		||||
	err := json.Unmarshal(this.DnsResolver, resolverConfig)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		// ignore error
 | 
			
		||||
	}
 | 
			
		||||
	return resolverConfig
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,8 @@ import (
 | 
			
		||||
type NodeTaskType = string
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	NodeTaskTypeConfigChanged      NodeTaskType = "configChanged"
 | 
			
		||||
	NodeTaskTypeConfigChanged         NodeTaskType = "configChanged"         // 节点整体配置变化
 | 
			
		||||
	NodeTaskTypeDDosProtectionChanged NodeTaskType = "ddosProtectionChanged" // 节点DDoS配置变更
 | 
			
		||||
	NodeTaskTypeIPItemChanged         NodeTaskType = "ipItemChanged"
 | 
			
		||||
	NodeTaskTypeNodeVersionChanged    NodeTaskType = "nodeVersionChanged"
 | 
			
		||||
	NodeTaskTypeScriptsChanged        NodeTaskType = "scriptsChanged"
 | 
			
		||||
 
 | 
			
		||||
@@ -71,7 +71,7 @@ func TestAliDNSProvider_AddRecord(t *testing.T) {
 | 
			
		||||
		Name:  "test",
 | 
			
		||||
		Type:  dnstypes.RecordTypeA,
 | 
			
		||||
		Value: "192.168.1.100",
 | 
			
		||||
		Route: "unicom",
 | 
			
		||||
		Route: "aliyun_r_cn-beijing",
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
@@ -103,7 +103,7 @@ func testAliDNSProvider() (ProviderInterface, error) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	one, err := db.FindOne("SELECT * FROM edgeDNSProviders WHERE type='alidns' ORDER BY id DESC")
 | 
			
		||||
	one, err := db.FindOne("SELECT * FROM edgeDNSProviders WHERE type='alidns' AND state=1 ORDER BY id DESC")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,7 @@ import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
 | 
			
		||||
	"github.com/andybalholm/brotli"
 | 
			
		||||
	"github.com/iwind/TeaGo/dbs"
 | 
			
		||||
@@ -767,6 +768,7 @@ func (this *NodeService) FindCurrentNodeConfig(ctx context.Context, req *pb.Find
 | 
			
		||||
		NodeJSON:     data,
 | 
			
		||||
		DataSize:     int64(len(data)),
 | 
			
		||||
		IsCompressed: isCompressed,
 | 
			
		||||
		Timestamp:    time.Now().Unix(),
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1789,3 +1791,161 @@ func (this *NodeService) UpdateNodeDNSResolver(ctx context.Context, req *pb.Upda
 | 
			
		||||
 | 
			
		||||
	return this.Success()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FindNodeDDoSProtection 获取集群的DDoS设置
 | 
			
		||||
func (this *NodeService) FindNodeDDoSProtection(ctx context.Context, req *pb.FindNodeDDoSProtectionRequest) (*pb.FindNodeDDoSProtectionResponse, error) {
 | 
			
		||||
	var nodeId = req.NodeId
 | 
			
		||||
	var isFromNode = false
 | 
			
		||||
 | 
			
		||||
	_, err := this.ValidateAdmin(ctx, 0)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		// 检查是否来自节点
 | 
			
		||||
		currentNodeId, err2 := this.ValidateNode(ctx)
 | 
			
		||||
		if err2 != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if nodeId > 0 && currentNodeId != nodeId {
 | 
			
		||||
			return nil, errors.New("invalid 'nodeId'")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		nodeId = currentNodeId
 | 
			
		||||
		isFromNode = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var tx *dbs.Tx
 | 
			
		||||
	ddosProtection, err := models.SharedNodeDAO.FindNodeDDoSProtection(tx, nodeId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if ddosProtection == nil {
 | 
			
		||||
		ddosProtection = ddosconfigs.DefaultProtectionConfig()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 组合父级节点配置
 | 
			
		||||
	// 只有从节点读取配置时才需要组合
 | 
			
		||||
	if isFromNode {
 | 
			
		||||
		clusterId, err := models.SharedNodeDAO.FindNodeClusterId(tx, nodeId)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if clusterId > 0 {
 | 
			
		||||
			clusterDDoSProtection, err := models.SharedNodeClusterDAO.FindClusterDDoSProtection(tx, clusterId)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			if clusterDDoSProtection == nil {
 | 
			
		||||
				clusterDDoSProtection = ddosconfigs.DefaultProtectionConfig()
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			clusterDDoSProtection.Merge(ddosProtection)
 | 
			
		||||
			ddosProtection = clusterDDoSProtection
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ddosProtectionJSON, err := json.Marshal(ddosProtection)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var result = &pb.FindNodeDDoSProtectionResponse{
 | 
			
		||||
		DdosProtectionJSON: ddosProtectionJSON,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return result, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateNodeDDoSProtection 修改集群的DDOS设置
 | 
			
		||||
func (this *NodeService) UpdateNodeDDoSProtection(ctx context.Context, req *pb.UpdateNodeDDoSProtectionRequest) (*pb.RPCSuccess, error) {
 | 
			
		||||
	_, err := this.ValidateAdmin(ctx, 0)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var ddosProtection = &ddosconfigs.ProtectionConfig{}
 | 
			
		||||
	err = json.Unmarshal(req.DdosProtectionJSON, ddosProtection)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var tx *dbs.Tx
 | 
			
		||||
	err = models.SharedNodeDAO.UpdateNodeDDoSProtection(tx, req.NodeId, ddosProtection)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return this.Success()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FindEnabledNodeConfigInfo 取得节点的配置概要信息
 | 
			
		||||
func (this *NodeService) FindEnabledNodeConfigInfo(ctx context.Context, req *pb.FindEnabledNodeConfigInfoRequest) (*pb.FindEnabledNodeConfigInfoResponse, error) {
 | 
			
		||||
	_, err := this.ValidateAdmin(ctx, 0)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var tx = this.NullTx()
 | 
			
		||||
	var result = &pb.FindEnabledNodeConfigInfoResponse{}
 | 
			
		||||
	node, err := models.SharedNodeDAO.FindEnabledNode(tx, req.NodeId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if node == nil {
 | 
			
		||||
		// 总是返回非空
 | 
			
		||||
		return result, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// dns
 | 
			
		||||
	if len(node.DNSRouteCodes()) > 0 {
 | 
			
		||||
		result.HasDNSInfo = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// cache
 | 
			
		||||
	if len(node.CacheDiskDir) > 0 {
 | 
			
		||||
		result.HasCacheInfo = true
 | 
			
		||||
	} else {
 | 
			
		||||
		var diskCapacity = node.DecodeMaxCacheDiskCapacity()
 | 
			
		||||
		var memoryCapacity = node.DecodeMaxCacheMemoryCapacity()
 | 
			
		||||
		if (diskCapacity != nil && diskCapacity.IsNotEmpty()) || (memoryCapacity != nil && memoryCapacity.IsNotEmpty()) {
 | 
			
		||||
			result.HasCacheInfo = true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// thresholds
 | 
			
		||||
	countThresholds, err := models.SharedNodeThresholdDAO.CountAllEnabledThresholds(tx, nodeconfigs.NodeRoleNode, 0, req.NodeId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	result.HasThresholds = countThresholds > 0
 | 
			
		||||
 | 
			
		||||
	// ssh
 | 
			
		||||
	nodeLogin, err := models.SharedNodeLoginDAO.FindEnabledNodeLoginWithNodeId(tx, nodeconfigs.NodeRoleNode, req.NodeId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if nodeLogin != nil {
 | 
			
		||||
		sshParams, err := nodeLogin.DecodeSSHParams()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		if sshParams != nil {
 | 
			
		||||
			result.HasSSH = len(sshParams.Host) > 0 || sshParams.Port > 0
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// systemSettings
 | 
			
		||||
	if node.MaxCPU > 0 {
 | 
			
		||||
		result.HasSystemSettings = true
 | 
			
		||||
	} else {
 | 
			
		||||
		// dns resolver
 | 
			
		||||
		var dnsResolverConfig = node.DecodeDNSResolver()
 | 
			
		||||
		if dnsResolverConfig != nil {
 | 
			
		||||
			result.HasSystemSettings = dnsResolverConfig.Type != nodeconfigs.DNSResolverTypeDefault
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// ddos protection
 | 
			
		||||
	result.HasDDoSProtection = node.HasDDoSProtection()
 | 
			
		||||
 | 
			
		||||
	return result, nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,7 @@ import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
 | 
			
		||||
	"github.com/iwind/TeaGo/dbs"
 | 
			
		||||
	"github.com/iwind/TeaGo/lists"
 | 
			
		||||
	"github.com/iwind/TeaGo/maps"
 | 
			
		||||
@@ -83,7 +84,7 @@ func (this *NodeClusterService) UpdateNodeCluster(ctx context.Context, req *pb.U
 | 
			
		||||
 | 
			
		||||
	tx := this.NullTx()
 | 
			
		||||
 | 
			
		||||
	err = models.SharedNodeClusterDAO.UpdateCluster(tx, req.NodeClusterId, req.Name, req.NodeGrantId, req.InstallDir, req.TimeZone, req.NodeMaxThreads, req.NodeTCPMaxConnections, req.AutoOpenPorts)
 | 
			
		||||
	err = models.SharedNodeClusterDAO.UpdateCluster(tx, req.NodeClusterId, req.Name, req.NodeGrantId, req.InstallDir, req.TimeZone, req.NodeMaxThreads, req.AutoOpenPorts)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -162,7 +163,6 @@ func (this *NodeClusterService) FindEnabledNodeCluster(ctx context.Context, req
 | 
			
		||||
		IsOn:                 cluster.IsOn,
 | 
			
		||||
		TimeZone:             cluster.TimeZone,
 | 
			
		||||
		NodeMaxThreads:       int32(cluster.NodeMaxThreads),
 | 
			
		||||
		NodeTCPMaxConnections: int32(cluster.NodeTCPMaxConnections),
 | 
			
		||||
		AutoOpenPorts:        cluster.AutoOpenPorts == 1,
 | 
			
		||||
	}}, nil
 | 
			
		||||
}
 | 
			
		||||
@@ -1054,6 +1054,9 @@ func (this *NodeClusterService) FindEnabledNodeClusterConfigInfo(ctx context.Con
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// ddos
 | 
			
		||||
	result.HasDDoSProtection = cluster.HasDDoSProtection()
 | 
			
		||||
 | 
			
		||||
	return result, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1114,3 +1117,51 @@ func (this *NodeClusterService) UpdateNodeClusterWebPPolicy(ctx context.Context,
 | 
			
		||||
	}
 | 
			
		||||
	return this.Success()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FindNodeClusterDDoSProtection 获取集群的DDOS设置
 | 
			
		||||
func (this *NodeClusterService) FindNodeClusterDDoSProtection(ctx context.Context, req *pb.FindNodeClusterDDoSProtectionRequest) (*pb.FindNodeClusterDDoSProtectionResponse, error) {
 | 
			
		||||
	_, err := this.ValidateAdmin(ctx, 0)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var tx *dbs.Tx
 | 
			
		||||
	ddosProtection, err := models.SharedNodeClusterDAO.FindClusterDDoSProtection(tx, req.NodeClusterId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if ddosProtection == nil {
 | 
			
		||||
		ddosProtection = ddosconfigs.DefaultProtectionConfig()
 | 
			
		||||
	}
 | 
			
		||||
	ddosProtectionJSON, err := json.Marshal(ddosProtection)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var result = &pb.FindNodeClusterDDoSProtectionResponse{
 | 
			
		||||
		DdosProtectionJSON: ddosProtectionJSON,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return result, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateNodeClusterDDoSProtection 修改集群的DDOS设置
 | 
			
		||||
func (this *NodeClusterService) UpdateNodeClusterDDoSProtection(ctx context.Context, req *pb.UpdateNodeClusterDDoSProtectionRequest) (*pb.RPCSuccess, error) {
 | 
			
		||||
	_, err := this.ValidateAdmin(ctx, 0)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var ddosProtection = &ddosconfigs.ProtectionConfig{}
 | 
			
		||||
	err = json.Unmarshal(req.DdosProtectionJSON, ddosProtection)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var tx *dbs.Tx
 | 
			
		||||
	err = models.SharedNodeClusterDAO.UpdateClusterDDoSProtection(tx, req.NodeClusterId, ddosProtection)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return this.Success()
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user