5秒盾支持例外URL和限制URL

This commit is contained in:
GoEdgeLab
2023-03-06 21:49:11 +08:00
parent a7f5980de8
commit 5bd22ba4c3
6 changed files with 272 additions and 1 deletions

View 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
}

View File

@@ -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()

View File

@@ -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)
}

View 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
}

View 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)
}
}

View File

@@ -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
}