mirror of
				https://github.com/TeaOSLab/EdgeCommon.git
				synced 2025-11-04 05:00:24 +08:00 
			
		
		
		
	5秒盾支持例外URL和限制URL
This commit is contained in:
		
							
								
								
									
										47
									
								
								pkg/serverconfigs/http_cc_config.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								pkg/serverconfigs/http_cc_config.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
			
		||||
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
 | 
			
		||||
 | 
			
		||||
package serverconfigs
 | 
			
		||||
 | 
			
		||||
import "strings"
 | 
			
		||||
 | 
			
		||||
// HTTPCCConfig HTTP CC防护配置
 | 
			
		||||
type HTTPCCConfig struct {
 | 
			
		||||
	IsPrior            bool   `yaml:"isPrior" json:"isPrior"`                       // 是否覆盖父级
 | 
			
		||||
	IsOn               bool   `yaml:"isOn" json:"isOn"`                             // 是否启用
 | 
			
		||||
	WithRequestPath    bool   `yaml:"withRequestPath" json:"withRequestPath"`       // 根据URL路径区分请求
 | 
			
		||||
	PeriodSeconds      int32  `yaml:"periodSeconds" json:"periodSeconds"`           // 计算周期
 | 
			
		||||
	MaxRequests        int32  `yaml:"maxRequests" json:"maxRequests"`               // 请求数最大值
 | 
			
		||||
	MaxConnections     int32  `yaml:"maxConnections" json:"maxConnections"`         // 连接数最大值
 | 
			
		||||
	IgnoreCommonFiles  bool   `yaml:"ignoreCommonFiles" json:"ignoreCommonFiles"`   // 忽略常用文件,如CSS、JS等
 | 
			
		||||
	IgnoreCommonAgents bool   `yaml:"ignoreCommonAgents" json:"ignoreCommonAgents"` // 忽略常见搜索引擎等
 | 
			
		||||
	Action             string `yaml:"action" json:"action"`                         // 动作,比如block、captcha等
 | 
			
		||||
 | 
			
		||||
	fullKey string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewHTTPCCConfig() *HTTPCCConfig {
 | 
			
		||||
	return &HTTPCCConfig{
 | 
			
		||||
		WithRequestPath:    false,
 | 
			
		||||
		PeriodSeconds:      10,
 | 
			
		||||
		MaxRequests:        60,
 | 
			
		||||
		MaxConnections:     10,
 | 
			
		||||
		IgnoreCommonFiles:  false,
 | 
			
		||||
		IgnoreCommonAgents: true,
 | 
			
		||||
		Action:             "captcha",
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *HTTPCCConfig) Init() error {
 | 
			
		||||
	// 组合Key
 | 
			
		||||
	var keys = []string{"${remoteAddr}"}
 | 
			
		||||
	if this.WithRequestPath {
 | 
			
		||||
		keys = append(keys, "${requestPath}")
 | 
			
		||||
	}
 | 
			
		||||
	this.fullKey = strings.Join(keys, "@")
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *HTTPCCConfig) Key() string {
 | 
			
		||||
	return this.fullKey
 | 
			
		||||
}
 | 
			
		||||
@@ -49,8 +49,9 @@ type HTTPWebConfig struct {
 | 
			
		||||
	RequestLimit   *HTTPRequestLimitConfig   `yaml:"requestLimit" json:"requestLimit"`     // 并发请求限制
 | 
			
		||||
	RequestScripts *HTTPRequestScriptsConfig `yaml:"requestScripts" json:"requestScripts"` // HTTP请求相关脚本
 | 
			
		||||
 | 
			
		||||
	// UAM
 | 
			
		||||
	// UAM, CC ...
 | 
			
		||||
	UAM *UAMConfig `yaml:"uam" json:"uam"`
 | 
			
		||||
	CC  *UAMConfig `yaml:"cc" json:"cc"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *HTTPWebConfig) Init() error {
 | 
			
		||||
@@ -284,6 +285,14 @@ func (this *HTTPWebConfig) Init() error {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// cc
 | 
			
		||||
	if this.CC != nil {
 | 
			
		||||
		err := this.CC.Init()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// user agent
 | 
			
		||||
	if this.UserAgent != nil {
 | 
			
		||||
		err := this.UserAgent.Init()
 | 
			
		||||
 
 | 
			
		||||
@@ -103,3 +103,16 @@ func (this *HTTPHeaderConfig) Init() error {
 | 
			
		||||
func (this *HTTPHeaderConfig) HasVariables() bool {
 | 
			
		||||
	return this.hasVariables
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Match 判断是否匹配状态码
 | 
			
		||||
func (this *HTTPHeaderConfig) Match(statusCode int) bool {
 | 
			
		||||
	if !this.IsOn {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if this.Status == nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return this.Status.Match(statusCode)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										66
									
								
								pkg/serverconfigs/shared/url_pattern.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								pkg/serverconfigs/shared/url_pattern.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
			
		||||
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
 | 
			
		||||
 | 
			
		||||
package shared
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type URLPatternType = string
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	URLPatternTypeWildcard URLPatternType = "wildcard" // 通配符
 | 
			
		||||
	URLPatternTypeRegexp   URLPatternType = "regexp"   // 正则表达式
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type URLPattern struct {
 | 
			
		||||
	Type    URLPatternType `yaml:"type" json:"type"`
 | 
			
		||||
	Pattern string         `yaml:"pattern" json:"pattern"`
 | 
			
		||||
 | 
			
		||||
	reg *regexp.Regexp
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *URLPattern) Init() error {
 | 
			
		||||
	if len(this.Pattern) == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch this.Type {
 | 
			
		||||
	case URLPatternTypeWildcard:
 | 
			
		||||
		// 只支持星号
 | 
			
		||||
		var pieces = strings.Split(this.Pattern, "*")
 | 
			
		||||
		for index, piece := range pieces {
 | 
			
		||||
			pieces[index] = regexp.QuoteMeta(piece)
 | 
			
		||||
		}
 | 
			
		||||
		reg, err := regexp.Compile("(?i)" /** 大小写不敏感 **/ + strings.Join(pieces, "(.*)"))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		this.reg = reg
 | 
			
		||||
	case URLPatternTypeRegexp:
 | 
			
		||||
		var pattern = this.Pattern
 | 
			
		||||
		if !strings.HasPrefix(pattern, "(?i)") { // 大小写不敏感
 | 
			
		||||
			pattern = "(?i)" + pattern
 | 
			
		||||
		}
 | 
			
		||||
		reg, err := regexp.Compile(pattern)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return errors.New("compile '" + pattern + "' failed: " + err.Error())
 | 
			
		||||
		}
 | 
			
		||||
		this.reg = reg
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *URLPattern) Match(url string) bool {
 | 
			
		||||
	if len(this.Pattern) == 0 && len(url) == 0 {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if this.reg != nil {
 | 
			
		||||
		return this.reg.MatchString(url)
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										93
									
								
								pkg/serverconfigs/shared/url_pattern_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								pkg/serverconfigs/shared/url_pattern_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,93 @@
 | 
			
		||||
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
 | 
			
		||||
 | 
			
		||||
package shared_test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
 | 
			
		||||
	"github.com/iwind/TeaGo/assert"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestURLPattern_Match(t *testing.T) {
 | 
			
		||||
	var a = assert.NewAssertion(t)
 | 
			
		||||
 | 
			
		||||
	type unitTest struct {
 | 
			
		||||
		patternType string
 | 
			
		||||
		pattern     string
 | 
			
		||||
		url         string
 | 
			
		||||
		result      bool
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, ut := range []*unitTest{
 | 
			
		||||
		{
 | 
			
		||||
			patternType: "wildcard",
 | 
			
		||||
			pattern:     "*",
 | 
			
		||||
			url:         "https://example.com",
 | 
			
		||||
			result:      true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			patternType: "wildcard",
 | 
			
		||||
			pattern:     "https://example*",
 | 
			
		||||
			url:         "https://example.com",
 | 
			
		||||
			result:      true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			patternType: "wildcard",
 | 
			
		||||
			pattern:     "*com",
 | 
			
		||||
			url:         "https://example.com",
 | 
			
		||||
			result:      true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			patternType: "wildcard",
 | 
			
		||||
			pattern:     "*COM",
 | 
			
		||||
			url:         "https://example.com",
 | 
			
		||||
			result:      true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			patternType: "wildcard",
 | 
			
		||||
			pattern:     "http://*",
 | 
			
		||||
			url:         "https://example.com",
 | 
			
		||||
			result:      false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			patternType: "regexp",
 | 
			
		||||
			pattern:     ".*",
 | 
			
		||||
			url:         "https://example.com",
 | 
			
		||||
			result:      true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			patternType: "regexp",
 | 
			
		||||
			pattern:     "^https://.*",
 | 
			
		||||
			url:         "https://example.com",
 | 
			
		||||
			result:      true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			patternType: "regexp",
 | 
			
		||||
			pattern:     "^https://.*EXAMPLE.COM",
 | 
			
		||||
			url:         "https://example.com",
 | 
			
		||||
			result:      true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			patternType: "regexp",
 | 
			
		||||
			pattern:     "(?i)https://.*EXAMPLE.COM/\\d+",
 | 
			
		||||
			url:         "https://example.com/123456",
 | 
			
		||||
			result:      true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			patternType: "regexp",
 | 
			
		||||
			pattern:     "(?i)https://.*EXAMPLE.COM/\\d+$",
 | 
			
		||||
			url:         "https://example.com/123456/789",
 | 
			
		||||
			result:      false,
 | 
			
		||||
		},
 | 
			
		||||
	} {
 | 
			
		||||
		var p = &shared.URLPattern{
 | 
			
		||||
			Type:    ut.patternType,
 | 
			
		||||
			Pattern: ut.pattern,
 | 
			
		||||
		}
 | 
			
		||||
		err := p.Init()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
		a.IsTrue(p.Match(ut.url) == ut.result)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -2,12 +2,55 @@
 | 
			
		||||
 | 
			
		||||
package serverconfigs
 | 
			
		||||
 | 
			
		||||
import "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
 | 
			
		||||
 | 
			
		||||
// UAMConfig UAM配置
 | 
			
		||||
type UAMConfig struct {
 | 
			
		||||
	IsPrior bool `yaml:"isPrior" json:"isPrior"`
 | 
			
		||||
	IsOn    bool `yaml:"isOn" json:"isOn"`
 | 
			
		||||
 | 
			
		||||
	OnlyURLPatterns   []*shared.URLPattern `yaml:"onlyURLPatterns" json:"onlyURLPatterns"`     // 仅限的URL
 | 
			
		||||
	ExceptURLPatterns []*shared.URLPattern `yaml:"exceptURLPatterns" json:"exceptURLPatterns"` // 排除的URL
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *UAMConfig) 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 *UAMConfig) 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
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user