diff --git a/go.sum b/go.sum index a811d7f3..e8fa853b 100644 --- a/go.sum +++ b/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= diff --git a/internal/db/models/node_cluster_dao.go b/internal/db/models/node_cluster_dao.go index e7e2cf77..eac3f412 100644 --- a/internal/db/models/node_cluster_dao.go +++ b/internal/db/models/node_cluster_dao.go @@ -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) diff --git a/internal/db/models/node_cluster_model.go b/internal/db/models/node_cluster_model.go index 451cfee5..696e12aa 100644 --- a/internal/db/models/node_cluster_model.go +++ b/internal/db/models/node_cluster_model.go @@ -4,69 +4,69 @@ import "github.com/iwind/TeaGo/dbs" // NodeCluster 节点集群 type NodeCluster struct { - Id uint32 `field:"id"` // ID - AdminId uint32 `field:"adminId"` // 管理员ID - UserId uint32 `field:"userId"` // 用户ID - IsOn bool `field:"isOn"` // 是否启用 - Name string `field:"name"` // 名称 - UseAllAPINodes uint8 `field:"useAllAPINodes"` // 是否使用所有API节点 - ApiNodes dbs.JSON `field:"apiNodes"` // 使用的API节点 - InstallDir string `field:"installDir"` // 安装目录 - Order uint32 `field:"order"` // 排序 - CreatedAt uint64 `field:"createdAt"` // 创建时间 - GrantId uint32 `field:"grantId"` // 默认认证方式 - State uint8 `field:"state"` // 状态 - AutoRegister uint8 `field:"autoRegister"` // 是否开启自动注册 - UniqueId string `field:"uniqueId"` // 唯一ID - Secret string `field:"secret"` // 密钥 - HealthCheck dbs.JSON `field:"healthCheck"` // 健康检查 - DnsName string `field:"dnsName"` // DNS名称 - DnsDomainId uint32 `field:"dnsDomainId"` // 域名ID - Dns dbs.JSON `field:"dns"` // DNS配置 - Toa dbs.JSON `field:"toa"` // TOA配置 - CachePolicyId uint32 `field:"cachePolicyId"` // 缓存策略ID - HttpFirewallPolicyId uint32 `field:"httpFirewallPolicyId"` // WAF策略ID - AccessLog dbs.JSON `field:"accessLog"` // 访问日志设置 - SystemServices dbs.JSON `field:"systemServices"` // 系统服务设置 - TimeZone string `field:"timeZone"` // 时区 - NodeMaxThreads uint32 `field:"nodeMaxThreads"` // 节点最大线程数 - NodeTCPMaxConnections uint32 `field:"nodeTCPMaxConnections"` // TCP最大连接数 - AutoOpenPorts uint8 `field:"autoOpenPorts"` // 是否自动尝试开放端口 - IsPinned bool `field:"isPinned"` // 是否置顶 - Webp dbs.JSON `field:"webp"` // WebP设置 + Id uint32 `field:"id"` // ID + AdminId uint32 `field:"adminId"` // 管理员ID + UserId uint32 `field:"userId"` // 用户ID + IsOn bool `field:"isOn"` // 是否启用 + Name string `field:"name"` // 名称 + UseAllAPINodes uint8 `field:"useAllAPINodes"` // 是否使用所有API节点 + ApiNodes dbs.JSON `field:"apiNodes"` // 使用的API节点 + InstallDir string `field:"installDir"` // 安装目录 + Order uint32 `field:"order"` // 排序 + CreatedAt uint64 `field:"createdAt"` // 创建时间 + GrantId uint32 `field:"grantId"` // 默认认证方式 + State uint8 `field:"state"` // 状态 + AutoRegister uint8 `field:"autoRegister"` // 是否开启自动注册 + UniqueId string `field:"uniqueId"` // 唯一ID + Secret string `field:"secret"` // 密钥 + HealthCheck dbs.JSON `field:"healthCheck"` // 健康检查 + DnsName string `field:"dnsName"` // DNS名称 + DnsDomainId uint32 `field:"dnsDomainId"` // 域名ID + Dns dbs.JSON `field:"dns"` // DNS配置 + Toa dbs.JSON `field:"toa"` // TOA配置 + CachePolicyId uint32 `field:"cachePolicyId"` // 缓存策略ID + HttpFirewallPolicyId uint32 `field:"httpFirewallPolicyId"` // WAF策略ID + AccessLog dbs.JSON `field:"accessLog"` // 访问日志设置 + SystemServices dbs.JSON `field:"systemServices"` // 系统服务设置 + TimeZone string `field:"timeZone"` // 时区 + NodeMaxThreads uint32 `field:"nodeMaxThreads"` // 节点最大线程数 + DdosProtection dbs.JSON `field:"ddosProtection"` // DDOS端口 + AutoOpenPorts uint8 `field:"autoOpenPorts"` // 是否自动尝试开放端口 + IsPinned bool `field:"isPinned"` // 是否置顶 + Webp dbs.JSON `field:"webp"` // WebP设置 } type NodeClusterOperator struct { - Id interface{} // ID - AdminId interface{} // 管理员ID - UserId interface{} // 用户ID - IsOn interface{} // 是否启用 - Name interface{} // 名称 - UseAllAPINodes interface{} // 是否使用所有API节点 - ApiNodes interface{} // 使用的API节点 - InstallDir interface{} // 安装目录 - Order interface{} // 排序 - CreatedAt interface{} // 创建时间 - GrantId interface{} // 默认认证方式 - State interface{} // 状态 - AutoRegister interface{} // 是否开启自动注册 - UniqueId interface{} // 唯一ID - Secret interface{} // 密钥 - HealthCheck interface{} // 健康检查 - DnsName interface{} // DNS名称 - DnsDomainId interface{} // 域名ID - Dns interface{} // DNS配置 - Toa interface{} // TOA配置 - CachePolicyId interface{} // 缓存策略ID - HttpFirewallPolicyId interface{} // WAF策略ID - AccessLog interface{} // 访问日志设置 - SystemServices interface{} // 系统服务设置 - TimeZone interface{} // 时区 - NodeMaxThreads interface{} // 节点最大线程数 - NodeTCPMaxConnections interface{} // TCP最大连接数 - AutoOpenPorts interface{} // 是否自动尝试开放端口 - IsPinned interface{} // 是否置顶 - Webp interface{} // WebP设置 + Id interface{} // ID + AdminId interface{} // 管理员ID + UserId interface{} // 用户ID + IsOn interface{} // 是否启用 + Name interface{} // 名称 + UseAllAPINodes interface{} // 是否使用所有API节点 + ApiNodes interface{} // 使用的API节点 + InstallDir interface{} // 安装目录 + Order interface{} // 排序 + CreatedAt interface{} // 创建时间 + GrantId interface{} // 默认认证方式 + State interface{} // 状态 + AutoRegister interface{} // 是否开启自动注册 + UniqueId interface{} // 唯一ID + Secret interface{} // 密钥 + HealthCheck interface{} // 健康检查 + DnsName interface{} // DNS名称 + DnsDomainId interface{} // 域名ID + Dns interface{} // DNS配置 + Toa interface{} // TOA配置 + CachePolicyId interface{} // 缓存策略ID + HttpFirewallPolicyId interface{} // WAF策略ID + AccessLog interface{} // 访问日志设置 + SystemServices interface{} // 系统服务设置 + TimeZone interface{} // 时区 + NodeMaxThreads interface{} // 节点最大线程数 + DdosProtection interface{} // DDOS端口 + AutoOpenPorts interface{} // 是否自动尝试开放端口 + IsPinned interface{} // 是否置顶 + Webp interface{} // WebP设置 } func NewNodeClusterOperator() *NodeClusterOperator { diff --git a/internal/db/models/node_cluster_model_ext.go b/internal/db/models/node_cluster_model_ext.go index b9454eb5..e4a3b930 100644 --- a/internal/db/models/node_cluster_model_ext.go +++ b/internal/db/models/node_cluster_model_ext.go @@ -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 +} diff --git a/internal/db/models/node_dao.go b/internal/db/models/node_dao.go index 389c452f..65171504 100644 --- a/internal/db/models/node_dao.go +++ b/internal/db/models/node_dao.go @@ -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 { // 这里只需要通知单个集群即可,因为节点是公用的,更新一个就相当于更新了所有 diff --git a/internal/db/models/node_ip_address_dao.go b/internal/db/models/node_ip_address_dao.go index 485a8a80..6d138b0a 100644 --- a/internal/db/models/node_ip_address_dao.go +++ b/internal/db/models/node_ip_address_dao.go @@ -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 } diff --git a/internal/db/models/node_model.go b/internal/db/models/node_model.go index b4078fbf..e6d4b8b3 100644 --- a/internal/db/models/node_model.go +++ b/internal/db/models/node_model.go @@ -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{} // 内存缓存容量 diff --git a/internal/db/models/node_model_ext.go b/internal/db/models/node_model_ext.go index 01e10d2e..9ce1b89f 100644 --- a/internal/db/models/node_model_ext.go +++ b/internal/db/models/node_model_ext.go @@ -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 +} diff --git a/internal/db/models/node_task_dao.go b/internal/db/models/node_task_dao.go index d10036d0..e6255e63 100644 --- a/internal/db/models/node_task_dao.go +++ b/internal/db/models/node_task_dao.go @@ -14,11 +14,12 @@ import ( type NodeTaskType = string const ( - NodeTaskTypeConfigChanged NodeTaskType = "configChanged" - NodeTaskTypeIPItemChanged NodeTaskType = "ipItemChanged" - NodeTaskTypeNodeVersionChanged NodeTaskType = "nodeVersionChanged" - NodeTaskTypeScriptsChanged NodeTaskType = "scriptsChanged" - NodeTaskTypeNodeLevelChanged NodeTaskType = "nodeLevelChanged" + NodeTaskTypeConfigChanged NodeTaskType = "configChanged" // 节点整体配置变化 + NodeTaskTypeDDosProtectionChanged NodeTaskType = "ddosProtectionChanged" // 节点DDoS配置变更 + NodeTaskTypeIPItemChanged NodeTaskType = "ipItemChanged" + NodeTaskTypeNodeVersionChanged NodeTaskType = "nodeVersionChanged" + NodeTaskTypeScriptsChanged NodeTaskType = "scriptsChanged" + NodeTaskTypeNodeLevelChanged NodeTaskType = "nodeLevelChanged" // NS相关 diff --git a/internal/dnsclients/provider_alidns_test.go b/internal/dnsclients/provider_alidns_test.go index 938542c7..685450eb 100644 --- a/internal/dnsclients/provider_alidns_test.go +++ b/internal/dnsclients/provider_alidns_test.go @@ -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 } diff --git a/internal/rpc/services/service_node.go b/internal/rpc/services/service_node.go index d58abfbb..43457745 100644 --- a/internal/rpc/services/service_node.go +++ b/internal/rpc/services/service_node.go @@ -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 +} diff --git a/internal/rpc/services/service_node_cluster.go b/internal/rpc/services/service_node_cluster.go index 58617839..ac0c9dfb 100644 --- a/internal/rpc/services/service_node_cluster.go +++ b/internal/rpc/services/service_node_cluster.go @@ -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 } @@ -148,22 +149,21 @@ func (this *NodeClusterService) FindEnabledNodeCluster(ctx context.Context, req } return &pb.FindEnabledNodeClusterResponse{NodeCluster: &pb.NodeCluster{ - Id: int64(cluster.Id), - Name: cluster.Name, - CreatedAt: int64(cluster.CreatedAt), - InstallDir: cluster.InstallDir, - NodeGrantId: int64(cluster.GrantId), - UniqueId: cluster.UniqueId, - Secret: cluster.Secret, - HttpCachePolicyId: int64(cluster.CachePolicyId), - HttpFirewallPolicyId: int64(cluster.HttpFirewallPolicyId), - DnsName: cluster.DnsName, - DnsDomainId: int64(cluster.DnsDomainId), - IsOn: cluster.IsOn, - TimeZone: cluster.TimeZone, - NodeMaxThreads: int32(cluster.NodeMaxThreads), - NodeTCPMaxConnections: int32(cluster.NodeTCPMaxConnections), - AutoOpenPorts: cluster.AutoOpenPorts == 1, + Id: int64(cluster.Id), + Name: cluster.Name, + CreatedAt: int64(cluster.CreatedAt), + InstallDir: cluster.InstallDir, + NodeGrantId: int64(cluster.GrantId), + UniqueId: cluster.UniqueId, + Secret: cluster.Secret, + HttpCachePolicyId: int64(cluster.CachePolicyId), + HttpFirewallPolicyId: int64(cluster.HttpFirewallPolicyId), + DnsName: cluster.DnsName, + DnsDomainId: int64(cluster.DnsDomainId), + IsOn: cluster.IsOn, + TimeZone: cluster.TimeZone, + NodeMaxThreads: int32(cluster.NodeMaxThreads), + 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() +}