// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn . //go:build plus package serverconfigs import ( "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared" ) type HTTPCCLevel = string // DefaultHTTPCCConfig 默认的CC配置 func DefaultHTTPCCConfig() *HTTPCCConfig { return &HTTPCCConfig{ EnableFingerprint: true, EnableGET302: true, UseDefaultThresholds: true, IgnoreCommonFiles: true, } } const ( HTTPCCLevelLow HTTPCCLevel = "low" HTTPCCLevelMiddle HTTPCCLevel = "middle" HTTPCCLevelHigh HTTPCCLevel = "high" ) type HTTPCCThreshold struct { PeriodSeconds int32 `yaml:"periodSeconds" json:"periodSeconds"` // 计算周期 MaxRequests int32 `yaml:"maxRequests" json:"maxRequests"` // 请求数最大值 //MaxConnections int32 `yaml:"maxConnections" json:"maxConnections"` // 连接数最大值 TODO BlockSeconds int32 `yaml:"blockSeconds" json:"blockSeconds"` // 拦截时间 } func NewHTTPCCThreshold() *HTTPCCThreshold { return &HTTPCCThreshold{} } func (this *HTTPCCThreshold) Merge(threshold *HTTPCCThreshold) { if threshold.PeriodSeconds > 0 { this.PeriodSeconds = threshold.PeriodSeconds } if threshold.MaxRequests > 0 { this.MaxRequests = threshold.MaxRequests } if threshold.BlockSeconds > 0 { this.BlockSeconds = threshold.BlockSeconds } } func (this *HTTPCCThreshold) MergeIfEmpty(threshold *HTTPCCThreshold) { if threshold.PeriodSeconds > 0 && this.PeriodSeconds <= 0 { this.PeriodSeconds = threshold.PeriodSeconds } if threshold.MaxRequests > 0 && this.MaxRequests <= 0 { this.MaxRequests = threshold.MaxRequests } if threshold.BlockSeconds > 0 && this.BlockSeconds <= 0 { this.BlockSeconds = threshold.BlockSeconds } } func (this *HTTPCCThreshold) Clone() *HTTPCCThreshold { return &HTTPCCThreshold{ PeriodSeconds: this.PeriodSeconds, MaxRequests: this.MaxRequests, BlockSeconds: this.BlockSeconds, } } const ( DefaultHTTPCCThresholdPeriodSeconds0 = 5 DefaultHTTPCCThresholdPeriodSeconds1 = 60 DefaultHTTPCCThresholdPeriodSeconds2 = 300 DefaultHTTPCCThresholdBlockSeconds0 = 600 DefaultHTTPCCThresholdBlockSeconds1 = 2400 DefaultHTTPCCThresholdBlockSeconds2 = 3600 ) var DefaultHTTPCCThresholds = []*HTTPCCThreshold{ { PeriodSeconds: DefaultHTTPCCThresholdPeriodSeconds0, MaxRequests: 60, BlockSeconds: DefaultHTTPCCThresholdBlockSeconds0, }, { PeriodSeconds: DefaultHTTPCCThresholdPeriodSeconds1, MaxRequests: 150, BlockSeconds: DefaultHTTPCCThresholdBlockSeconds1, }, { PeriodSeconds: DefaultHTTPCCThresholdPeriodSeconds2, MaxRequests: 300, BlockSeconds: DefaultHTTPCCThresholdBlockSeconds2, }, } func CloneDefaultHTTPCCThresholds() []*HTTPCCThreshold { var result = []*HTTPCCThreshold{} for _, threshold := range DefaultHTTPCCThresholds { result = append(result, threshold.Clone()) } return result } // HTTPCCConfig HTTP CC防护配置 type HTTPCCConfig struct { IsPrior bool `yaml:"isPrior" json:"isPrior"` // 是否覆盖父级 IsOn bool `yaml:"isOn" json:"isOn"` // 是否启用 Level HTTPCCLevel `yaml:"level" json:"level"` // 级别 TODO WithRequestPath bool `yaml:"withRequestPath" json:"withRequestPath"` // 根据URL路径区分请求 TODO UseDefaultThresholds bool `yaml:"useDefaultThresholds" json:"useDefaultThresholds"` // 是否使用默认的阈值设置 Thresholds []*HTTPCCThreshold `yaml:"thresholds" json:"thresholds"` // 阈值设置 IgnoreCommonFiles bool `yaml:"ignoreCommonFiles" json:"ignoreCommonFiles"` // 忽略常用文件,如CSS、JS等 IgnoreCommonAgents bool `yaml:"ignoreCommonAgents" json:"ignoreCommonAgents"` // 忽略常见搜索引擎等 TODO Action string `yaml:"action" json:"action"` // 动作,比如block、captcha等 TODO OnlyURLPatterns []*shared.URLPattern `yaml:"onlyURLPatterns" json:"onlyURLPatterns"` // 仅限的URL ExceptURLPatterns []*shared.URLPattern `yaml:"exceptURLPatterns" json:"exceptURLPatterns"` // 排除的URL EnableFingerprint bool `yaml:"enableFingerprint" json:"enableFingerprint"` // 是否检查请求来源指纹 EnableGET302 bool `yaml:"enableGET302" json:"enableGET302"` // 是否支持GET302校验 MinQPSPerIP int `yaml:"minQPSPerIP" json:"minQPSPerIP"` // 启用要求的单IP最低平均QPS } func NewHTTPCCConfig() *HTTPCCConfig { return &HTTPCCConfig{ WithRequestPath: false, IgnoreCommonFiles: true, IgnoreCommonAgents: true, Action: "captcha", EnableFingerprint: true, EnableGET302: true, } } func (this *HTTPCCConfig) Init() error { // only urls for _, pattern := range this.OnlyURLPatterns { err := pattern.Init() if err != nil { return err } } // except urls for _, pattern := range this.ExceptURLPatterns { err := pattern.Init() if err != nil { return err } } return nil } func (this *HTTPCCConfig) MatchURL(url string) bool { // except if len(this.ExceptURLPatterns) > 0 { for _, pattern := range this.ExceptURLPatterns { if pattern.Match(url) { return false } } } if len(this.OnlyURLPatterns) > 0 { for _, pattern := range this.OnlyURLPatterns { if pattern.Match(url) { return true } } return false } return true }