1.4.5.2
This commit is contained in:
22
EdgeCommon/pkg/nodeconfigs/clock_config.go
Normal file
22
EdgeCommon/pkg/nodeconfigs/clock_config.go
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package nodeconfigs
|
||||
|
||||
func DefaultClockConfig() *ClockConfig {
|
||||
return &ClockConfig{
|
||||
AutoSync: true,
|
||||
Server: "",
|
||||
CheckChrony: true,
|
||||
}
|
||||
}
|
||||
|
||||
// ClockConfig 时钟相关配置
|
||||
type ClockConfig struct {
|
||||
AutoSync bool `yaml:"autoSync" json:"autoSync"` // 自动尝试同步时钟
|
||||
Server string `yaml:"server" json:"server"` // 时钟同步服务器
|
||||
CheckChrony bool `yaml:"checkChrony" json:"checkChrony"` // 检查 chronyd 是否在运行
|
||||
}
|
||||
|
||||
func (this *ClockConfig) Init() error {
|
||||
return nil
|
||||
}
|
||||
11
EdgeCommon/pkg/nodeconfigs/connectivity.go
Normal file
11
EdgeCommon/pkg/nodeconfigs/connectivity.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package nodeconfigs
|
||||
|
||||
import "github.com/TeaOSLab/EdgeCommon/pkg/reporterconfigs"
|
||||
|
||||
// Connectivity 连通性状态
|
||||
type Connectivity struct {
|
||||
CostMs float64 `json:"costMs"` // 平均耗时
|
||||
Level reporterconfigs.ReportLevel `json:"level"` // 级别
|
||||
Percent float64 `json:"percent"` // 连通的百分比,是一个0到100之间的小数
|
||||
UpdatedAt int64 `json:"updatedAt"` // 更新时间
|
||||
}
|
||||
37
EdgeCommon/pkg/nodeconfigs/defaults.go
Normal file
37
EdgeCommon/pkg/nodeconfigs/defaults.go
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package nodeconfigs
|
||||
|
||||
import "github.com/iwind/TeaGo/maps"
|
||||
|
||||
// 一组系统默认值
|
||||
// 修改单个IP相关限制值时要考虑到NAT中每个IP会代表很多个主机,并非1对1的关系
|
||||
|
||||
const (
|
||||
DefaultMaxThreads = 20000 // 单节点最大线程数
|
||||
DefaultMaxThreadsMin = 1000 // 单节点最大线程数最小值
|
||||
DefaultMaxThreadsMax = 100_000 // 单节点最大线程数最大值
|
||||
|
||||
DefaultTCPMaxConnections = 100_000 // 单节点TCP最大连接数
|
||||
DefaultTCPMaxConnectionsPerIP = 1000 // 单IP最大连接数
|
||||
DefaultTCPMinConnectionsPerIP = 5 // 单IP最小连接数
|
||||
|
||||
DefaultTCPNewConnectionsMinutelyRate = 500 // 单IP连接速率限制(按分钟)
|
||||
DefaultTCPNewConnectionsMinMinutelyRate = 3 // 单IP最小连接速率
|
||||
|
||||
DefaultTCPNewConnectionsSecondlyRate = 300 // 单IP连接速率限制(按秒)
|
||||
DefaultTCPNewConnectionsMinSecondlyRate = 3 // 单IP最小连接速率
|
||||
|
||||
DefaultTCPLinger = 5 // 单节点TCP Linger值
|
||||
DefaultTLSHandshakeTimeout = 3 // TLS握手超时时间
|
||||
)
|
||||
|
||||
var DefaultConfigs = maps.Map{
|
||||
"tcpMaxConnections": DefaultTCPMaxConnections,
|
||||
"tcpMaxConnectionsPerIP": DefaultTCPMaxConnectionsPerIP,
|
||||
"tcpMinConnectionsPerIP": DefaultTCPMinConnectionsPerIP,
|
||||
"tcpNewConnectionsMinutelyRate": DefaultTCPNewConnectionsMinutelyRate,
|
||||
"tcpNewConnectionsMinMinutelyRate": DefaultTCPNewConnectionsMinMinutelyRate,
|
||||
"tcpNewConnectionsSecondlyRate": DefaultTCPNewConnectionsSecondlyRate,
|
||||
"tcpNewConnectionsMinSecondlyRate": DefaultTCPNewConnectionsMinSecondlyRate,
|
||||
}
|
||||
25
EdgeCommon/pkg/nodeconfigs/dns_resolver.go
Normal file
25
EdgeCommon/pkg/nodeconfigs/dns_resolver.go
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package nodeconfigs
|
||||
|
||||
type DNSResolverType = string
|
||||
|
||||
const (
|
||||
DNSResolverTypeDefault = "default"
|
||||
DNSResolverTypeGoNative = "goNative"
|
||||
DNSResolverTypeCGO = "cgo"
|
||||
)
|
||||
|
||||
func DefaultDNSResolverConfig() *DNSResolverConfig {
|
||||
return &DNSResolverConfig{
|
||||
Type: DNSResolverTypeDefault,
|
||||
}
|
||||
}
|
||||
|
||||
type DNSResolverConfig struct {
|
||||
Type string `yaml:"type" json:"type"` // 使用Go语言内置的DNS解析器
|
||||
}
|
||||
|
||||
func (this *DNSResolverConfig) Init() error {
|
||||
return nil
|
||||
}
|
||||
25
EdgeCommon/pkg/nodeconfigs/http3_policy.go
Normal file
25
EdgeCommon/pkg/nodeconfigs/http3_policy.go
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package nodeconfigs
|
||||
|
||||
const DefaultHTTP3Port = 443
|
||||
|
||||
type HTTP3Policy struct {
|
||||
IsOn bool `yaml:"isOn" json:"isOn"`
|
||||
Port int `yaml:"port" json:"port"`
|
||||
SupportMobileBrowsers bool `yaml:"supportMobileBrowsers" json:"supportMobileBrowsers"` // enable http/3 on common mobile browsers
|
||||
}
|
||||
|
||||
func NewHTTP3Policy() *HTTP3Policy {
|
||||
return &HTTP3Policy{
|
||||
Port: DefaultHTTP3Port,
|
||||
SupportMobileBrowsers: false,
|
||||
}
|
||||
}
|
||||
|
||||
func (this *HTTP3Policy) Init() error {
|
||||
if this.Port <= 0 {
|
||||
this.Port = DefaultHTTP3Port
|
||||
}
|
||||
return nil
|
||||
}
|
||||
22
EdgeCommon/pkg/nodeconfigs/http_cc_policy.go
Normal file
22
EdgeCommon/pkg/nodeconfigs/http_cc_policy.go
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build !plus
|
||||
|
||||
package nodeconfigs
|
||||
|
||||
import "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
|
||||
// HTTPCCPolicy CC策略
|
||||
type HTTPCCPolicy struct {
|
||||
IsOn bool `json:"isOn" yaml:"isOn"`
|
||||
Thresholds []*serverconfigs.HTTPCCThreshold `json:"thresholds" yaml:"thresholds"` // 阈值
|
||||
}
|
||||
|
||||
func NewHTTPCCPolicy() *HTTPCCPolicy {
|
||||
return &HTTPCCPolicy{
|
||||
IsOn: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (this *HTTPCCPolicy) Init() error {
|
||||
return nil
|
||||
}
|
||||
56
EdgeCommon/pkg/nodeconfigs/http_cc_policy_plus.go
Normal file
56
EdgeCommon/pkg/nodeconfigs/http_cc_policy_plus.go
Normal file
@@ -0,0 +1,56 @@
|
||||
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package nodeconfigs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||
)
|
||||
|
||||
const (
|
||||
HTTPCCPolicyMaxConnectionsPerIP = 30
|
||||
HTTPCCPolicyRedirectsCheckingValidatePath = "/GE/CC/VALIDATOR"
|
||||
HTTPCCPolicyRedirectsCheckingDurationSeconds = 120
|
||||
HTTPCCPolicyRedirectsCheckingMaxRedirects = 30
|
||||
HTTPCCPolicyRedirectsCheckingBlockSeconds = 3600
|
||||
)
|
||||
|
||||
// HTTPCCPolicy CC策略
|
||||
type HTTPCCPolicy struct {
|
||||
IsOn bool `json:"isOn" yaml:"isOn"`
|
||||
Thresholds []*serverconfigs.HTTPCCThreshold `json:"thresholds" yaml:"thresholds"` // 阈值
|
||||
MaxConnectionsPerIP int `json:"maxConnectionsPerIP" yaml:"maxConnectionsPerIP"` // 单IP最大并发连接数
|
||||
|
||||
// 跳转校验
|
||||
RedirectsChecking struct {
|
||||
ValidatePath string `json:"validatePath" yaml:"validatePath"` // 校验路径
|
||||
DurationSeconds int `json:"durationSeconds" yaml:"durationSeconds"` // 无效跳转检测周期
|
||||
MaxRedirects int `json:"maxRedirects" yaml:"maxRedirects"` // 最大跳转次数
|
||||
BlockSeconds int `json:"blockSeconds" yaml:"blockSeconds"` // 拦截时间
|
||||
} `json:"redirectsChecking" yaml:"redirectsChecking"`
|
||||
|
||||
// 防火墙策略
|
||||
Firewall struct {
|
||||
Scope firewallconfigs.FirewallScope `json:"scope" yaml:"scope"`
|
||||
} `json:"firewall" yaml:"firewall"`
|
||||
}
|
||||
|
||||
func NewHTTPCCPolicy() *HTTPCCPolicy {
|
||||
var policy = &HTTPCCPolicy{
|
||||
IsOn: true,
|
||||
}
|
||||
policy.Firewall.Scope = firewallconfigs.FirewallScopeGlobal
|
||||
return policy
|
||||
}
|
||||
|
||||
func (this *HTTPCCPolicy) Init() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *HTTPCCPolicy) FirewallScope() firewallconfigs.FirewallScope {
|
||||
if len(this.Firewall.Scope) == 0 {
|
||||
return firewallconfigs.FirewallScopeGlobal
|
||||
}
|
||||
return this.Firewall.Scope
|
||||
}
|
||||
28
EdgeCommon/pkg/nodeconfigs/http_pages_policy.go
Normal file
28
EdgeCommon/pkg/nodeconfigs/http_pages_policy.go
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package nodeconfigs
|
||||
|
||||
import "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
|
||||
// HTTPPagesPolicy 全局的HTTP自定义页面设置
|
||||
type HTTPPagesPolicy struct {
|
||||
IsOn bool `json:"isOn" yaml:"isOn"` // 是否启用
|
||||
Pages []*serverconfigs.HTTPPageConfig `json:"pages" yaml:"pages"` // 自定义页面
|
||||
}
|
||||
|
||||
func NewHTTPPagesPolicy() *HTTPPagesPolicy {
|
||||
return &HTTPPagesPolicy{}
|
||||
}
|
||||
|
||||
func (this *HTTPPagesPolicy) Init() error {
|
||||
if len(this.Pages) > 0 {
|
||||
for _, page := range this.Pages {
|
||||
err := page.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
51
EdgeCommon/pkg/nodeconfigs/image_webp_policy.go
Normal file
51
EdgeCommon/pkg/nodeconfigs/image_webp_policy.go
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package nodeconfigs
|
||||
|
||||
import "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
|
||||
func init() {
|
||||
_ = DefaultWebPImagePolicy.Init()
|
||||
}
|
||||
|
||||
var DefaultWebPImagePolicy = NewWebPImagePolicy()
|
||||
|
||||
func NewWebPImagePolicy() *WebPImagePolicy {
|
||||
return &WebPImagePolicy{
|
||||
IsOn: true,
|
||||
RequireCache: true,
|
||||
MinLength: shared.NewSizeCapacity(0, shared.SizeCapacityUnitKB),
|
||||
MaxLength: shared.NewSizeCapacity(128, shared.SizeCapacityUnitMB),
|
||||
}
|
||||
}
|
||||
|
||||
// WebPImagePolicy WebP策略
|
||||
type WebPImagePolicy struct {
|
||||
IsOn bool `yaml:"isOn" json:"isOn"` // 是否启用
|
||||
RequireCache bool `yaml:"requireCache" json:"requireCache"` // 需要在缓存条件下进行
|
||||
MinLength *shared.SizeCapacity `yaml:"minLength" json:"minLength"` // 最小压缩对象比如4m, 24k
|
||||
MaxLength *shared.SizeCapacity `yaml:"maxLength" json:"maxLength"` // 最大压缩对象
|
||||
Quality int `yaml:"quality" json:"quality"` // 生成的图片质量:0-100
|
||||
|
||||
minLength int64
|
||||
maxLength int64
|
||||
}
|
||||
|
||||
func (this *WebPImagePolicy) Init() error {
|
||||
if this.MinLength != nil {
|
||||
this.minLength = this.MinLength.Bytes()
|
||||
}
|
||||
if this.MaxLength != nil {
|
||||
this.maxLength = this.MaxLength.Bytes()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *WebPImagePolicy) MinLengthBytes() int64 {
|
||||
return this.minLength
|
||||
}
|
||||
|
||||
func (this *WebPImagePolicy) MaxLengthBytes() int64 {
|
||||
return this.maxLength
|
||||
}
|
||||
49
EdgeCommon/pkg/nodeconfigs/networking_security_policy.go
Normal file
49
EdgeCommon/pkg/nodeconfigs/networking_security_policy.go
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package nodeconfigs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
type NetworkSecurityStatus = string
|
||||
|
||||
const (
|
||||
NetworkSecurityStatusAuto NetworkSecurityStatus = "auto"
|
||||
NetworkSecurityStatusOn NetworkSecurityStatus = "on"
|
||||
NetworkSecurityStatusOff NetworkSecurityStatus = "off"
|
||||
)
|
||||
|
||||
// NetworkSecurityPolicy 节点网络安全策略
|
||||
type NetworkSecurityPolicy struct {
|
||||
Status NetworkSecurityStatus `json:"status"` // 启用状态
|
||||
|
||||
TCP struct{} `json:"tcp"` // TODO
|
||||
UDP struct{} `json:"udp"` // TODO
|
||||
ICMP struct{} `json:"icmp"` // TODO
|
||||
}
|
||||
|
||||
func NewNetworkSecurityPolicy() *NetworkSecurityPolicy {
|
||||
var policy = &NetworkSecurityPolicy{}
|
||||
policy.Status = NetworkSecurityStatusAuto
|
||||
return policy
|
||||
}
|
||||
|
||||
func (this *NetworkSecurityPolicy) Init() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *NetworkSecurityPolicy) AsJSON() ([]byte, error) {
|
||||
return json.Marshal(this)
|
||||
}
|
||||
|
||||
func (this *NetworkSecurityPolicy) IsOn() bool {
|
||||
return this.Status != NetworkSecurityStatusOff
|
||||
}
|
||||
|
||||
func (this *NetworkSecurityPolicy) IsSame(anotherPolicy *NetworkSecurityPolicy) bool {
|
||||
data1, _ := json.Marshal(this)
|
||||
data2, _ := json.Marshal(anotherPolicy)
|
||||
return bytes.Equal(data1, data2)
|
||||
}
|
||||
455
EdgeCommon/pkg/nodeconfigs/node_actions_plus.go
Normal file
455
EdgeCommon/pkg/nodeconfigs/node_actions_plus.go
Normal file
@@ -0,0 +1,455 @@
|
||||
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package nodeconfigs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
type NodeActionParam = string
|
||||
|
||||
const (
|
||||
NodeActionParamDailyTrafficOut NodeActionParam = "dailyTrafficOut" // 节点日出口流量
|
||||
NodeActionParamMonthlyTrafficOut NodeActionParam = "monthlyTrafficOut" // 节点月出口流量
|
||||
|
||||
// NodeActionParamTotalTraffic NodeActionParam = "totalTraffic" // 节点总流量 TODO 需要实现
|
||||
|
||||
NodeActionParamBandwidthIn NodeActionParam = "bandwidthIn" // 节点入口带宽
|
||||
NodeActionParamBandwidthOut NodeActionParam = "bandwidthOut" // 节点出口带宽
|
||||
NodeActionParamUDPDPSIn NodeActionParam = "udpDPSIn" // 节点单秒入口UDP数据报数量
|
||||
NodeActionParamUDPDPSOut NodeActionParam = "udpDPSOut" // 节点单秒出口UDP数据报数量
|
||||
NodeActionParamCPUUsage NodeActionParam = "cpuUsage" // 节点CPU用量,百分比制,0-100
|
||||
NodeActionParamMemoryUsage NodeActionParam = "memoryUsage" // 节点内存用量,百分比制,0-100
|
||||
NodeActionParamLoad NodeActionParam = "load" // 当前节点负载
|
||||
|
||||
// NodeActionParamConnectivity NodeActionParam = "connectivity" // 节点连通性 TODO 需要实现
|
||||
|
||||
NodeActionParamHealthCheckFailure NodeActionParam = "heathCheckFailure" // 节点健康检查失败
|
||||
)
|
||||
|
||||
type NodeActionParamDefinition struct {
|
||||
Name string `json:"name"`
|
||||
Code string `json:"code"`
|
||||
Description string `json:"description"`
|
||||
Operators []NodeActionOperator `json:"operators"`
|
||||
ValueName string `json:"valueName"`
|
||||
ValueType string `json:"valueType"`
|
||||
HasDuration bool `json:"hasDuration"`
|
||||
}
|
||||
|
||||
func FindAllNodeActionParamDefinitions() []*NodeActionParamDefinition {
|
||||
return []*NodeActionParamDefinition{
|
||||
{
|
||||
Code: NodeActionParamBandwidthOut,
|
||||
Name: "节点出口带宽",
|
||||
Description: "当前节点当前时间点的出口发送平均带宽(从节点发送到客户端)。",
|
||||
Operators: allNodeActionNumberOperators,
|
||||
ValueName: "对比带宽",
|
||||
ValueType: "bandwidth",
|
||||
HasDuration: true,
|
||||
},
|
||||
{
|
||||
Code: NodeActionParamBandwidthIn,
|
||||
Name: "节点入口带宽",
|
||||
Description: "当前节点当前时间点的入口接收平均带宽(从客户端发送到节点)。",
|
||||
Operators: allNodeActionNumberOperators,
|
||||
ValueName: "对比带宽",
|
||||
ValueType: "bandwidth",
|
||||
HasDuration: true,
|
||||
},
|
||||
{
|
||||
Code: NodeActionParamMonthlyTrafficOut,
|
||||
Name: "节点当月流量",
|
||||
Description: "当前节点在当月的出口发送流量。",
|
||||
Operators: allNodeActionNumberOperators,
|
||||
ValueName: "对比流量",
|
||||
ValueType: "traffic",
|
||||
HasDuration: false,
|
||||
},
|
||||
{
|
||||
Code: NodeActionParamDailyTrafficOut,
|
||||
Name: "节点当日流量",
|
||||
Description: "当前节点在当天的出口发送流量。",
|
||||
Operators: allNodeActionNumberOperators,
|
||||
ValueName: "对比流量",
|
||||
ValueType: "traffic",
|
||||
HasDuration: false,
|
||||
},
|
||||
{
|
||||
Code: NodeActionParamCPUUsage,
|
||||
Name: "节点CPU利用率",
|
||||
Description: "节点当前CPU利用率,取值范围为0-100。",
|
||||
Operators: allNodeActionNumberOperators,
|
||||
ValueName: "CPU利用率",
|
||||
ValueType: "cpu",
|
||||
HasDuration: true,
|
||||
},
|
||||
{
|
||||
Code: NodeActionParamMemoryUsage,
|
||||
Name: "节点内存利用率",
|
||||
Description: "节点当前内存利用率,取值范围为0-100。",
|
||||
Operators: allNodeActionNumberOperators,
|
||||
ValueName: "内存利用率",
|
||||
ValueType: "memory",
|
||||
HasDuration: true,
|
||||
},
|
||||
{
|
||||
Code: NodeActionParamLoad,
|
||||
Name: "节点负载",
|
||||
Description: "节点当前负载,取值范围为0-∞,通常超过10表示系统负载较重。",
|
||||
Operators: allNodeActionNumberOperators,
|
||||
ValueName: "系统负载",
|
||||
ValueType: "load",
|
||||
HasDuration: true,
|
||||
},
|
||||
{
|
||||
Code: NodeActionParamHealthCheckFailure,
|
||||
Name: "节点健康检查失败",
|
||||
Description: "当前节点任一IP健康检查失败,此功能需要当前集群开启健康检查。",
|
||||
Operators: nil,
|
||||
HasDuration: true,
|
||||
},
|
||||
{
|
||||
Code: NodeActionParamUDPDPSOut,
|
||||
Name: "节点UDP数据报发送速率",
|
||||
Description: "当前节点当前时间点的UDP数据报发送速率。",
|
||||
Operators: allNodeActionNumberOperators,
|
||||
ValueName: "对比速率",
|
||||
ValueType: "rate",
|
||||
HasDuration: true,
|
||||
},
|
||||
{
|
||||
Code: NodeActionParamUDPDPSIn,
|
||||
Name: "节点UDP数据报接收速率",
|
||||
Description: "当前节点当前时间点的UDP数据报接收速率。",
|
||||
Operators: allNodeActionNumberOperators,
|
||||
ValueName: "对比速率",
|
||||
ValueType: "rate",
|
||||
HasDuration: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type NodeActionOperator = string
|
||||
|
||||
const (
|
||||
NodeActionOperatorGt NodeActionOperator = "gt"
|
||||
NodeActionOperatorGte NodeActionOperator = "gte"
|
||||
NodeActionOperatorLt NodeActionOperator = "lt"
|
||||
NodeActionOperatorLte NodeActionOperator = "lte"
|
||||
NodeActionOperatorEq NodeActionOperator = "eq"
|
||||
)
|
||||
|
||||
var allNodeActionNumberOperators = []NodeActionOperator{NodeActionOperatorGt, NodeActionOperatorGte, NodeActionOperatorLt, NodeActionOperatorLte, NodeActionOperatorEq}
|
||||
|
||||
func FindAllNodeActionOperatorDefinitions() []*shared.Definition {
|
||||
return []*shared.Definition{
|
||||
{
|
||||
Code: NodeActionOperatorGt,
|
||||
Name: "大于(>)",
|
||||
},
|
||||
{
|
||||
Code: NodeActionOperatorGte,
|
||||
Name: "大于等于(≥)",
|
||||
},
|
||||
{
|
||||
Code: NodeActionOperatorLt,
|
||||
Name: "小于(<)",
|
||||
},
|
||||
{
|
||||
Code: NodeActionOperatorLte,
|
||||
Name: "小于等于(≤)",
|
||||
},
|
||||
{
|
||||
Code: NodeActionOperatorEq,
|
||||
Name: "等于(=)",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// NodeActionCondConnector 条件之间关系
|
||||
type NodeActionCondConnector = string
|
||||
|
||||
const (
|
||||
NodeActionCondConnectorAnd NodeActionCondConnector = "and"
|
||||
NodeActionCondConnectorOr NodeActionCondConnector = "or"
|
||||
)
|
||||
|
||||
type NodeActionCond struct {
|
||||
Param NodeActionParam `json:"param"` // 参数名
|
||||
Operator NodeActionOperator `json:"operator"` // 操作符
|
||||
Value any `json:"value"` // 对比值
|
||||
}
|
||||
|
||||
func (this *NodeActionCond) Match(value any) bool {
|
||||
var paramDef *NodeActionParamDefinition
|
||||
for _, paramDef2 := range FindAllNodeActionParamDefinitions() {
|
||||
if paramDef2.Code == this.Param {
|
||||
paramDef = paramDef2
|
||||
break
|
||||
}
|
||||
}
|
||||
if paramDef == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
switch paramDef.ValueType {
|
||||
case "bandwidth":
|
||||
if value != nil && !this.isScalar(value) {
|
||||
var value1Map = maps.NewMap(value)
|
||||
value = this.toBandwidthBits(value1Map)
|
||||
}
|
||||
var value2Map = maps.NewMap(this.Value)
|
||||
return this.compare(value, this.toBandwidthBits(value2Map))
|
||||
case "traffic":
|
||||
if value != nil && !this.isScalar(value) {
|
||||
var value1Map = maps.NewMap(value)
|
||||
value = this.toTrafficBytes(value1Map)
|
||||
}
|
||||
var value2Map = maps.NewMap(this.Value)
|
||||
return this.compare(value, this.toTrafficBytes(value2Map))
|
||||
case "cpu":
|
||||
return this.compare(value, this.Value)
|
||||
case "memory":
|
||||
return this.compare(value, this.Value)
|
||||
case "load":
|
||||
return this.compare(value, this.Value)
|
||||
case "rate":
|
||||
return this.compare(value, this.Value)
|
||||
case "":
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (this *NodeActionCond) compare(value1, value2 any) bool {
|
||||
switch this.Operator {
|
||||
case NodeActionOperatorGt:
|
||||
return types.Int64(value1) > types.Int64(value2)
|
||||
case NodeActionOperatorGte:
|
||||
return types.Int64(value1) >= types.Int64(value2)
|
||||
case NodeActionOperatorLt:
|
||||
return types.Int64(value1) < types.Int64(value2)
|
||||
case NodeActionOperatorLte:
|
||||
return types.Int64(value1) <= types.Int64(value2)
|
||||
case NodeActionOperatorEq:
|
||||
return types.Int64(value1) == types.Int64(value2)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (this *NodeActionCond) toBandwidthBits(m maps.Map) int64 {
|
||||
var count = m.GetInt64("count")
|
||||
var unit = m.GetString("unit")
|
||||
if count <= 0 {
|
||||
return 0
|
||||
}
|
||||
switch unit {
|
||||
case "b":
|
||||
return count
|
||||
case "kb":
|
||||
return count << 10
|
||||
case "mb":
|
||||
return count << 20
|
||||
case "gb":
|
||||
return count << 30
|
||||
case "tb":
|
||||
return count << 40
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (this *NodeActionCond) toTrafficBytes(m maps.Map) int64 {
|
||||
var count = m.GetInt64("count")
|
||||
var unit = m.GetString("unit")
|
||||
if count <= 0 {
|
||||
return 0
|
||||
}
|
||||
switch unit {
|
||||
case "b":
|
||||
return count
|
||||
case "kb":
|
||||
return count << 10
|
||||
case "mb":
|
||||
return count << 20
|
||||
case "gb":
|
||||
return count << 30
|
||||
case "tb":
|
||||
return count << 40
|
||||
case "pb":
|
||||
return count << 50
|
||||
case "eb":
|
||||
return count << 60
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (this *NodeActionCond) isScalar(value any) bool {
|
||||
if value == nil {
|
||||
return false
|
||||
}
|
||||
switch value.(type) {
|
||||
case int, int8, int16, int32, int64, uint, uint8, uint16, uint64, float32, float64, string, bool:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type NodeActionCondsConfig struct {
|
||||
Conds []*NodeActionCond `json:"conds"`
|
||||
Connector NodeActionCondConnector `json:"connector"`
|
||||
}
|
||||
|
||||
func NewNodeActionCondsConfig() *NodeActionCondsConfig {
|
||||
return &NodeActionCondsConfig{
|
||||
Connector: NodeActionCondConnectorAnd,
|
||||
}
|
||||
}
|
||||
|
||||
func (this *NodeActionCondsConfig) Match(valueGetter func(param NodeActionParam) (value any, err error)) (bool, error) {
|
||||
if len(this.Conds) == 0 {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
for index, cond := range this.Conds {
|
||||
value, err := valueGetter(cond.Param)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var b = cond.Match(value)
|
||||
if !b {
|
||||
if this.Connector == NodeActionCondConnectorAnd {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// 如果是最后一个OR条件,则直接返回false
|
||||
if index == len(this.Conds)-1 {
|
||||
return false, nil
|
||||
}
|
||||
} else {
|
||||
if this.Connector == NodeActionCondConnectorOr {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// 如果是最后一个AND条件,则直接返回true
|
||||
if index == len(this.Conds)-1 {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// NodeActionCode 动作代号
|
||||
type NodeActionCode = string
|
||||
|
||||
const (
|
||||
NodeActionCodeUp NodeActionCode = "up" // 上线
|
||||
NodeActionCodeDown NodeActionCode = "down" // 下线
|
||||
NodeActionCodeSwitchToBackupNodesInCluster NodeActionCode = "switchToBackupNodesInCluster" // 切换到集群备用节点
|
||||
NodeActionCodeSwitchToBackupNodesInGroup NodeActionCode = "switchToBackupNodesInGroup" // 切换到分组备用节点
|
||||
NodeActionCodeSwitchToBackupIP NodeActionCode = "switchToBackupIP" // 切换到备用IP
|
||||
NodeActionCodeEnableBackupNodesInCluster NodeActionCode = "enableBackupNodesInCluster" // 启用集群备用节点
|
||||
NodeActionCodeEnableBackupNodesInGroup NodeActionCode = "enableBackupNodesInGroup" // 启用分组备用节点
|
||||
NodeActionCodeEnableBackupIP NodeActionCode = "enableBackupIP" // 启用备用IP
|
||||
NodeActionCodeWebHook NodeActionCode = "webHook" // WebHook
|
||||
)
|
||||
|
||||
func FindAllNodeActionDefinitions() []*shared.Definition {
|
||||
return []*shared.Definition{
|
||||
{
|
||||
Code: NodeActionCodeUp,
|
||||
Name: "上线当前节点",
|
||||
Description: "将当前节点状态设置为在线。",
|
||||
},
|
||||
{
|
||||
Code: NodeActionCodeDown,
|
||||
Name: "下线当前节点",
|
||||
Description: "将当前节点状态设置为离线。",
|
||||
},
|
||||
{
|
||||
Code: NodeActionCodeSwitchToBackupNodesInCluster,
|
||||
Name: "切换到集群备用节点",
|
||||
Description: "下线当前节点并启用节点所在集群备用节点。",
|
||||
},
|
||||
{
|
||||
Code: NodeActionCodeSwitchToBackupNodesInGroup,
|
||||
Name: "切换到分组备用节点",
|
||||
Description: "下线当前节点并启用节点所在分组备用节点。",
|
||||
},
|
||||
{
|
||||
Code: NodeActionCodeSwitchToBackupIP,
|
||||
Name: "切换到备用IP",
|
||||
Description: "将当前节点的IP切换到当前节点配置的备用IP。",
|
||||
},
|
||||
|
||||
{
|
||||
Code: NodeActionCodeEnableBackupNodesInCluster,
|
||||
Name: "启用集群备用节点",
|
||||
Description: "保持当前节点并启用节点所在集群备用节点。",
|
||||
},
|
||||
{
|
||||
Code: NodeActionCodeEnableBackupNodesInGroup,
|
||||
Name: "启用分组备用节点",
|
||||
Description: "保持当前节点并启用节点所在分组备用节点。",
|
||||
},
|
||||
{
|
||||
Code: NodeActionCodeEnableBackupIP,
|
||||
Name: "启用备用IP",
|
||||
Description: "保持当前节点的IP并启用当前节点配置的备用IP。",
|
||||
},
|
||||
|
||||
{
|
||||
Code: NodeActionCodeWebHook,
|
||||
Name: "WebHook",
|
||||
Description: "通过WebHook发送通知到URL。",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func FindNodeActionDefinition(code NodeActionCode) *shared.Definition {
|
||||
for _, def := range FindAllNodeActionDefinitions() {
|
||||
if def.Code == code {
|
||||
return def
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func FindNodeActionName(code NodeActionCode) string {
|
||||
var def = FindNodeActionDefinition(code)
|
||||
if def != nil {
|
||||
return def.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// NodeActionConfig 动作配置
|
||||
type NodeActionConfig struct {
|
||||
Code NodeActionCode `json:"code"` // 动作代号
|
||||
Params any `json:"params"` // 动作参数
|
||||
}
|
||||
|
||||
func NewNodeActionConfig() *NodeActionConfig {
|
||||
return &NodeActionConfig{}
|
||||
}
|
||||
|
||||
type NodeActionCodeWebHookParams struct {
|
||||
URL string `json:"url"` // URL路径
|
||||
}
|
||||
|
||||
// NodeActionStatus 动作状态
|
||||
type NodeActionStatus struct {
|
||||
ActionId int64 `json:"actionId"` // 动作ID
|
||||
CreatedAt int64 `json:"createdAt"` // 状态创建时间
|
||||
Conds *NodeActionCondsConfig `json:"conds"` // 动作条件
|
||||
Action *NodeActionConfig `json:"action"` // 动作配置
|
||||
ExpiresAt int64 `json:"expiresAt"` // 过期时间
|
||||
DurationSeconds int64 `json:"durationSeconds"` // 周期秒数
|
||||
}
|
||||
852
EdgeCommon/pkg/nodeconfigs/node_config.go
Normal file
852
EdgeCommon/pkg/nodeconfigs/node_config.go
Normal file
@@ -0,0 +1,852 @@
|
||||
package nodeconfigs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var sharedNodeConfig *NodeConfig = nil
|
||||
var uamPolicyLocker = &sync.RWMutex{}
|
||||
var httpCCPolicyLocker = &sync.RWMutex{}
|
||||
var http3PolicyLocker = &sync.RWMutex{}
|
||||
var httpPagesPolicyLocker = &sync.RWMutex{}
|
||||
var webPPolicyLocker = &sync.RWMutex{}
|
||||
var plansLocker = &sync.RWMutex{}
|
||||
|
||||
type ServerError struct {
|
||||
Id int64
|
||||
Message string
|
||||
}
|
||||
|
||||
func NewServerError(serverId int64, message string) *ServerError {
|
||||
return &ServerError{Id: serverId, Message: message}
|
||||
}
|
||||
|
||||
// NodeConfig 边缘节点配置
|
||||
type NodeConfig struct {
|
||||
Id int64 `yaml:"id" json:"id"`
|
||||
Edition string `yaml:"edition" json:"edition"`
|
||||
NodeId string `yaml:"nodeId" json:"nodeId"`
|
||||
Secret string `yaml:"secret" json:"secret"`
|
||||
IsOn bool `yaml:"isOn" json:"isOn"`
|
||||
Servers []*serverconfigs.ServerConfig `yaml:"servers" json:"servers"`
|
||||
SupportCNAME bool `yaml:"supportCNAME" json:"supportCNAME"`
|
||||
Version int64 `yaml:"version" json:"version"`
|
||||
Name string `yaml:"name" json:"name"`
|
||||
GroupId int64 `yaml:"groupId" json:"groupId"`
|
||||
RegionId int64 `yaml:"regionId" json:"regionId"`
|
||||
OCSPVersion int64 `yaml:"ocspVersion" json:"ocspVersion"`
|
||||
DataMap *shared.DataMap `yaml:"dataMap" json:"dataMap"`
|
||||
UpdatingServerListId int64 `yaml:"updatingServerListId" json:"updatingServerListId"`
|
||||
|
||||
// 性能
|
||||
MaxCPU int32 `yaml:"maxCPU" json:"maxCPU"`
|
||||
APINodeAddrs []*serverconfigs.NetworkAddressConfig `yaml:"apiNodeAddrs" json:"apiNodeAddrs"`
|
||||
|
||||
CacheDiskDir string `yaml:"cacheDiskDir" json:"cacheDiskDir"` // 文件缓存目录
|
||||
MaxCacheDiskCapacity *shared.SizeCapacity `yaml:"maxCacheDiskCapacity" json:"maxCacheDiskCapacity"` // 文件缓存容量
|
||||
|
||||
CacheDiskSubDirs []*serverconfigs.CacheDir `yaml:"cacheDiskSubDirs" json:"cacheDiskSubDirs"` // 其余缓存目录
|
||||
|
||||
MaxCacheMemoryCapacity *shared.SizeCapacity `yaml:"maxCacheMemoryCapacity" json:"maxCacheMemoryCapacity"` // 内容缓存容量
|
||||
MaxThreads int `yaml:"maxThreads" json:"maxThreads"` // 最大线程数
|
||||
DDoSProtection *ddosconfigs.ProtectionConfig `yaml:"ddosProtection" json:"ddosProtection"` // DDoS防护
|
||||
EnableIPLists bool `yaml:"enableIPLists" json:"enableIPLists"` // 启用IP名单
|
||||
|
||||
// 级别
|
||||
Level int32 `yaml:"level" json:"level"`
|
||||
ParentNodes map[int64][]*ParentNodeConfig `yaml:"parentNodes" json:"parentNodes"` // clusterId => []*ParentNodeConfig
|
||||
|
||||
// 全局配置
|
||||
GlobalServerConfig *serverconfigs.GlobalServerConfig `yaml:"globalServerConfig" json:"globalServerConfig"` // 服务全局配置,用来替代 GlobalConfig
|
||||
ProductConfig *ProductConfig `yaml:"productConfig" json:"productConfig"`
|
||||
|
||||
// 集群统一配置
|
||||
HTTPFirewallPolicies []*firewallconfigs.HTTPFirewallPolicy `yaml:"httpFirewallPolicies" json:"httpFirewallPolicies"`
|
||||
HTTPCachePolicies []*serverconfigs.HTTPCachePolicy `yaml:"httpCachePolicies" json:"httpCachePolicies"`
|
||||
TOA *TOAConfig `yaml:"toa" json:"toa"`
|
||||
SystemServices map[string]maps.Map `yaml:"systemServices" json:"systemServices"` // 系统服务配置 type => params
|
||||
FirewallActions []*firewallconfigs.FirewallActionConfig `yaml:"firewallActions" json:"firewallActions"` // 防火墙动作
|
||||
TimeZone string `yaml:"timeZone" json:"timeZone"` // 自动设置时区
|
||||
AutoOpenPorts bool `yaml:"autoOpenPorts" json:"autoOpenPorts"` // 自动开放所需端口
|
||||
Clock *ClockConfig `yaml:"clock" json:"clock"` // 时钟配置
|
||||
AutoInstallNftables bool `yaml:"autoInstallNftables" json:"autoInstallNftables"` // 自动安装nftables
|
||||
AutoSystemTuning bool `yaml:"autoSystemTuning" json:"autoSystemTuning"` // 自动调整系统参数
|
||||
AutoTrimDisks bool `yaml:"autoTrimDisks" json:"autoTrimDisks"` // 自动执行TRIM
|
||||
MaxConcurrentReads int `yaml:"maxConcurrentReads" json:"maxConcurrentReads"` // 最大并发读
|
||||
MaxConcurrentWrites int `yaml:"maxConcurrentWrites" json:"maxConcurrentWrites"` // 最大并发写
|
||||
|
||||
// 指标
|
||||
MetricItems []*serverconfigs.MetricItemConfig `yaml:"metricItems" json:"metricItems"`
|
||||
|
||||
IPAddresses []string `yaml:"ipAddresses" json:"ipAddresses"` // IP地址
|
||||
AllowedIPs []string `yaml:"allowedIPs" json:"allowedIPs"` // 自动IP白名单
|
||||
|
||||
// 脚本
|
||||
CommonScripts []*serverconfigs.CommonScript `yaml:"commonScripts" json:"commonScripts"`
|
||||
|
||||
WebPImagePolicies map[int64]*WebPImagePolicy `yaml:"webpImagePolicies" json:"webpImagePolicies"` // WebP相关配置,clusterId => *WebPImagePolicy
|
||||
UAMPolicies map[int64]*UAMPolicy `yaml:"uamPolicies" json:"uamPolicies"` // UAM相关配置,clusterId => *UAMPolicy
|
||||
HTTPCCPolicies map[int64]*HTTPCCPolicy `yaml:"httpCCPolicies" json:"httpCCPolicies"` // CC相关配置, clusterId => *HTTPCCPolicy
|
||||
HTTP3Policies map[int64]*HTTP3Policy `yaml:"http3Policies" json:"http3Policies"` // HTTP3相关配置, clusterId => *HTTP3Policy
|
||||
HTTPPagesPolicies map[int64]*HTTPPagesPolicy `yaml:"httpPagesPolicies" json:"httpPagesPolicies"` // 自定义页面,clusterId => *HTTPPagesPolicy
|
||||
NetworkSecurityPolicy *NetworkSecurityPolicy `yaml:"networkSecurityPolicy" json:"networkSecurityPolicy"` // 网络安全策略
|
||||
Plans map[int64]*serverconfigs.PlanConfig `yaml:"plans" json:"plans"` // 套餐 plan id => *serverconfigs.PlanConfig
|
||||
|
||||
// DNS
|
||||
DNSResolver *DNSResolverConfig `yaml:"dnsResolver" json:"dnsResolver"`
|
||||
|
||||
// Cluster
|
||||
ClusterSecret string `yaml:"clusterSecret" json:"clusterSecret"`
|
||||
|
||||
paddedId string
|
||||
|
||||
// firewall
|
||||
firewallPolicies []*firewallconfigs.HTTPFirewallPolicy
|
||||
|
||||
// metrics
|
||||
hasHTTPConnectionMetrics bool
|
||||
|
||||
// 源站集合
|
||||
originMap map[int64]*serverconfigs.OriginConfig
|
||||
|
||||
// 自动白名单
|
||||
allowedIPMap map[string]bool
|
||||
|
||||
// syn flood
|
||||
synFlood *firewallconfigs.SYNFloodConfig
|
||||
|
||||
secretHash string
|
||||
}
|
||||
|
||||
// SharedNodeConfig 取得当前节点配置单例
|
||||
func SharedNodeConfig() (*NodeConfig, error) {
|
||||
shared.Locker.Lock()
|
||||
defer shared.Locker.Unlock()
|
||||
|
||||
if sharedNodeConfig != nil {
|
||||
return sharedNodeConfig, nil
|
||||
}
|
||||
|
||||
// 从本地缓存读取
|
||||
var configFile = Tea.ConfigFile("node.json")
|
||||
var readCacheOk = false
|
||||
defer func() {
|
||||
if !readCacheOk {
|
||||
_ = os.Remove(configFile)
|
||||
}
|
||||
}()
|
||||
|
||||
data, err := os.ReadFile(configFile)
|
||||
if err != nil {
|
||||
return &NodeConfig{}, err
|
||||
}
|
||||
|
||||
encodedNodeInfo, encodedJSONData, found := bytes.Cut(data, []byte("\n"))
|
||||
if !found {
|
||||
// 删除缓存文件
|
||||
return &NodeConfig{}, errors.New("node.json: invalid data format")
|
||||
}
|
||||
|
||||
encodedNodeInfoData, err := base64.StdEncoding.DecodeString(string(encodedNodeInfo))
|
||||
if err != nil {
|
||||
// 删除缓存文件
|
||||
return &NodeConfig{}, err
|
||||
}
|
||||
|
||||
nodeUniqueId, nodeSecret, found := strings.Cut(string(encodedNodeInfoData), "|")
|
||||
if !found {
|
||||
// 删除缓存文件
|
||||
return &NodeConfig{}, errors.New("node.json: node info: invalid data format")
|
||||
}
|
||||
|
||||
jsonData, err := nodeutils.DecryptData(nodeUniqueId, nodeSecret, string(encodedJSONData))
|
||||
if err != nil {
|
||||
return &NodeConfig{}, err
|
||||
}
|
||||
|
||||
var config = &NodeConfig{}
|
||||
err = json.Unmarshal(jsonData, &config)
|
||||
if err != nil {
|
||||
return &NodeConfig{}, err
|
||||
}
|
||||
|
||||
readCacheOk = true
|
||||
sharedNodeConfig = config
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// ResetNodeConfig 重置节点配置
|
||||
func ResetNodeConfig(nodeConfig *NodeConfig) {
|
||||
shared.Locker.Lock()
|
||||
sharedNodeConfig = nodeConfig
|
||||
shared.Locker.Unlock()
|
||||
}
|
||||
|
||||
// CloneNodeConfig 复制节点配置
|
||||
func CloneNodeConfig(nodeConfig *NodeConfig) (*NodeConfig, error) {
|
||||
if nodeConfig == nil {
|
||||
return nil, errors.New("node config should not be nil")
|
||||
}
|
||||
|
||||
uamPolicyLocker.RLock()
|
||||
defer uamPolicyLocker.RUnlock()
|
||||
|
||||
httpCCPolicyLocker.RLock()
|
||||
defer httpCCPolicyLocker.RUnlock()
|
||||
|
||||
http3PolicyLocker.RLock()
|
||||
defer http3PolicyLocker.RUnlock()
|
||||
|
||||
httpPagesPolicyLocker.RLock()
|
||||
defer httpPagesPolicyLocker.RUnlock()
|
||||
|
||||
webPPolicyLocker.RLock()
|
||||
defer webPPolicyLocker.RUnlock()
|
||||
|
||||
plansLocker.RLock()
|
||||
defer plansLocker.RUnlock()
|
||||
|
||||
var newConfigValue = reflect.Indirect(reflect.ValueOf(&NodeConfig{}))
|
||||
var oldValue = reflect.Indirect(reflect.ValueOf(nodeConfig))
|
||||
var valueType = oldValue.Type()
|
||||
for i := 0; i < valueType.NumField(); i++ {
|
||||
var field = valueType.Field(i)
|
||||
var fieldName = field.Name
|
||||
if !field.IsExported() {
|
||||
continue
|
||||
}
|
||||
if fieldName == "Servers" {
|
||||
continue
|
||||
}
|
||||
|
||||
newConfigValue.FieldByName(fieldName).Set(oldValue.FieldByName(fieldName))
|
||||
}
|
||||
|
||||
var newConfig = newConfigValue.Interface().(NodeConfig)
|
||||
newConfig.Servers = append([]*serverconfigs.ServerConfig{}, nodeConfig.Servers...)
|
||||
return &newConfig, nil
|
||||
}
|
||||
|
||||
// Init 初始化
|
||||
func (this *NodeConfig) Init(ctx context.Context) (err error, serverErrors []*ServerError) {
|
||||
// 设置Context
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
}
|
||||
ctx = context.WithValue(ctx, "DataMap", this.DataMap)
|
||||
|
||||
this.secretHash = fmt.Sprintf("%x", sha256.Sum256([]byte(this.NodeId+"@"+this.Secret)))
|
||||
this.paddedId = fmt.Sprintf("%08d", this.Id)
|
||||
|
||||
// servers
|
||||
for _, server := range this.Servers {
|
||||
// 避免在运行时重新初始化
|
||||
if server.IsInitialized() {
|
||||
continue
|
||||
}
|
||||
|
||||
// 初始化
|
||||
errs := server.Init(ctx)
|
||||
if len(errs) > 0 {
|
||||
// 这里不返回错误,而是继续往下,防止单个服务错误而影响其他服务
|
||||
for _, serverErr := range errs {
|
||||
serverErrors = append(serverErrors, NewServerError(server.Id, "server '"+strconv.FormatInt(server.Id, 10)+"' init failed: "+serverErr.Error()))
|
||||
}
|
||||
}
|
||||
|
||||
// 检查ACME支持
|
||||
if server.IsOn && server.SupportCNAME {
|
||||
this.SupportCNAME = true
|
||||
}
|
||||
}
|
||||
|
||||
// cache policy
|
||||
if len(this.HTTPCachePolicies) > 0 {
|
||||
for _, policy := range this.HTTPCachePolicies {
|
||||
err = policy.Init()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// firewall policy
|
||||
if len(this.HTTPFirewallPolicies) > 0 {
|
||||
for _, policy := range this.HTTPFirewallPolicies {
|
||||
err = policy.Init()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TOA
|
||||
if this.TOA != nil {
|
||||
err = this.TOA.Init()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 源站
|
||||
this.originMap = map[int64]*serverconfigs.OriginConfig{}
|
||||
|
||||
// 查找FirewallPolicy
|
||||
this.synFlood = nil
|
||||
this.firewallPolicies = []*firewallconfigs.HTTPFirewallPolicy{}
|
||||
for _, policy := range this.HTTPFirewallPolicies {
|
||||
if policy.IsOn {
|
||||
this.firewallPolicies = append(this.firewallPolicies, policy)
|
||||
if policy.SYNFlood != nil && policy.SYNFlood.IsOn {
|
||||
this.synFlood = policy.SYNFlood
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, server := range this.Servers {
|
||||
if !server.IsOk() || !server.IsOn {
|
||||
continue
|
||||
}
|
||||
|
||||
// WAF策略
|
||||
if server.HTTPFirewallPolicyId > 0 {
|
||||
for _, policy := range this.HTTPFirewallPolicies {
|
||||
if server.HTTPFirewallPolicyId == policy.Id {
|
||||
server.HTTPFirewallPolicy = policy
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 缓存策略
|
||||
if server.HTTPCachePolicyId > 0 {
|
||||
for _, policy := range this.HTTPCachePolicies {
|
||||
if server.HTTPCachePolicyId == policy.Id {
|
||||
server.HTTPCachePolicy = policy
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 源站
|
||||
if server.ReverseProxyRef != nil && server.ReverseProxyRef.IsOn && server.ReverseProxy != nil && server.ReverseProxy.IsOn {
|
||||
for _, origin := range server.ReverseProxy.PrimaryOrigins {
|
||||
if origin.IsOn {
|
||||
this.originMap[origin.Id] = origin
|
||||
}
|
||||
}
|
||||
for _, origin := range server.ReverseProxy.BackupOrigins {
|
||||
if origin.IsOn {
|
||||
this.originMap[origin.Id] = origin
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if server.Web != nil {
|
||||
this.lookupWeb(server, server.Web)
|
||||
}
|
||||
}
|
||||
|
||||
// firewall actions
|
||||
for _, action := range this.FirewallActions {
|
||||
err = action.Init()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// metric items
|
||||
this.hasHTTPConnectionMetrics = false
|
||||
for _, item := range this.MetricItems {
|
||||
err = item.Init()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if item.IsOn && item.HasHTTPConnectionValue() {
|
||||
this.hasHTTPConnectionMetrics = true
|
||||
}
|
||||
}
|
||||
|
||||
// 自动白名单
|
||||
this.allowedIPMap = map[string]bool{}
|
||||
for _, allowIP := range this.AllowedIPs {
|
||||
this.allowedIPMap[allowIP] = true
|
||||
}
|
||||
|
||||
// webp image policy
|
||||
webPPolicyLocker.RLock()
|
||||
if this.WebPImagePolicies != nil {
|
||||
for _, policy := range this.WebPImagePolicies {
|
||||
err = policy.Init()
|
||||
if err != nil {
|
||||
webPPolicyLocker.RUnlock()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
webPPolicyLocker.RUnlock()
|
||||
|
||||
// uam policy
|
||||
uamPolicyLocker.RLock()
|
||||
if len(this.UAMPolicies) > 0 {
|
||||
for _, policy := range this.UAMPolicies {
|
||||
err = policy.Init()
|
||||
if err != nil {
|
||||
uamPolicyLocker.RUnlock()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
uamPolicyLocker.RUnlock()
|
||||
|
||||
// http cc policy
|
||||
httpCCPolicyLocker.RLock()
|
||||
if len(this.HTTPCCPolicies) > 0 {
|
||||
for _, policy := range this.HTTPCCPolicies {
|
||||
err = policy.Init()
|
||||
if err != nil {
|
||||
httpCCPolicyLocker.RUnlock()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
httpCCPolicyLocker.RUnlock()
|
||||
|
||||
// http3 policy
|
||||
http3PolicyLocker.RLock()
|
||||
if len(this.HTTP3Policies) > 0 {
|
||||
for _, policy := range this.HTTP3Policies {
|
||||
err = policy.Init()
|
||||
if err != nil {
|
||||
http3PolicyLocker.RUnlock()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
http3PolicyLocker.RUnlock()
|
||||
|
||||
// http pages policy
|
||||
httpPagesPolicyLocker.RLock()
|
||||
if len(this.HTTPPagesPolicies) > 0 {
|
||||
for _, policy := range this.HTTPPagesPolicies {
|
||||
err = policy.Init()
|
||||
if err != nil {
|
||||
httpPagesPolicyLocker.RUnlock()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
httpPagesPolicyLocker.RUnlock()
|
||||
|
||||
// plans
|
||||
plansLocker.RLock()
|
||||
if len(this.Plans) > 0 {
|
||||
for _, plan := range this.Plans {
|
||||
err = plan.Init()
|
||||
if err != nil {
|
||||
plansLocker.RUnlock()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
plansLocker.RUnlock()
|
||||
|
||||
// dns resolver
|
||||
if this.DNSResolver != nil {
|
||||
err = this.DNSResolver.Init()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 全局服务设置
|
||||
if this.GlobalServerConfig != nil {
|
||||
err = this.GlobalServerConfig.Init()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// api node addrs
|
||||
if len(this.APINodeAddrs) > 0 {
|
||||
for _, addr := range this.APINodeAddrs {
|
||||
err = addr.Init()
|
||||
if err != nil {
|
||||
return err, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// network security policy
|
||||
if this.NetworkSecurityPolicy != nil {
|
||||
err = this.NetworkSecurityPolicy.Init()
|
||||
if err != nil {
|
||||
return err, nil
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// AddServer 添加服务
|
||||
func (this *NodeConfig) AddServer(server *serverconfigs.ServerConfig) {
|
||||
if server == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var found = false
|
||||
for index, oldServer := range this.Servers {
|
||||
if oldServer.Id == server.Id {
|
||||
this.Servers[index] = server
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
this.Servers = append(this.Servers, server)
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveServer 删除服务
|
||||
func (this *NodeConfig) RemoveServer(serverId int64) {
|
||||
for index, oldServer := range this.Servers {
|
||||
if oldServer.Id == serverId {
|
||||
this.Servers = append(this.Servers[:index], this.Servers[index+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// AvailableGroups 根据网络地址和协议分组
|
||||
func (this *NodeConfig) AvailableGroups() []*serverconfigs.ServerAddressGroup {
|
||||
var groupMapping = map[string]*serverconfigs.ServerAddressGroup{} // protocol://addr => Server Group
|
||||
for _, server := range this.Servers {
|
||||
if !server.IsOk() || !server.IsOn {
|
||||
continue
|
||||
}
|
||||
for _, addr := range server.FullAddresses() {
|
||||
group, ok := groupMapping[addr]
|
||||
if ok {
|
||||
group.Add(server)
|
||||
} else {
|
||||
group = serverconfigs.NewServerAddressGroup(addr)
|
||||
group.Add(server)
|
||||
}
|
||||
groupMapping[addr] = group
|
||||
}
|
||||
}
|
||||
var result = []*serverconfigs.ServerAddressGroup{}
|
||||
for _, group := range groupMapping {
|
||||
result = append(result, group)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// HTTP3Group HTTP/3网站分组
|
||||
// 这里暂时不区分集群
|
||||
func (this *NodeConfig) HTTP3Group() *serverconfigs.ServerAddressGroup {
|
||||
var group = serverconfigs.NewServerAddressGroup("HTTP3")
|
||||
for _, server := range this.Servers {
|
||||
if !server.SupportsHTTP3() {
|
||||
continue
|
||||
}
|
||||
group.Add(server)
|
||||
}
|
||||
return group
|
||||
}
|
||||
|
||||
// FindAllFirewallPolicies 获取所有的防火墙策略
|
||||
func (this *NodeConfig) FindAllFirewallPolicies() []*firewallconfigs.HTTPFirewallPolicy {
|
||||
return this.firewallPolicies
|
||||
}
|
||||
|
||||
// Save 写入到文件
|
||||
func (this *NodeConfig) Save() error {
|
||||
shared.Locker.Lock()
|
||||
defer shared.Locker.Unlock()
|
||||
|
||||
data, err := json.Marshal(this)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var headerData = []byte(base64.StdEncoding.EncodeToString([]byte(this.NodeId+"|"+this.Secret)) + "\n")
|
||||
|
||||
encodedData, err := nodeutils.EncryptData(this.NodeId, this.Secret, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return os.WriteFile(Tea.ConfigFile("node.json"), append(headerData, encodedData...), 0777)
|
||||
}
|
||||
|
||||
// PaddedId 获取填充后的ID
|
||||
func (this *NodeConfig) PaddedId() string {
|
||||
return this.paddedId
|
||||
}
|
||||
|
||||
// HasHTTPConnectionMetrics 是否含有HTTP连接数的指标
|
||||
func (this *NodeConfig) HasHTTPConnectionMetrics() bool {
|
||||
return this.hasHTTPConnectionMetrics
|
||||
}
|
||||
|
||||
// FindOrigin 读取源站配置
|
||||
func (this *NodeConfig) FindOrigin(originId int64) *serverconfigs.OriginConfig {
|
||||
if this.originMap == nil {
|
||||
return nil
|
||||
}
|
||||
config, ok := this.originMap[originId]
|
||||
if ok {
|
||||
return config
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 搜索WAF策略
|
||||
func (this *NodeConfig) lookupWeb(server *serverconfigs.ServerConfig, web *serverconfigs.HTTPWebConfig) {
|
||||
if web == nil || !web.IsOn {
|
||||
return
|
||||
}
|
||||
if web.FirewallPolicy != nil && web.FirewallPolicy.IsOn {
|
||||
// 复用节点的选项设置
|
||||
if server.HTTPFirewallPolicy != nil {
|
||||
if (web.FirewallPolicy.BlockOptions == nil || !web.FirewallPolicy.BlockOptions.IsPrior) && server.HTTPFirewallPolicy.BlockOptions != nil {
|
||||
web.FirewallPolicy.BlockOptions = server.HTTPFirewallPolicy.BlockOptions
|
||||
}
|
||||
if (web.FirewallPolicy.PageOptions == nil || !web.FirewallPolicy.PageOptions.IsPrior) && server.HTTPFirewallPolicy.PageOptions != nil {
|
||||
web.FirewallPolicy.PageOptions = server.HTTPFirewallPolicy.PageOptions
|
||||
}
|
||||
if (web.FirewallPolicy.CaptchaOptions == nil || !web.FirewallPolicy.CaptchaOptions.IsPrior) && server.HTTPFirewallPolicy.CaptchaOptions != nil {
|
||||
web.FirewallPolicy.CaptchaOptions = server.HTTPFirewallPolicy.CaptchaOptions
|
||||
}
|
||||
if (web.FirewallPolicy.Get302Options == nil || !web.FirewallPolicy.Get302Options.IsPrior) && server.HTTPFirewallPolicy.Get302Options != nil {
|
||||
web.FirewallPolicy.Get302Options = server.HTTPFirewallPolicy.Get302Options
|
||||
}
|
||||
if (web.FirewallPolicy.Post307Options == nil || !web.FirewallPolicy.Post307Options.IsPrior) && server.HTTPFirewallPolicy.Post307Options != nil {
|
||||
web.FirewallPolicy.Post307Options = server.HTTPFirewallPolicy.Post307Options
|
||||
}
|
||||
if (web.FirewallPolicy.JSCookieOptions == nil || !web.FirewallPolicy.JSCookieOptions.IsPrior) && server.HTTPFirewallPolicy.JSCookieOptions != nil {
|
||||
web.FirewallPolicy.JSCookieOptions = server.HTTPFirewallPolicy.JSCookieOptions
|
||||
}
|
||||
if (web.FirewallPolicy.SYNFlood == nil || !web.FirewallPolicy.SYNFlood.IsPrior) && server.HTTPFirewallPolicy.SYNFlood != nil {
|
||||
web.FirewallPolicy.SYNFlood = server.HTTPFirewallPolicy.SYNFlood
|
||||
}
|
||||
if (web.FirewallPolicy.Log == nil || !web.FirewallPolicy.Log.IsPrior) && server.HTTPFirewallPolicy.Log != nil {
|
||||
web.FirewallPolicy.Log = server.HTTPFirewallPolicy.Log
|
||||
}
|
||||
|
||||
web.FirewallPolicy.Mode = server.HTTPFirewallPolicy.Mode
|
||||
web.FirewallPolicy.UseLocalFirewall = server.HTTPFirewallPolicy.UseLocalFirewall
|
||||
}
|
||||
|
||||
this.firewallPolicies = append(this.firewallPolicies, web.FirewallPolicy)
|
||||
}
|
||||
if len(web.Locations) > 0 {
|
||||
for _, location := range web.Locations {
|
||||
// 源站
|
||||
if location.IsOn && location.ReverseProxyRef != nil && location.ReverseProxyRef.IsOn && location.ReverseProxy != nil && location.ReverseProxy.IsOn {
|
||||
for _, origin := range location.ReverseProxy.PrimaryOrigins {
|
||||
if origin.IsOn {
|
||||
this.originMap[origin.Id] = origin
|
||||
}
|
||||
}
|
||||
for _, origin := range location.ReverseProxy.BackupOrigins {
|
||||
if origin.IsOn {
|
||||
this.originMap[origin.Id] = origin
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Web
|
||||
if location.Web != nil && location.Web.IsOn {
|
||||
this.lookupWeb(server, location.Web)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IPIsAutoAllowed 检查是否自动允许某个IP
|
||||
func (this *NodeConfig) IPIsAutoAllowed(ip string) bool {
|
||||
_, ok := this.allowedIPMap[ip]
|
||||
return ok
|
||||
}
|
||||
|
||||
// SYNFloodConfig 获取SYN Flood配置
|
||||
func (this *NodeConfig) SYNFloodConfig() *firewallconfigs.SYNFloodConfig {
|
||||
return this.synFlood
|
||||
}
|
||||
|
||||
// UpdateCertOCSP 修改证书OCSP
|
||||
func (this *NodeConfig) UpdateCertOCSP(certId int64, ocsp []byte, expiresAt int64) {
|
||||
shared.Locker.Lock()
|
||||
defer shared.Locker.Unlock()
|
||||
|
||||
var servers = this.Servers
|
||||
for _, server := range servers {
|
||||
if server.HTTPS != nil &&
|
||||
server.HTTPS.SSLPolicy != nil &&
|
||||
server.HTTPS.SSLPolicy.OCSPIsOn &&
|
||||
server.HTTPS.SSLPolicy.ContainsCert(certId) {
|
||||
server.HTTPS.SSLPolicy.UpdateCertOCSP(certId, ocsp, expiresAt)
|
||||
}
|
||||
|
||||
if server.TLS != nil &&
|
||||
server.TLS.SSLPolicy != nil &&
|
||||
server.TLS.SSLPolicy.OCSPIsOn &&
|
||||
server.TLS.SSLPolicy.ContainsCert(certId) {
|
||||
server.TLS.SSLPolicy.UpdateCertOCSP(certId, ocsp, expiresAt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FindWebPImagePolicyWithClusterId 使用集群ID查找WebP策略
|
||||
func (this *NodeConfig) FindWebPImagePolicyWithClusterId(clusterId int64) *WebPImagePolicy {
|
||||
webPPolicyLocker.RLock()
|
||||
defer webPPolicyLocker.RUnlock()
|
||||
|
||||
if this.WebPImagePolicies == nil {
|
||||
return nil
|
||||
}
|
||||
return this.WebPImagePolicies[clusterId]
|
||||
}
|
||||
|
||||
// UpdateWebPImagePolicies 修改集群WebP策略
|
||||
func (this *NodeConfig) UpdateWebPImagePolicies(policies map[int64]*WebPImagePolicy) {
|
||||
webPPolicyLocker.Lock()
|
||||
defer webPPolicyLocker.Unlock()
|
||||
this.WebPImagePolicies = policies
|
||||
}
|
||||
|
||||
// FindUAMPolicyWithClusterId 使用集群ID查找UAM策略
|
||||
func (this *NodeConfig) FindUAMPolicyWithClusterId(clusterId int64) *UAMPolicy {
|
||||
uamPolicyLocker.RLock()
|
||||
defer uamPolicyLocker.RUnlock()
|
||||
if this.UAMPolicies == nil {
|
||||
return nil
|
||||
}
|
||||
return this.UAMPolicies[clusterId]
|
||||
}
|
||||
|
||||
// UpdateUAMPolicies 修改集群UAM策略
|
||||
func (this *NodeConfig) UpdateUAMPolicies(policies map[int64]*UAMPolicy) {
|
||||
uamPolicyLocker.Lock()
|
||||
defer uamPolicyLocker.Unlock()
|
||||
this.UAMPolicies = policies
|
||||
}
|
||||
|
||||
// FindHTTPCCPolicyWithClusterId 使用集群ID查找CC策略
|
||||
func (this *NodeConfig) FindHTTPCCPolicyWithClusterId(clusterId int64) *HTTPCCPolicy {
|
||||
httpCCPolicyLocker.RLock()
|
||||
defer httpCCPolicyLocker.RUnlock()
|
||||
if this.HTTPCCPolicies == nil {
|
||||
return nil
|
||||
}
|
||||
return this.HTTPCCPolicies[clusterId]
|
||||
}
|
||||
|
||||
// UpdateHTTPCCPolicies 修改集群CC策略
|
||||
func (this *NodeConfig) UpdateHTTPCCPolicies(policies map[int64]*HTTPCCPolicy) {
|
||||
httpCCPolicyLocker.Lock()
|
||||
defer httpCCPolicyLocker.Unlock()
|
||||
this.HTTPCCPolicies = policies
|
||||
}
|
||||
|
||||
// FindHTTP3PolicyWithClusterId 使用集群ID查找HTTP/3策略
|
||||
func (this *NodeConfig) FindHTTP3PolicyWithClusterId(clusterId int64) *HTTP3Policy {
|
||||
http3PolicyLocker.RLock()
|
||||
defer http3PolicyLocker.RUnlock()
|
||||
if this.HTTP3Policies == nil {
|
||||
return nil
|
||||
}
|
||||
return this.HTTP3Policies[clusterId]
|
||||
}
|
||||
|
||||
// FindHTTP3Ports 查询HTTP/3所有端口
|
||||
func (this *NodeConfig) FindHTTP3Ports() (ports []int) {
|
||||
http3PolicyLocker.RLock()
|
||||
defer http3PolicyLocker.RUnlock()
|
||||
for _, policy := range this.HTTP3Policies {
|
||||
if !policy.IsOn {
|
||||
continue
|
||||
}
|
||||
if policy.Port <= 0 {
|
||||
policy.Port = DefaultHTTP3Port
|
||||
}
|
||||
if !lists.ContainsInt(ports, policy.Port) {
|
||||
ports = append(ports, policy.Port)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateHTTP3Policies 修改集群HTTP/3策略
|
||||
func (this *NodeConfig) UpdateHTTP3Policies(policies map[int64]*HTTP3Policy) {
|
||||
http3PolicyLocker.Lock()
|
||||
defer http3PolicyLocker.Unlock()
|
||||
this.HTTP3Policies = policies
|
||||
}
|
||||
|
||||
// UpdateHTTPPagesPolicies 修改集群自定义页面策略
|
||||
func (this *NodeConfig) UpdateHTTPPagesPolicies(policies map[int64]*HTTPPagesPolicy) {
|
||||
httpPagesPolicyLocker.Lock()
|
||||
defer httpPagesPolicyLocker.Unlock()
|
||||
this.HTTPPagesPolicies = policies
|
||||
}
|
||||
|
||||
// FindHTTPPagesPolicyWithClusterId 使用集群ID查找自定义页面策略
|
||||
func (this *NodeConfig) FindHTTPPagesPolicyWithClusterId(clusterId int64) *HTTPPagesPolicy {
|
||||
httpPagesPolicyLocker.RLock()
|
||||
defer httpPagesPolicyLocker.RUnlock()
|
||||
if this.HTTPPagesPolicies == nil {
|
||||
return nil
|
||||
}
|
||||
return this.HTTPPagesPolicies[clusterId]
|
||||
}
|
||||
|
||||
// UpdatePlans 更新套餐
|
||||
func (this *NodeConfig) UpdatePlans(planMap map[int64]*serverconfigs.PlanConfig) {
|
||||
plansLocker.Lock()
|
||||
this.Plans = planMap
|
||||
plansLocker.Unlock()
|
||||
}
|
||||
|
||||
// FindAllPlans 查找所有套餐
|
||||
func (this *NodeConfig) FindAllPlans() map[int64]*serverconfigs.PlanConfig {
|
||||
plansLocker.RLock()
|
||||
defer plansLocker.RUnlock()
|
||||
return this.Plans
|
||||
}
|
||||
|
||||
// 查找单个套餐
|
||||
func (this *NodeConfig) FindPlan(planId int64) *serverconfigs.PlanConfig {
|
||||
plansLocker.RLock()
|
||||
defer plansLocker.RUnlock()
|
||||
return this.Plans[planId]
|
||||
}
|
||||
|
||||
// SecretHash 对Id和Secret的Hash计算
|
||||
func (this *NodeConfig) SecretHash() string {
|
||||
return this.secretHash
|
||||
}
|
||||
|
||||
// HasConnTimeoutSettings 检查是否有连接超时设置
|
||||
func (this *NodeConfig) HasConnTimeoutSettings() bool {
|
||||
return this.GlobalServerConfig != nil && (this.GlobalServerConfig.Performance.AutoReadTimeout || this.GlobalServerConfig.Performance.AutoWriteTimeout)
|
||||
}
|
||||
120
EdgeCommon/pkg/nodeconfigs/node_config_test.go
Normal file
120
EdgeCommon/pkg/nodeconfigs/node_config_test.go
Normal file
@@ -0,0 +1,120 @@
|
||||
package nodeconfigs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestSharedNodeConfig(t *testing.T) {
|
||||
{
|
||||
config, err := SharedNodeConfig()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(config)
|
||||
}
|
||||
|
||||
// read from memory cache
|
||||
{
|
||||
config, err := SharedNodeConfig()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(config)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNodeConfig_Groups(t *testing.T) {
|
||||
config := &NodeConfig{}
|
||||
config.Servers = []*serverconfigs.ServerConfig{
|
||||
{
|
||||
IsOn: true,
|
||||
HTTP: &serverconfigs.HTTPProtocolConfig{
|
||||
BaseProtocol: serverconfigs.BaseProtocol{
|
||||
IsOn: true,
|
||||
Listen: []*serverconfigs.NetworkAddressConfig{
|
||||
{
|
||||
Protocol: serverconfigs.ProtocolHTTP,
|
||||
Host: "127.0.0.1",
|
||||
PortRange: "1234",
|
||||
},
|
||||
{
|
||||
Protocol: serverconfigs.ProtocolHTTP,
|
||||
PortRange: "8080",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
HTTP: &serverconfigs.HTTPProtocolConfig{
|
||||
BaseProtocol: serverconfigs.BaseProtocol{
|
||||
IsOn: true,
|
||||
Listen: []*serverconfigs.NetworkAddressConfig{
|
||||
{
|
||||
Protocol: serverconfigs.ProtocolHTTP,
|
||||
PortRange: "8080",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
logs.PrintAsJSON(config.AvailableGroups(), t)
|
||||
}
|
||||
|
||||
func TestCloneNodeConfig(t *testing.T) {
|
||||
var config = &NodeConfig{Id: 1, NodeId: "1", IsOn: true}
|
||||
for i := 0; i < 100_000; i++ {
|
||||
config.Servers = append(config.Servers, &serverconfigs.ServerConfig{})
|
||||
}
|
||||
var before = time.Now()
|
||||
newConfig, err := CloneNodeConfig(config)
|
||||
t.Log(time.Since(before))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
newConfig.Servers = []*serverconfigs.ServerConfig{}
|
||||
logs.PrintAsJSON(newConfig, t)
|
||||
}
|
||||
|
||||
func TestNodeConfig_AddServer(t *testing.T) {
|
||||
var config = &NodeConfig{Id: 1, NodeId: "1", IsOn: true}
|
||||
config.AddServer(&serverconfigs.ServerConfig{Id: 1})
|
||||
config.AddServer(&serverconfigs.ServerConfig{Id: 2})
|
||||
|
||||
t.Log("===before===")
|
||||
for _, s := range config.Servers {
|
||||
t.Log(s.Id)
|
||||
}
|
||||
|
||||
t.Log("===after===")
|
||||
config.AddServer(&serverconfigs.ServerConfig{Id: 3})
|
||||
config.RemoveServer(2)
|
||||
for _, s := range config.Servers {
|
||||
t.Log(s.Id)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCloneNodeConfig_UAMPolicies(t *testing.T) {
|
||||
var config = &NodeConfig{}
|
||||
config.UAMPolicies = map[int64]*UAMPolicy{}
|
||||
t.Logf("%p", config.UAMPolicies)
|
||||
|
||||
clonedConfig, err := CloneNodeConfig(config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Logf("%p", clonedConfig.UAMPolicies)
|
||||
}
|
||||
|
||||
func BenchmarkNodeConfig(b *testing.B) {
|
||||
var config = &NodeConfig{}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, _ = CloneNodeConfig(config)
|
||||
}
|
||||
}
|
||||
12
EdgeCommon/pkg/nodeconfigs/node_ip_addr.go
Normal file
12
EdgeCommon/pkg/nodeconfigs/node_ip_addr.go
Normal file
@@ -0,0 +1,12 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package nodeconfigs
|
||||
|
||||
type NodeIPAddr struct {
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
IP string `json:"ip"`
|
||||
IsOn bool `json:"isOn"`
|
||||
IsUp bool `json:"isUp"`
|
||||
CanAccess bool `json:"canAccess"`
|
||||
}
|
||||
37
EdgeCommon/pkg/nodeconfigs/node_levels.go
Normal file
37
EdgeCommon/pkg/nodeconfigs/node_levels.go
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package nodeconfigs
|
||||
|
||||
type NodeLevel struct {
|
||||
Name string `yaml:"name" json:"name"`
|
||||
Code int `yaml:"code" json:"code"`
|
||||
Description string `yaml:"description" json:"description"`
|
||||
}
|
||||
|
||||
func FindAllNodeLevels() []*NodeLevel {
|
||||
return []*NodeLevel{
|
||||
{
|
||||
Name: "边缘节点",
|
||||
Code: 1,
|
||||
Description: "普通的边缘节点。",
|
||||
},
|
||||
{
|
||||
Name: "L2节点",
|
||||
Code: 2,
|
||||
Description: "特殊的边缘节点,同时负责同组上一级节点的回源。",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func FindNodeLevel(level int) *NodeLevel {
|
||||
level--
|
||||
|
||||
var levels = FindAllNodeLevels()
|
||||
if level < 0 {
|
||||
return levels[0]
|
||||
}
|
||||
if level < len(levels) {
|
||||
return levels[level]
|
||||
}
|
||||
return levels[0]
|
||||
}
|
||||
12
EdgeCommon/pkg/nodeconfigs/node_log_type.go
Normal file
12
EdgeCommon/pkg/nodeconfigs/node_log_type.go
Normal file
@@ -0,0 +1,12 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package nodeconfigs
|
||||
|
||||
type NodeLogType = string
|
||||
|
||||
const (
|
||||
NodeLogTypeListenAddressFailed NodeLogType = "listenAddressFailed"
|
||||
NodeLogTypeServerConfigInitFailed NodeLogType = "serverConfigInitFailed"
|
||||
NodeLogTypeRunScriptFailed NodeLogType = "runScriptFailed"
|
||||
NodeLogTypeScriptConsoleLog NodeLogType = "scriptConsoleLog"
|
||||
)
|
||||
10
EdgeCommon/pkg/nodeconfigs/node_parent_config.go
Normal file
10
EdgeCommon/pkg/nodeconfigs/node_parent_config.go
Normal file
@@ -0,0 +1,10 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package nodeconfigs
|
||||
|
||||
// ParentNodeConfig 父级节点配置
|
||||
type ParentNodeConfig struct {
|
||||
Id int64 `yaml:"id" json:"id"`
|
||||
Addrs []string `yaml:"addrs" json:"addrs"`
|
||||
SecretHash string `yaml:"secretHash" json:"secretHash"`
|
||||
}
|
||||
18
EdgeCommon/pkg/nodeconfigs/node_roles.go
Normal file
18
EdgeCommon/pkg/nodeconfigs/node_roles.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package nodeconfigs
|
||||
|
||||
type NodeRole = string
|
||||
|
||||
const (
|
||||
NodeRoleAdmin NodeRole = "admin"
|
||||
NodeRoleUser NodeRole = "user"
|
||||
NodeRoleProvider NodeRole = "provider"
|
||||
NodeRoleAPI NodeRole = "api"
|
||||
NodeRoleDatabase NodeRole = "database"
|
||||
NodeRoleLog NodeRole = "log"
|
||||
NodeRoleDNS NodeRole = "dns"
|
||||
NodeRoleMonitor NodeRole = "monitor"
|
||||
NodeRoleNode NodeRole = "node"
|
||||
NodeRoleCluster NodeRole = "cluster"
|
||||
NodeRoleAuthority NodeRole = "authority"
|
||||
NodeRoleReport NodeRole = "report"
|
||||
)
|
||||
43
EdgeCommon/pkg/nodeconfigs/node_status.go
Normal file
43
EdgeCommon/pkg/nodeconfigs/node_status.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package nodeconfigs
|
||||
|
||||
// NodeStatus 节点状态
|
||||
type NodeStatus struct {
|
||||
BuildVersion string `json:"buildVersion"` // 编译版本
|
||||
BuildVersionCode uint32 `json:"buildVersionCode"` // 版本数字
|
||||
ConfigVersion int64 `json:"configVersion"` // 节点配置版本
|
||||
|
||||
OS string `json:"os"`
|
||||
Arch string `json:"arch"`
|
||||
Hostname string `json:"hostname"`
|
||||
HostIP string `json:"hostIP"`
|
||||
CPUUsage float64 `json:"cpuUsage"`
|
||||
CPULogicalCount int `json:"cpuLogicalCount"`
|
||||
CPUPhysicalCount int `json:"cpuPhysicalCount"`
|
||||
MemoryUsage float64 `json:"memoryUsage"`
|
||||
MemoryTotal uint64 `json:"memoryTotal"`
|
||||
DiskUsage float64 `json:"diskUsage"`
|
||||
DiskMaxUsage float64 `json:"diskMaxUsage"`
|
||||
DiskMaxUsagePartition string `json:"diskMaxUsagePartition"`
|
||||
DiskTotal uint64 `json:"diskTotal"`
|
||||
DiskWritingSpeedMB int `json:"diskWritingSpeedMB"` // 硬盘写入速度
|
||||
UpdatedAt int64 `json:"updatedAt"`
|
||||
Timestamp int64 `json:"timestamp"` // 当前节点时间戳
|
||||
Load1m float64 `json:"load1m"`
|
||||
Load5m float64 `json:"load5m"`
|
||||
Load15m float64 `json:"load15m"`
|
||||
ConnectionCount int `json:"connectionCount"` // 连接数
|
||||
ExePath string `json:"exePath"` // 可执行文件路径
|
||||
APISuccessPercent float64 `json:"apiSuccessPercent"` // API成功比例
|
||||
APIAvgCostSeconds float64 `json:"apiAvgCostSeconds"` // API平均耗时
|
||||
|
||||
TrafficInBytes uint64 `json:"trafficInBytes"`
|
||||
TrafficOutBytes uint64 `json:"trafficOutBytes"`
|
||||
|
||||
CacheTotalDiskSize int64 `json:"cacheTotalDiskSize"`
|
||||
CacheTotalMemorySize int64 `json:"cacheTotalMemorySize"`
|
||||
|
||||
LocalFirewallName string `json:"localFirewallName"`
|
||||
|
||||
IsActive bool `json:"isActive"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
355
EdgeCommon/pkg/nodeconfigs/node_value_item.go
Normal file
355
EdgeCommon/pkg/nodeconfigs/node_value_item.go
Normal file
@@ -0,0 +1,355 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package nodeconfigs
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
// NodeValueItem 监控项
|
||||
type NodeValueItem = string
|
||||
|
||||
const (
|
||||
NodeValueItemCPU NodeValueItem = "cpu" // CPU
|
||||
NodeValueItemMemory NodeValueItem = "memory" // 内存
|
||||
NodeValueItemLoad NodeValueItem = "load" // 负载
|
||||
|
||||
NodeValueItemTrafficIn NodeValueItem = "trafficIn" // 业务上行流量
|
||||
NodeValueItemTrafficOut NodeValueItem = "trafficOut" // 业务下行流量
|
||||
NodeValueItemAllTraffic NodeValueItem = "allTraffic" // 所有流量
|
||||
|
||||
NodeValueItemConnections NodeValueItem = "connections" // 连接数
|
||||
NodeValueItemRequests NodeValueItem = "requests" // 请求访问量
|
||||
NodeValueItemAttackRequests NodeValueItem = "attackRequests" // 攻击请求访问量
|
||||
NodeValueItemDisk NodeValueItem = "disk" // 磁盘
|
||||
NodeValueItemCacheDir NodeValueItem = "cacheDir" // 缓存目录
|
||||
|
||||
NodeValueItemNetworkPackets NodeValueItem = "networkPackets" // 网络数据包统计
|
||||
)
|
||||
|
||||
type nodeValueItemDefinition struct {
|
||||
Code string `json:"code"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Params []*nodeValueItemParamDefinition `json:"params"`
|
||||
}
|
||||
|
||||
type nodeValueItemParamDefinition struct {
|
||||
Code string `json:"code"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
IsPercent bool `json:"isPercent"` // 是否支持百分比
|
||||
}
|
||||
|
||||
var nodeValueItemDefinitions = []*nodeValueItemDefinition{
|
||||
{
|
||||
Code: NodeValueItemCPU,
|
||||
Name: "CPU",
|
||||
Params: []*nodeValueItemParamDefinition{
|
||||
{
|
||||
Code: "usage",
|
||||
Name: "使用比例",
|
||||
Description: "0到100之间的数字",
|
||||
IsPercent: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Code: NodeValueItemMemory,
|
||||
Name: "内存",
|
||||
Params: []*nodeValueItemParamDefinition{
|
||||
{
|
||||
Code: "usage",
|
||||
Name: "使用比例",
|
||||
Description: "0到100之间的数字",
|
||||
IsPercent: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Code: NodeValueItemLoad,
|
||||
Name: "负载",
|
||||
Params: []*nodeValueItemParamDefinition{
|
||||
{
|
||||
Code: "load1m",
|
||||
Name: "1分钟负载",
|
||||
Description: "1分钟内的平均负载",
|
||||
},
|
||||
{
|
||||
Code: "load5m",
|
||||
Name: "5分钟负载",
|
||||
Description: "5分钟内的平均负载",
|
||||
},
|
||||
{
|
||||
Code: "load15m",
|
||||
Name: "15分钟负载",
|
||||
Description: "15分钟内的平均负载",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Code: NodeValueItemTrafficIn,
|
||||
Name: "上行流量",
|
||||
Description: "平均每分钟客户端发送到服务器端的流量。",
|
||||
Params: []*nodeValueItemParamDefinition{
|
||||
{
|
||||
Code: "total",
|
||||
Name: "流量",
|
||||
Description: "单位为字节",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Code: NodeValueItemTrafficOut,
|
||||
Name: "下行流量",
|
||||
Description: "平均每分钟服务器端发送到客户端的流量。",
|
||||
Params: []*nodeValueItemParamDefinition{
|
||||
{
|
||||
Code: "total",
|
||||
Name: "流量",
|
||||
Description: "单位为字节",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Code: NodeValueItemConnections,
|
||||
Name: "连接数",
|
||||
Description: "平均每分钟连接数",
|
||||
Params: []*nodeValueItemParamDefinition{
|
||||
{
|
||||
Code: "total",
|
||||
Name: "总数",
|
||||
Description: "连接总数",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Code: NodeValueItemRequests,
|
||||
Name: "请求数",
|
||||
Description: "平均每分钟请求数",
|
||||
Params: []*nodeValueItemParamDefinition{
|
||||
{
|
||||
Code: "total",
|
||||
Name: "总数",
|
||||
Description: "请求总数",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Code: NodeValueItemAttackRequests,
|
||||
Name: "攻击请求数",
|
||||
Description: "平均每分钟攻击请求数",
|
||||
Params: []*nodeValueItemParamDefinition{
|
||||
{
|
||||
Code: "total",
|
||||
Name: "总数",
|
||||
Description: "攻击请求总数",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Code: NodeValueItemDisk,
|
||||
Name: "硬盘空间",
|
||||
Params: []*nodeValueItemParamDefinition{
|
||||
{
|
||||
Code: "usage",
|
||||
Name: "使用比例",
|
||||
Description: "0到100之间的数字",
|
||||
IsPercent: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Code: NodeValueItemNetworkPackets,
|
||||
Name: "网络数据包",
|
||||
Params: []*nodeValueItemParamDefinition{
|
||||
{
|
||||
Code: "tcpInPPS",
|
||||
Name: "TCP入口包速率(pps)",
|
||||
},
|
||||
{
|
||||
Code: "udpInPPS",
|
||||
Name: "UDP入口包速率(pps)",
|
||||
},
|
||||
{
|
||||
Code: "icmpInPPS",
|
||||
Name: "ICMP入口包速率(pps)",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// FindAllNodeValueItemDefinitions 获取所有监控项信息
|
||||
func FindAllNodeValueItemDefinitions() []*nodeValueItemDefinition {
|
||||
return nodeValueItemDefinitions
|
||||
}
|
||||
|
||||
// FindNodeValueItemName 获取监控项名称
|
||||
func FindNodeValueItemName(code NodeValueItem) string {
|
||||
for _, def := range nodeValueItemDefinitions {
|
||||
if def.Code == code {
|
||||
return def.Name
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// FindNodeValueItemParamName 获取监控项某个参数的名称
|
||||
func FindNodeValueItemParamName(nodeCode NodeValueItem, paramCode string) string {
|
||||
for _, def := range nodeValueItemDefinitions {
|
||||
if def.Code == nodeCode {
|
||||
for _, p := range def.Params {
|
||||
if p.Code == paramCode {
|
||||
return p.Name
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// CheckNodeValueItemParamIsPercent 判断监控项某个参数是否支持百分比
|
||||
func CheckNodeValueItemParamIsPercent(nodeCode NodeValueItem, paramCode string) bool {
|
||||
for _, def := range nodeValueItemDefinitions {
|
||||
if def.Code == nodeCode {
|
||||
for _, p := range def.Params {
|
||||
if p.Code == paramCode {
|
||||
return p.IsPercent
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// NodeValueRange 值范围
|
||||
type NodeValueRange = string
|
||||
|
||||
const (
|
||||
NodeValueRangeMinute NodeValueRange = "minute"
|
||||
)
|
||||
|
||||
// NodeValueOperator 操作符
|
||||
type NodeValueOperator = string
|
||||
|
||||
const (
|
||||
NodeValueOperatorGt NodeValueOperator = "gt" // 大于
|
||||
NodeValueOperatorGte NodeValueOperator = "gte" // 大于等于
|
||||
NodeValueOperatorLt NodeValueOperator = "lt" // 小于
|
||||
NodeValueOperatorLte NodeValueOperator = "lte" // 小于等于
|
||||
NodeValueOperatorEq NodeValueOperator = "eq" // 等于
|
||||
NodeValueOperatorNeq NodeValueOperator = "neq" // 不等于
|
||||
)
|
||||
|
||||
type nodeValueOperatorDefinition struct {
|
||||
Code string `json:"code"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
var nodeValueOperatorDefinitions = []*nodeValueOperatorDefinition{
|
||||
{
|
||||
Code: NodeValueOperatorGt,
|
||||
Name: "大于",
|
||||
},
|
||||
{
|
||||
Code: NodeValueOperatorGte,
|
||||
Name: "大于等于",
|
||||
},
|
||||
{
|
||||
Code: NodeValueOperatorLt,
|
||||
Name: "小于",
|
||||
},
|
||||
{
|
||||
Code: NodeValueOperatorLte,
|
||||
Name: "小于等于",
|
||||
},
|
||||
{
|
||||
Code: NodeValueOperatorEq,
|
||||
Name: "等于",
|
||||
},
|
||||
{
|
||||
Code: NodeValueOperatorNeq,
|
||||
Name: "不等于",
|
||||
},
|
||||
}
|
||||
|
||||
// FindNodeValueOperatorName 操作符名称
|
||||
func FindNodeValueOperatorName(operator NodeValueOperator) string {
|
||||
for _, def := range nodeValueOperatorDefinitions {
|
||||
if def.Code == operator {
|
||||
return def.Name
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// FindAllNodeValueOperatorDefinitions 获取所有操作符定义
|
||||
func FindAllNodeValueOperatorDefinitions() []*nodeValueOperatorDefinition {
|
||||
return nodeValueOperatorDefinitions
|
||||
}
|
||||
|
||||
// CompareNodeValue 对比值
|
||||
func CompareNodeValue(operator NodeValueOperator, value1 float64, value2 float64) bool {
|
||||
switch operator {
|
||||
case NodeValueOperatorGt:
|
||||
return value1 > value2
|
||||
case NodeValueOperatorGte:
|
||||
return value1 >= value2
|
||||
case NodeValueOperatorLt:
|
||||
return value1 < value2
|
||||
case NodeValueOperatorLte:
|
||||
return value1 <= value2
|
||||
case NodeValueOperatorEq:
|
||||
return value1 == value2
|
||||
case NodeValueOperatorNeq:
|
||||
return value1 != value2
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// NodeValueSumMethod 聚合方法
|
||||
type NodeValueSumMethod = string
|
||||
|
||||
const (
|
||||
NodeValueSumMethodSum NodeValueSumMethod = "sum" // 相加
|
||||
NodeValueSumMethodAvg NodeValueSumMethod = "avg" // 平均
|
||||
)
|
||||
|
||||
// FindNodeValueSumMethodName 聚合方法名称
|
||||
func FindNodeValueSumMethodName(method NodeValueSumMethod) string {
|
||||
switch method {
|
||||
case NodeValueSumMethodSum:
|
||||
return "和"
|
||||
case NodeValueSumMethodAvg:
|
||||
return "平均"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// NodeValueDurationUnit 时间单位
|
||||
type NodeValueDurationUnit = string
|
||||
|
||||
const (
|
||||
NodeValueDurationUnitMinute NodeValueDurationUnit = "minute"
|
||||
)
|
||||
|
||||
// FindNodeValueDurationUnitName 时间单位名称
|
||||
func FindNodeValueDurationUnitName(unit NodeValueDurationUnit) string {
|
||||
switch unit {
|
||||
case NodeValueDurationUnitMinute:
|
||||
return "分钟"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// UnmarshalNodeValue 对值进行解码
|
||||
func UnmarshalNodeValue(valueJSON []byte) string {
|
||||
var result = ""
|
||||
err := json.Unmarshal(valueJSON, &result)
|
||||
if err != nil {
|
||||
// 暂时不提示错误
|
||||
}
|
||||
return result
|
||||
}
|
||||
160
EdgeCommon/pkg/nodeconfigs/node_value_thresholds.go
Normal file
160
EdgeCommon/pkg/nodeconfigs/node_value_thresholds.go
Normal file
@@ -0,0 +1,160 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package nodeconfigs
|
||||
|
||||
import "github.com/iwind/TeaGo/maps"
|
||||
|
||||
type IPAddressThresholdItem = string
|
||||
|
||||
const (
|
||||
IPAddressThresholdItemNodeAvgRequests IPAddressThresholdItem = "nodeAvgRequests" // 个
|
||||
IPAddressThresholdItemNodeAvgTrafficOut IPAddressThresholdItem = "nodeAvgTrafficOut" // 节点下行流量 M
|
||||
IPAddressThresholdItemNodeAvgTrafficIn IPAddressThresholdItem = "nodeAvgTrafficIn" // 节点上行流量 M
|
||||
IPAddressThresholdItemNodeHealthCheck IPAddressThresholdItem = "nodeHealthCheck" // 节点健康检查结果
|
||||
IPAddressThresholdItemGroupAvgRequests IPAddressThresholdItem = "groupAvgRequests" // 个
|
||||
IPAddressThresholdItemGroupAvgTrafficIn IPAddressThresholdItem = "groupAvgTrafficIn" // 分组上行流量 M
|
||||
IPAddressThresholdItemGroupAvgTrafficOut IPAddressThresholdItem = "groupAvgTrafficOut" // 分组下行流量 M
|
||||
IPAddressThresholdItemClusterAvgRequests IPAddressThresholdItem = "clusterAvgRequests" // 个
|
||||
IPAddressThresholdItemClusterAvgTrafficIn IPAddressThresholdItem = "clusterAvgTrafficIn" // 集群上行流量 M
|
||||
IPAddressThresholdItemClusterAvgTrafficOut IPAddressThresholdItem = "clusterAvgTrafficOut" // 集群下行流量 M
|
||||
IPAddressThresholdItemConnectivity IPAddressThresholdItem = "connectivity" // 0-100
|
||||
)
|
||||
|
||||
// FindAllIPAddressThresholdItems IP相关阈值项目
|
||||
func FindAllIPAddressThresholdItems() []maps.Map {
|
||||
return []maps.Map{
|
||||
{
|
||||
"name": "节点平均请求数",
|
||||
"code": IPAddressThresholdItemNodeAvgRequests,
|
||||
"description": "当前节点在单位时间内接收到的平均请求数。",
|
||||
"unit": "个",
|
||||
},
|
||||
{
|
||||
"name": "节点平均下行流量",
|
||||
"code": IPAddressThresholdItemNodeAvgTrafficOut,
|
||||
"description": "当前节点在单位时间内发送的下行流量。",
|
||||
"unit": "M",
|
||||
},
|
||||
{
|
||||
"name": "节点平均上行流量",
|
||||
"code": IPAddressThresholdItemNodeAvgTrafficIn,
|
||||
"description": "当前节点在单位时间内接收的上行流量。",
|
||||
"unit": "M",
|
||||
},
|
||||
{
|
||||
"name": "节点健康检查结果",
|
||||
"code": IPAddressThresholdItemNodeHealthCheck,
|
||||
"description": "当前节点健康检查结果。",
|
||||
"unit": "",
|
||||
},
|
||||
|
||||
{
|
||||
"name": "IP连通性",
|
||||
"code": IPAddressThresholdItemConnectivity,
|
||||
"description": "通过区域监控得到的当前IP地址的连通性数值,取值在0和100之间。",
|
||||
"unit": "%",
|
||||
},
|
||||
|
||||
{
|
||||
"name": "分组平均请求数",
|
||||
"code": IPAddressThresholdItemGroupAvgRequests,
|
||||
"description": "当前节点所在分组在单位时间内接收到的平均请求数。",
|
||||
"unit": "个",
|
||||
},
|
||||
{
|
||||
"name": "分组平均下行流量",
|
||||
"code": IPAddressThresholdItemGroupAvgTrafficOut,
|
||||
"description": "当前节点所在分组在单位时间内发送的下行流量。",
|
||||
"unit": "M",
|
||||
},
|
||||
{
|
||||
"name": "分组平均上行流量",
|
||||
"code": IPAddressThresholdItemGroupAvgTrafficIn,
|
||||
"description": "当前节点所在分组在单位时间内接收的上行流量。",
|
||||
"unit": "M",
|
||||
},
|
||||
|
||||
{
|
||||
"name": "集群平均请求数",
|
||||
"code": IPAddressThresholdItemClusterAvgRequests,
|
||||
"description": "当前节点所在集群在单位时间内接收到的平均请求数。",
|
||||
"unit": "个",
|
||||
},
|
||||
{
|
||||
"name": "集群平均下行流量",
|
||||
"code": IPAddressThresholdItemClusterAvgTrafficOut,
|
||||
"description": "当前节点所在集群在单位时间内发送的下行流量。",
|
||||
"unit": "M",
|
||||
},
|
||||
{
|
||||
"name": "集群平均上行流量",
|
||||
"code": IPAddressThresholdItemClusterAvgTrafficIn,
|
||||
"description": "当前节点所在集群在单位时间内接收的上行流量。",
|
||||
"unit": "M",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// IPAddressThresholdConfig 阈值列表
|
||||
type IPAddressThresholdConfig struct {
|
||||
Id int64 `json:"id"`
|
||||
Items []*IPAddressThresholdItemConfig `json:"items"`
|
||||
Actions []*IPAddressThresholdActionConfig `json:"actions"`
|
||||
}
|
||||
|
||||
// IPAddressThresholdItemConfig 阈值项目
|
||||
type IPAddressThresholdItemConfig struct {
|
||||
Item IPAddressThresholdItem `json:"item"`
|
||||
Operator NodeValueOperator `json:"operator"`
|
||||
Value float64 `json:"value"`
|
||||
Duration int `json:"duration"`
|
||||
DurationUnit NodeValueDurationUnit `json:"durationUnit"`
|
||||
Options maps.Map `json:"options"` // 附加选项
|
||||
}
|
||||
|
||||
type IPAddressThresholdActionConfig struct {
|
||||
Action string `json:"action"`
|
||||
Options maps.Map `json:"options"`
|
||||
}
|
||||
|
||||
// IPAddressThresholdAction 动作
|
||||
type IPAddressThresholdAction = string
|
||||
|
||||
const (
|
||||
IPAddressThresholdActionUp IPAddressThresholdAction = "up" // 上线
|
||||
IPAddressThresholdActionDown IPAddressThresholdAction = "down" // 下线
|
||||
IPAddressThresholdActionNotify IPAddressThresholdAction = "notify" // 通知
|
||||
IPAddressThresholdActionSwitch IPAddressThresholdAction = "switch" // 切换到备用IP
|
||||
IPAddressThresholdActionWebHook IPAddressThresholdAction = "webHook" // 调用外部Webhook
|
||||
)
|
||||
|
||||
// FindAllIPAddressThresholdActions IP相关阈值动作
|
||||
func FindAllIPAddressThresholdActions() []maps.Map {
|
||||
return []maps.Map{
|
||||
{
|
||||
"name": "上线",
|
||||
"code": IPAddressThresholdActionUp,
|
||||
"description": "上线当前IP。",
|
||||
},
|
||||
{
|
||||
"name": "下线",
|
||||
"code": IPAddressThresholdActionDown,
|
||||
"description": "下线当前IP。",
|
||||
},
|
||||
{
|
||||
"name": "通知",
|
||||
"code": IPAddressThresholdActionNotify,
|
||||
"description": "发送已达到阈值通知。",
|
||||
},
|
||||
{
|
||||
"name": "切换",
|
||||
"code": IPAddressThresholdActionSwitch,
|
||||
"description": "在DNS中记录中将IP切换到指定的备用IP。",
|
||||
},
|
||||
{
|
||||
"name": "WebHook",
|
||||
"code": IPAddressThresholdActionWebHook,
|
||||
"description": "调用外部的WebHook。",
|
||||
},
|
||||
}
|
||||
}
|
||||
11
EdgeCommon/pkg/nodeconfigs/product_config.go
Normal file
11
EdgeCommon/pkg/nodeconfigs/product_config.go
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package nodeconfigs
|
||||
|
||||
const DefaultProductName = "GoEdge"
|
||||
|
||||
// ProductConfig 产品相关设置
|
||||
type ProductConfig struct {
|
||||
Name string `yaml:"name" json:"name"`
|
||||
Version string `yaml:"version" json:"version"`
|
||||
}
|
||||
19
EdgeCommon/pkg/nodeconfigs/service_systemd_config.go
Normal file
19
EdgeCommon/pkg/nodeconfigs/service_systemd_config.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package nodeconfigs
|
||||
|
||||
type (
|
||||
SystemServiceType = string
|
||||
)
|
||||
|
||||
const (
|
||||
// TODO 需要支持supervisor等常用daemon管理工具
|
||||
SystemServiceTypeSystemd SystemServiceType = "systemd"
|
||||
)
|
||||
|
||||
// Systemd配置
|
||||
type SystemdServiceConfig struct {
|
||||
IsOn bool `yaml:"isOn" json:"isOn"` // 是否启用
|
||||
Provides string `yaml:"provides" json:"provides"` // 提供者,可以是服务名
|
||||
ShortDescription string `yaml:"shortDescription" json:"shortDescription"` // 短描述
|
||||
Description string `yaml:"description" json:"description"` // 长描述
|
||||
ExecPath string `yaml:"execPath" json:"execPath"` // 可执行文件的路径
|
||||
}
|
||||
11
EdgeCommon/pkg/nodeconfigs/ssh_params.go
Normal file
11
EdgeCommon/pkg/nodeconfigs/ssh_params.go
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package nodeconfigs
|
||||
|
||||
func DefaultSSHParams() *SSHParams {
|
||||
return &SSHParams{Port: 22}
|
||||
}
|
||||
|
||||
type SSHParams struct {
|
||||
Port int `json:"port"`
|
||||
}
|
||||
105
EdgeCommon/pkg/nodeconfigs/timezones.go
Normal file
105
EdgeCommon/pkg/nodeconfigs/timezones.go
Normal file
File diff suppressed because one or more lines are too long
17
EdgeCommon/pkg/nodeconfigs/timezones_test.go
Normal file
17
EdgeCommon/pkg/nodeconfigs/timezones_test.go
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package nodeconfigs
|
||||
|
||||
import (
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestFindAllTimeZoneLocations(t *testing.T) {
|
||||
var before = time.Now()
|
||||
var locations = FindAllTimeZoneLocations()
|
||||
t.Log(len(locations), "locations")
|
||||
t.Logf("%.2f %s", time.Since(before).Seconds()*1000, "ms")
|
||||
logs.PrintAsJSON(locations, t)
|
||||
}
|
||||
22
EdgeCommon/pkg/nodeconfigs/toa_config.go
Normal file
22
EdgeCommon/pkg/nodeconfigs/toa_config.go
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build !plus
|
||||
|
||||
package nodeconfigs
|
||||
|
||||
// NewTOAConfig 默认的TOA配置
|
||||
func NewTOAConfig() *TOAConfig {
|
||||
return &TOAConfig{}
|
||||
}
|
||||
|
||||
// TOAConfig TOA相关配置
|
||||
type TOAConfig struct {
|
||||
IsOn bool `yaml:"isOn" json:"isOn"`
|
||||
}
|
||||
|
||||
func (this *TOAConfig) Init() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *TOAConfig) RandLocalPort() uint16 {
|
||||
return 0
|
||||
}
|
||||
110
EdgeCommon/pkg/nodeconfigs/toa_config_plus.go
Normal file
110
EdgeCommon/pkg/nodeconfigs/toa_config_plus.go
Normal file
@@ -0,0 +1,110 @@
|
||||
//go:build plus
|
||||
|
||||
package nodeconfigs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
"net"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// NewTOAConfig 默认的TOA配置
|
||||
func NewTOAConfig() *TOAConfig {
|
||||
return &TOAConfig{
|
||||
IsOn: false,
|
||||
Debug: false,
|
||||
OptionTypeV4: 0xfe,
|
||||
OptionTypeV6: 0xfe,
|
||||
MinQueueId: 100,
|
||||
AutoSetup: true,
|
||||
}
|
||||
}
|
||||
|
||||
// TOAConfig TOA相关配置
|
||||
type TOAConfig struct {
|
||||
IsOn bool `yaml:"isOn" json:"isOn"` // 是否启用
|
||||
Debug bool `yaml:"debug" json:"debug"`
|
||||
OldOptionType uint8 `yaml:"optionType" json:"optionType"` // Deprecated 已过期,使用 OptionTypeV4 和 OptionTypeV6 代替
|
||||
OptionTypeV4 uint8 `yaml:"optionTypeV4" json:"optionTypeV4"` // IPv4的类型
|
||||
OptionTypeV6 uint8 `yaml:"OptionTypeV6" json:"optionTypeV6"`
|
||||
MinQueueId uint8 `yaml:"minQueueId" json:"minQueueId"`
|
||||
AutoSetup bool `yaml:"autoSetup" json:"autoSetup"`
|
||||
MinLocalPort uint16 `yaml:"minLocalPort" json:"minLocalPort"` // 本地可使用的最小端口 TODO
|
||||
MaxLocalPort uint16 `yaml:"maxLocalPort" json:"maxLocalPort"` // 本地可使用的最大端口 TODO
|
||||
SockPath string `yaml:"sockPath" json:"sockPath"` // Sock文件路径 TODO
|
||||
ByPassPorts []uint16 `yaml:"byPassPorts" json:"byPassPorts"` // 忽略的端口 TODO
|
||||
|
||||
minLocalPort int
|
||||
maxLocalPort int
|
||||
}
|
||||
|
||||
func (this *TOAConfig) Init() error {
|
||||
// LocalPort
|
||||
minPort := this.MinLocalPort
|
||||
maxPort := this.MaxLocalPort
|
||||
if minPort == 0 {
|
||||
minPort = 1025
|
||||
}
|
||||
if maxPort == 0 {
|
||||
maxPort = 65534
|
||||
}
|
||||
if minPort > maxPort {
|
||||
minPort, maxPort = maxPort, minPort
|
||||
}
|
||||
this.minLocalPort = int(minPort)
|
||||
this.maxLocalPort = int(maxPort)
|
||||
|
||||
// 兼容
|
||||
if this.OptionTypeV4 == 0 && this.OldOptionType > 0 {
|
||||
this.OptionTypeV4 = this.OldOptionType
|
||||
}
|
||||
if this.OptionTypeV6 == 0 && this.OldOptionType > 0 {
|
||||
this.OptionTypeV6 = this.OldOptionType
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SockFile Sock路径
|
||||
func (this *TOAConfig) SockFile() string {
|
||||
if len(this.SockPath) == 0 {
|
||||
return "/tmp/edge-toa.sock"
|
||||
}
|
||||
return this.SockPath
|
||||
}
|
||||
|
||||
// RandLocalPort 获取随机端口
|
||||
func (this *TOAConfig) RandLocalPort() uint16 {
|
||||
listener, err := net.Listen("tcp", ":0")
|
||||
if err != nil {
|
||||
return uint16(rands.Int(this.minLocalPort, this.maxLocalPort))
|
||||
}
|
||||
_ = listener.Close()
|
||||
return uint16(listener.Addr().(*net.TCPAddr).Port)
|
||||
}
|
||||
|
||||
// AsArgs 转换为参数的形式
|
||||
func (this *TOAConfig) AsArgs() (args []string) {
|
||||
args = append(args, "run")
|
||||
args = append(args, "-option-type-v4="+fmt.Sprintf("%d", this.OptionTypeV4))
|
||||
args = append(args, "-option-type-v6="+fmt.Sprintf("%d", this.OptionTypeV6))
|
||||
args = append(args, "-min-queue-id="+fmt.Sprintf("%d", this.MinQueueId))
|
||||
args = append(args, "-max-queue-id="+fmt.Sprintf("%d", this.MaxQueueId()))
|
||||
if this.AutoSetup {
|
||||
args = append(args, "-auto-setup")
|
||||
}
|
||||
if this.Debug {
|
||||
args = append(args, "-debug")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MaxQueueId 获取队列ID最大值
|
||||
func (this *TOAConfig) MaxQueueId() uint8 {
|
||||
var maxQueueId = int(this.MinQueueId) + runtime.NumCPU() - 1
|
||||
if maxQueueId > 255 {
|
||||
maxQueueId = 255
|
||||
}
|
||||
return uint8(maxQueueId)
|
||||
}
|
||||
78
EdgeCommon/pkg/nodeconfigs/toa_config_plus_test.go
Normal file
78
EdgeCommon/pkg/nodeconfigs/toa_config_plus_test.go
Normal file
@@ -0,0 +1,78 @@
|
||||
//go:build plus
|
||||
|
||||
package nodeconfigs
|
||||
|
||||
import (
|
||||
"net"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestTOAConfig_RandLocalPort(t *testing.T) {
|
||||
{
|
||||
toa := &TOAConfig{}
|
||||
err := toa.Init()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(toa.RandLocalPort())
|
||||
}
|
||||
{
|
||||
toa := &TOAConfig{
|
||||
MinLocalPort: 1,
|
||||
MaxLocalPort: 2,
|
||||
}
|
||||
err := toa.Init()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(toa.RandLocalPort())
|
||||
}
|
||||
}
|
||||
|
||||
func TestTOAConfig_FreePort(t *testing.T) {
|
||||
before := time.Now()
|
||||
listener, err := net.Listen("tcp", ":0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(listener.Addr())
|
||||
_ = listener.Close()
|
||||
t.Log(time.Since(before).Seconds()*1000, "ms")
|
||||
time.Sleep(30 * time.Second)
|
||||
}
|
||||
|
||||
func TestTOAConfig_AsArgs(t *testing.T) {
|
||||
toa := &TOAConfig{
|
||||
IsOn: false,
|
||||
Debug: true,
|
||||
OptionTypeV4: 0xfe,
|
||||
OptionTypeV6: 0xfe,
|
||||
MinQueueId: 10,
|
||||
AutoSetup: true,
|
||||
MinLocalPort: 0,
|
||||
MaxLocalPort: 0,
|
||||
SockPath: "",
|
||||
ByPassPorts: nil,
|
||||
}
|
||||
err := toa.Init()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(toa.AsArgs())
|
||||
}
|
||||
|
||||
func BenchmarkTOAConfig_RandLocalPort(b *testing.B) {
|
||||
runtime.GOMAXPROCS(1)
|
||||
|
||||
toa := &TOAConfig{
|
||||
MinLocalPort: 1,
|
||||
MaxLocalPort: 2,
|
||||
}
|
||||
_ = toa.Init()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = toa.RandLocalPort()
|
||||
}
|
||||
}
|
||||
16
EdgeCommon/pkg/nodeconfigs/uam_policy.go
Normal file
16
EdgeCommon/pkg/nodeconfigs/uam_policy.go
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build !plus
|
||||
|
||||
package nodeconfigs
|
||||
|
||||
func NewUAMPolicy() *UAMPolicy {
|
||||
return &UAMPolicy{}
|
||||
}
|
||||
|
||||
type UAMPolicy struct {
|
||||
IsOn bool `yaml:"isOn" json:"isOn"`
|
||||
}
|
||||
|
||||
func (this *UAMPolicy) Init() error {
|
||||
return nil
|
||||
}
|
||||
46
EdgeCommon/pkg/nodeconfigs/uam_policy_plus.go
Normal file
46
EdgeCommon/pkg/nodeconfigs/uam_policy_plus.go
Normal file
@@ -0,0 +1,46 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package nodeconfigs
|
||||
|
||||
import "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||
|
||||
func NewUAMPolicy() *UAMPolicy {
|
||||
var policy = &UAMPolicy{
|
||||
IsOn: true,
|
||||
AllowSearchEngines: true,
|
||||
IncludeSubdomains: true,
|
||||
DenySpiders: true,
|
||||
MaxFails: 30,
|
||||
BlockSeconds: 1800,
|
||||
UITitle: "",
|
||||
UIBody: "",
|
||||
KeyLife: 3600,
|
||||
}
|
||||
|
||||
policy.Firewall.Scope = firewallconfigs.FirewallScopeGlobal
|
||||
return policy
|
||||
}
|
||||
|
||||
type UAMPolicy struct {
|
||||
IsOn bool `yaml:"isOn" json:"isOn"`
|
||||
AllowSearchEngines bool `yaml:"allowSearchEngines" json:"allowSearchEngines"` // 直接跳过常见搜索引擎
|
||||
DenySpiders bool `yaml:"denySpiders" json:"denySpiders"` // 拦截常见爬虫
|
||||
MaxFails int `yaml:"maxFails" json:"maxFails"` // 失败尝试次数
|
||||
BlockSeconds int `yaml:"blockSeconds" json:"blockSeconds"` // 失败拦截秒数
|
||||
IncludeSubdomains bool `yaml:"includeSubdomains" json:"includeSubdomains"` // 是否包含子域名
|
||||
|
||||
UITitle string `yaml:"uiTitle" json:"uiTitle"` // 页面标题
|
||||
UIBody string `yaml:"uiBody" json:"uiBody"` // 页面内容
|
||||
|
||||
KeyLife int `yaml:"keyLife" json:"keyLife"` // Key有效期
|
||||
|
||||
// 防火墙策略
|
||||
Firewall struct {
|
||||
Scope firewallconfigs.FirewallScope `json:"scope" yaml:"scope"`
|
||||
} `json:"firewall" yaml:"firewall"`
|
||||
}
|
||||
|
||||
func (this *UAMPolicy) Init() error {
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user