WAF cc2尝试使用指纹统计方法

This commit is contained in:
GoEdgeLab
2023-03-08 16:59:44 +08:00
parent 10ca7321aa
commit 09806b75e7
8 changed files with 103 additions and 1 deletions

View File

@@ -17,6 +17,7 @@ type BaseClientConn struct {
hasLimit bool hasLimit bool
isPersistent bool // 是否为持久化连接 isPersistent bool // 是否为持久化连接
fingerprint []byte
isClosed bool isClosed bool
@@ -128,3 +129,13 @@ func (this *BaseClientConn) SetLinger(seconds int) error {
func (this *BaseClientConn) SetIsPersistent(isPersistent bool) { func (this *BaseClientConn) SetIsPersistent(isPersistent bool) {
this.isPersistent = isPersistent this.isPersistent = isPersistent
} }
// SetFingerprint 设置指纹信息
func (this *BaseClientConn) SetFingerprint(fingerprint []byte) {
this.fingerprint = fingerprint
}
// Fingerprint 读取指纹信息
func (this *BaseClientConn) Fingerprint() []byte {
return this.fingerprint
}

View File

@@ -26,4 +26,10 @@ type ClientConnInterface interface {
// SetIsPersistent 设置是否为持久化 // SetIsPersistent 设置是否为持久化
SetIsPersistent(isPersistent bool) SetIsPersistent(isPersistent bool)
// SetFingerprint 设置指纹信息
SetFingerprint(fingerprint []byte)
// Fingerprint 读取指纹信息
Fingerprint() []byte
} }

View File

@@ -68,3 +68,17 @@ func (this *ClientTLSConn) SetIsPersistent(isPersistent bool) {
} }
} }
} }
func (this *ClientTLSConn) Fingerprint() []byte {
tlsConn, ok := this.rawConn.(*tls.Conn)
if ok {
var rawConn = tlsConn.NetConn()
if rawConn != nil {
clientConn, ok := rawConn.(*ClientConn)
if ok {
return clientConn.fingerprint
}
}
}
return nil
}

View File

@@ -402,3 +402,17 @@ func (this *HTTPRequest) WAFOnAction(action interface{}) (goNext bool) {
} }
return true return true
} }
func (this *HTTPRequest) WAFFingerprint() []byte {
var requestConn = this.RawReq.Context().Value(HTTPConnContextKey)
if requestConn == nil {
return nil
}
clientConn, ok := requestConn.(ClientConnInterface)
if ok {
return clientConn.Fingerprint()
}
return nil
}

View File

@@ -36,6 +36,15 @@ func (this *BaseListener) buildTLSConfig() *tls.Config {
return &tls.Config{ return &tls.Config{
Certificates: nil, Certificates: nil,
GetConfigForClient: func(clientInfo *tls.ClientHelloInfo) (config *tls.Config, e error) { GetConfigForClient: func(clientInfo *tls.ClientHelloInfo) (config *tls.Config, e error) {
// 指纹信息
var fingerprint = this.calculateFingerprint(clientInfo)
if len(fingerprint) > 0 {
clientConn, ok := clientInfo.Conn.(ClientConnInterface)
if ok {
clientConn.SetFingerprint(fingerprint)
}
}
tlsPolicy, _, err := this.matchSSL(this.helloServerName(clientInfo)) tlsPolicy, _, err := this.matchSSL(this.helloServerName(clientInfo))
if err != nil { if err != nil {
return nil, err return nil, err
@@ -50,6 +59,15 @@ func (this *BaseListener) buildTLSConfig() *tls.Config {
return tlsPolicy.TLSConfig(), nil return tlsPolicy.TLSConfig(), nil
}, },
GetCertificate: func(clientInfo *tls.ClientHelloInfo) (certificate *tls.Certificate, e error) { GetCertificate: func(clientInfo *tls.ClientHelloInfo) (certificate *tls.Certificate, e error) {
// 指纹信息
var fingerprint = this.calculateFingerprint(clientInfo)
if len(fingerprint) > 0 {
clientConn, ok := clientInfo.Conn.(ClientConnInterface)
if ok {
clientConn.SetFingerprint(fingerprint)
}
}
tlsPolicy, cert, err := this.matchSSL(this.helloServerName(clientInfo)) tlsPolicy, cert, err := this.matchSSL(this.helloServerName(clientInfo))
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -0,0 +1,10 @@
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build !plus
package nodes
import "crypto/tls"
func (this *BaseListener) calculateFingerprint(clientInfo *tls.ClientHelloInfo) []byte {
return nil
}

View File

@@ -3,6 +3,7 @@
package checkpoints package checkpoints
import ( import (
"fmt"
"github.com/TeaOSLab/EdgeNode/internal/ttlcache" "github.com/TeaOSLab/EdgeNode/internal/ttlcache"
"github.com/TeaOSLab/EdgeNode/internal/waf/requests" "github.com/TeaOSLab/EdgeNode/internal/waf/requests"
"github.com/TeaOSLab/EdgeNode/internal/zero" "github.com/TeaOSLab/EdgeNode/internal/zero"
@@ -35,7 +36,11 @@ type CC2Checkpoint struct {
func (this *CC2Checkpoint) RequestValue(req requests.Request, param string, options maps.Map, ruleId int64) (value interface{}, hasRequestBody bool, sysErr error, userErr error) { func (this *CC2Checkpoint) RequestValue(req requests.Request, param string, options maps.Map, ruleId int64) (value interface{}, hasRequestBody bool, sysErr error, userErr error) {
var keys = options.GetSlice("keys") var keys = options.GetSlice("keys")
var keyValues = []string{} var keyValues = []string{}
var hasRemoteAddr = false
for _, key := range keys { for _, key := range keys {
if key == "${remoteAddr}" || key == "${rawRemoteAddr}" {
hasRemoteAddr = true
}
keyValues = append(keyValues, req.Format(types.String(key))) keyValues = append(keyValues, req.Format(types.String(key)))
} }
if len(keyValues) == 0 { if len(keyValues) == 0 {
@@ -66,8 +71,29 @@ func (this *CC2Checkpoint) RequestValue(req requests.Request, param string, opti
} }
} }
var expiresAt = time.Now().Unix() + period
var ccKey = "WAF-CC-" + types.String(ruleId) + "-" + strings.Join(keyValues, "@") var ccKey = "WAF-CC-" + types.String(ruleId) + "-" + strings.Join(keyValues, "@")
value = ccCache.IncreaseInt64(ccKey, 1, time.Now().Unix()+period, false) value = ccCache.IncreaseInt64(ccKey, 1, expiresAt, false)
// 基于指纹统计
if hasRemoteAddr {
var fingerprint = req.WAFFingerprint()
if len(fingerprint) > 0 {
var fpKeyValues = []string{}
for _, key := range keys {
if key == "${remoteAddr}" || key == "${rawRemoteAddr}" {
fpKeyValues = append(fpKeyValues, fmt.Sprintf("%x", fingerprint))
continue
}
fpKeyValues = append(fpKeyValues, req.Format(types.String(key)))
}
var fpCCKey = "WAF-CC-" + types.String(ruleId) + "-" + strings.Join(fpKeyValues, "@")
var fpValue = ccCache.IncreaseInt64(fpCCKey, 1, expiresAt, false)
if fpValue > value.(int64) {
value = fpValue
}
}
}
return return
} }

View File

@@ -32,6 +32,9 @@ type Request interface {
// WAFOnAction 动作回调 // WAFOnAction 动作回调
WAFOnAction(action interface{}) (goNext bool) WAFOnAction(action interface{}) (goNext bool)
// WAFFingerprint 读取连接指纹
WAFFingerprint() []byte
// Format 格式化变量 // Format 格式化变量
Format(string) string Format(string) string
} }