diff --git a/internal/nodes/http_request.go b/internal/nodes/http_request.go index 0ffae99..d742596 100644 --- a/internal/nodes/http_request.go +++ b/internal/nodes/http_request.go @@ -514,6 +514,12 @@ func (this *HTTPRequest) Format(source string) string { return this.requestRemoteUser() case "requestURI", "requestUri": return this.rawURI + case "requestURL": + var scheme = "http" + if this.IsHTTPS { + scheme = "https" + } + return scheme + "://" + this.Host + this.rawURI case "requestPath": return this.requestPath() case "requestPathExtension": @@ -1201,7 +1207,7 @@ func (this *HTTPRequest) canIgnore(err error) bool { } // HTTP内部错误 - if strings.HasPrefix(err.Error(), "http:") || strings.HasPrefix(err.Error(), "http2:") { + if strings.HasPrefix(err.Error(), "http:") || strings.HasPrefix(err.Error(), "http2:") { return true } diff --git a/internal/ttlcache/piece.go b/internal/ttlcache/piece.go index 4c0da96..4349e29 100644 --- a/internal/ttlcache/piece.go +++ b/internal/ttlcache/piece.go @@ -30,7 +30,7 @@ func (this *Piece) Add(key uint64, item *Item) () { func (this *Piece) IncreaseInt64(key uint64, delta int64, expiredAt int64) (result int64) { this.locker.Lock() item, ok := this.m[key] - if ok { + if ok && item.expiredAt > time.Now().Unix() { result = types.Int64(item.Value) + delta item.Value = result item.expiredAt = expiredAt diff --git a/internal/waf/checkpoints/cc2.go b/internal/waf/checkpoints/cc2.go new file mode 100644 index 0000000..9d7d122 --- /dev/null +++ b/internal/waf/checkpoints/cc2.go @@ -0,0 +1,48 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package checkpoints + +import ( + "github.com/TeaOSLab/EdgeNode/internal/ttlcache" + "github.com/TeaOSLab/EdgeNode/internal/waf/requests" + "github.com/iwind/TeaGo/maps" + "github.com/iwind/TeaGo/types" + "strings" + "time" +) + +var ccCache = ttlcache.NewCache(ttlcache.NewPiecesOption(32)) + +// CC2Checkpoint 新的CC +type CC2Checkpoint struct { + Checkpoint +} + +func (this *CC2Checkpoint) RequestValue(req requests.Request, param string, options maps.Map) (value interface{}, sysErr error, userErr error) { + var keys = options.GetSlice("keys") + var keyValues = []string{} + for _, key := range keys { + keyValues = append(keyValues, req.Format(types.String(key))) + } + if len(keyValues) == 0 { + return + } + + var period = options.GetInt64("period") + if period <= 0 { + period = 60 + } + + var threshold = options.GetInt64("threshold") + if threshold <= 0 { + threshold = 1000 + } + + value = ccCache.IncreaseInt64("WAF-CC-"+strings.Join(keyValues, "@"), 1, time.Now().Unix()+period) + + return +} + +func (this *CC2Checkpoint) ResponseValue(req requests.Request, resp *requests.Response, param string, options maps.Map) (value interface{}, sysErr error, userErr error) { + return +} diff --git a/internal/waf/checkpoints/utils.go b/internal/waf/checkpoints/utils.go index 6d79e13..9054af0 100644 --- a/internal/waf/checkpoints/utils.go +++ b/internal/waf/checkpoints/utils.go @@ -185,12 +185,19 @@ var AllCheckpoints = []*CheckpointDefinition{ Instance: new(RequestHeaderCheckpoint), }, { - Name: "CC统计", + Name: "CC统计(旧)", Prefix: "cc", Description: "统计某段时间段内的请求信息", HasParams: true, Instance: new(CCCheckpoint), }, + { + Name: "CC统计(新)", + Prefix: "cc2", + Description: "统计某段时间段内的请求信息", + HasParams: true, + Instance: new(CC2Checkpoint), + }, { Name: "通用响应Header长度限制", Prefix: "responseGeneralHeaderLength", diff --git a/internal/waf/requests/request.go b/internal/waf/requests/request.go index b2f35a9..5fb63fc 100644 --- a/internal/waf/requests/request.go +++ b/internal/waf/requests/request.go @@ -25,4 +25,7 @@ type Request interface { // WAFServerId 服务ID WAFServerId() int64 + + // Format 格式化变量 + Format(string) string } diff --git a/internal/waf/requests/test_request.go b/internal/waf/requests/test_request.go index 4682d37..2a9ca48 100644 --- a/internal/waf/requests/test_request.go +++ b/internal/waf/requests/test_request.go @@ -65,3 +65,7 @@ func (this *TestRequest) WAFRestoreBody(data []byte) { func (this *TestRequest) WAFServerId() int64 { return 0 } + +func (this *TestRequest) Format(s string) string { + return s +}