mirror of
https://github.com/TeaOSLab/EdgeCommon.git
synced 2025-11-27 06:10: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"` // 并发请求限制
|
RequestLimit *HTTPRequestLimitConfig `yaml:"requestLimit" json:"requestLimit"` // 并发请求限制
|
||||||
RequestScripts *HTTPRequestScriptsConfig `yaml:"requestScripts" json:"requestScripts"` // HTTP请求相关脚本
|
RequestScripts *HTTPRequestScriptsConfig `yaml:"requestScripts" json:"requestScripts"` // HTTP请求相关脚本
|
||||||
|
|
||||||
// UAM
|
// UAM, CC ...
|
||||||
UAM *UAMConfig `yaml:"uam" json:"uam"`
|
UAM *UAMConfig `yaml:"uam" json:"uam"`
|
||||||
|
CC *UAMConfig `yaml:"cc" json:"cc"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *HTTPWebConfig) Init() error {
|
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
|
// user agent
|
||||||
if this.UserAgent != nil {
|
if this.UserAgent != nil {
|
||||||
err := this.UserAgent.Init()
|
err := this.UserAgent.Init()
|
||||||
|
|||||||
@@ -103,3 +103,16 @@ func (this *HTTPHeaderConfig) Init() error {
|
|||||||
func (this *HTTPHeaderConfig) HasVariables() bool {
|
func (this *HTTPHeaderConfig) HasVariables() bool {
|
||||||
return this.hasVariables
|
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
|
package serverconfigs
|
||||||
|
|
||||||
|
import "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||||
|
|
||||||
// UAMConfig UAM配置
|
// UAMConfig UAM配置
|
||||||
type UAMConfig struct {
|
type UAMConfig struct {
|
||||||
IsPrior bool `yaml:"isPrior" json:"isPrior"`
|
IsPrior bool `yaml:"isPrior" json:"isPrior"`
|
||||||
IsOn bool `yaml:"isOn" json:"isOn"`
|
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 {
|
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
|
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