WAF标签动作匹配之后可以继续尝试匹配别的分组中的规则集

This commit is contained in:
刘祥超
2022-08-25 16:44:44 +08:00
parent d061876f7e
commit 59d3d6ae4b
17 changed files with 74 additions and 70 deletions

View File

@@ -25,7 +25,7 @@ func (this *AllowAction) WillChange() bool {
return true return true
} }
func (this *AllowAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (allow bool) { func (this *AllowAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (continueRequest bool, goNextSet bool) {
// do nothing // do nothing
return true return true, false
} }

View File

@@ -58,11 +58,11 @@ func (this *BlockAction) WillChange() bool {
return true return true
} }
func (this *BlockAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (allow bool) { func (this *BlockAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (continueRequest bool, goNextSet bool) {
// 加入到黑名单 // 加入到黑名单
var timeout = this.Timeout var timeout = this.Timeout
if timeout <= 0 { if timeout <= 0 {
timeout = 60 // 默认封锁60秒 timeout = 300 // 默认封锁300秒
} }
SharedIPBlackList.RecordIP(IPTypeAll, this.Scope, request.WAFServerId(), request.WAFRemoteIP(), time.Now().Unix()+int64(timeout), waf.Id, waf.UseLocalFirewall, group.Id, set.Id, "") SharedIPBlackList.RecordIP(IPTypeAll, this.Scope, request.WAFServerId(), request.WAFRemoteIP(), time.Now().Unix()+int64(timeout), waf.Id, waf.UseLocalFirewall, group.Id, set.Id, "")
@@ -82,14 +82,14 @@ func (this *BlockAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, reque
req, err := http.NewRequest(http.MethodGet, this.URL, nil) req, err := http.NewRequest(http.MethodGet, this.URL, nil)
if err != nil { if err != nil {
logs.Error(err) logs.Error(err)
return false return false, false
} }
req.Header.Set("User-Agent", teaconst.GlobalProductName+"/"+teaconst.Version) req.Header.Set("User-Agent", teaconst.GlobalProductName+"/"+teaconst.Version)
resp, err := httpClient.Do(req) resp, err := httpClient.Do(req)
if err != nil { if err != nil {
logs.Error(err) logs.Error(err)
return false return false, false
} }
defer func() { defer func() {
_ = resp.Body.Close() _ = resp.Body.Close()
@@ -113,11 +113,11 @@ func (this *BlockAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, reque
data, err := os.ReadFile(path) data, err := os.ReadFile(path)
if err != nil { if err != nil {
logs.Error(err) logs.Error(err)
return false return false, false
} }
_, _ = writer.Write(data) _, _ = writer.Write(data)
} }
return false return false, false
} }
if len(this.Body) > 0 { if len(this.Body) > 0 {
_, _ = writer.Write([]byte(this.Body)) _, _ = writer.Write([]byte(this.Body))
@@ -126,5 +126,5 @@ func (this *BlockAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, reque
} }
} }
return false return false, false
} }

View File

@@ -98,10 +98,10 @@ func (this *CaptchaAction) WillChange() bool {
return true return true
} }
func (this *CaptchaAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, req requests.Request, writer http.ResponseWriter) (allow bool) { func (this *CaptchaAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, req requests.Request, writer http.ResponseWriter) (continueRequest bool, goNextSet bool) {
// 是否在白名单中 // 是否在白名单中
if SharedIPWhiteList.Contains("set:"+types.String(set.Id), this.Scope, req.WAFServerId(), req.WAFRemoteIP()) { if SharedIPWhiteList.Contains("set:"+types.String(set.Id), this.Scope, req.WAFServerId(), req.WAFRemoteIP()) {
return true return true, false
} }
var refURL = req.WAFRaw().URL.String() var refURL = req.WAFRaw().URL.String()
@@ -128,7 +128,7 @@ func (this *CaptchaAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, req
info, err := utils.SimpleEncryptMap(captchaConfig) info, err := utils.SimpleEncryptMap(captchaConfig)
if err != nil { if err != nil {
remotelogs.Error("WAF_CAPTCHA_ACTION", "encode captcha config failed: "+err.Error()) remotelogs.Error("WAF_CAPTCHA_ACTION", "encode captcha config failed: "+err.Error())
return true return true, false
} }
// 占用一次失败次数 // 占用一次失败次数
@@ -136,5 +136,5 @@ func (this *CaptchaAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, req
http.Redirect(writer, req.WAFRaw(), CaptchaPath+"?info="+url.QueryEscape(info), http.StatusTemporaryRedirect) http.Redirect(writer, req.WAFRaw(), CaptchaPath+"?info="+url.QueryEscape(info), http.StatusTemporaryRedirect)
return false return false, false
} }

View File

@@ -41,15 +41,15 @@ func (this *Get302Action) WillChange() bool {
return true return true
} }
func (this *Get302Action) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (allow bool) { func (this *Get302Action) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (continueRequest bool, goNextSet bool) {
// 仅限于Get // 仅限于Get
if request.WAFRaw().Method != http.MethodGet { if request.WAFRaw().Method != http.MethodGet {
return true return true, false
} }
// 是否已经在白名单中 // 是否已经在白名单中
if SharedIPWhiteList.Contains("set:"+types.String(set.Id), this.Scope, request.WAFServerId(), request.WAFRemoteIP()) { if SharedIPWhiteList.Contains("set:"+types.String(set.Id), this.Scope, request.WAFServerId(), request.WAFRemoteIP()) {
return true return true, false
} }
var m = maps.Map{ var m = maps.Map{
@@ -64,7 +64,7 @@ func (this *Get302Action) Perform(waf *WAF, group *RuleGroup, set *RuleSet, requ
info, err := utils.SimpleEncryptMap(m) info, err := utils.SimpleEncryptMap(m)
if err != nil { if err != nil {
remotelogs.Error("WAF_GET_302_ACTION", "encode info failed: "+err.Error()) remotelogs.Error("WAF_GET_302_ACTION", "encode info failed: "+err.Error())
return true return true, false
} }
http.Redirect(writer, request.WAFRaw(), Get302Path+"?info="+url.QueryEscape(info), http.StatusFound) http.Redirect(writer, request.WAFRaw(), Get302Path+"?info="+url.QueryEscape(info), http.StatusFound)
@@ -73,5 +73,5 @@ func (this *Get302Action) Perform(waf *WAF, group *RuleGroup, set *RuleSet, requ
_ = this.CloseConn(writer) _ = this.CloseConn(writer)
} }
return false return false, false
} }

View File

@@ -1,8 +1,8 @@
package waf package waf
import ( import (
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
"github.com/TeaOSLab/EdgeNode/internal/waf/requests" "github.com/TeaOSLab/EdgeNode/internal/waf/requests"
"github.com/iwind/TeaGo/logs"
"github.com/iwind/TeaGo/types" "github.com/iwind/TeaGo/types"
"net/http" "net/http"
) )
@@ -29,20 +29,20 @@ func (this *GoGroupAction) WillChange() bool {
return true return true
} }
func (this *GoGroupAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (allow bool) { func (this *GoGroupAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (continueRequest bool, goNextSet bool) {
nextGroup := waf.FindRuleGroup(types.Int64(this.GroupId)) nextGroup := waf.FindRuleGroup(types.Int64(this.GroupId))
if nextGroup == nil || !nextGroup.IsOn { if nextGroup == nil || !nextGroup.IsOn {
return true return true, true
} }
b, _, nextSet, err := nextGroup.MatchRequest(request) b, _, nextSet, err := nextGroup.MatchRequest(request)
if err != nil { if err != nil {
logs.Error(err) remotelogs.Error("WAF", "GO_GROUP_ACTION: "+err.Error())
return true return true, false
} }
if !b { if !b {
return true return true, false
} }
return nextSet.PerformActions(waf, nextGroup, request, writer) return nextSet.PerformActions(waf, nextGroup, request, writer)

View File

@@ -1,8 +1,8 @@
package waf package waf
import ( import (
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
"github.com/TeaOSLab/EdgeNode/internal/waf/requests" "github.com/TeaOSLab/EdgeNode/internal/waf/requests"
"github.com/iwind/TeaGo/logs"
"github.com/iwind/TeaGo/types" "github.com/iwind/TeaGo/types"
"net/http" "net/http"
) )
@@ -30,23 +30,23 @@ func (this *GoSetAction) WillChange() bool {
return true return true
} }
func (this *GoSetAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (allow bool) { func (this *GoSetAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (continueRequest bool, goNextSet bool) {
nextGroup := waf.FindRuleGroup(types.Int64(this.GroupId)) nextGroup := waf.FindRuleGroup(types.Int64(this.GroupId))
if nextGroup == nil || !nextGroup.IsOn { if nextGroup == nil || !nextGroup.IsOn {
return true return true, true
} }
nextSet := nextGroup.FindRuleSet(types.Int64(this.SetId)) nextSet := nextGroup.FindRuleSet(types.Int64(this.SetId))
if nextSet == nil || !nextSet.IsOn { if nextSet == nil || !nextSet.IsOn {
return true return true, true
} }
b, _, err := nextSet.MatchRequest(request) b, _, err := nextSet.MatchRequest(request)
if err != nil { if err != nil {
logs.Error(err) remotelogs.Error("WAF", "GO_GROUP_ACTION: "+err.Error())
return true return true, false
} }
if !b { if !b {
return true return true, false
} }
return nextSet.PerformActions(waf, nextGroup, request, writer) return nextSet.PerformActions(waf, nextGroup, request, writer)
} }

View File

@@ -27,5 +27,5 @@ type ActionInterface interface {
WillChange() bool WillChange() bool
// Perform the action // Perform the action
Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (allow bool) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (continueRequest bool, goNextSet bool)
} }

View File

@@ -41,15 +41,15 @@ func (this *JSCookieAction) WillChange() bool {
return true return true
} }
func (this *JSCookieAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, req requests.Request, writer http.ResponseWriter) (allow bool) { func (this *JSCookieAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, req requests.Request, writer http.ResponseWriter) (continueRequest bool, goNextSet bool) {
// 是否在白名单中 // 是否在白名单中
if SharedIPWhiteList.Contains("set:"+types.String(set.Id), this.Scope, req.WAFServerId(), req.WAFRemoteIP()) { if SharedIPWhiteList.Contains("set:"+types.String(set.Id), this.Scope, req.WAFServerId(), req.WAFRemoteIP()) {
return true return true, false
} }
nodeConfig, err := nodeconfigs.SharedNodeConfig() nodeConfig, err := nodeconfigs.SharedNodeConfig()
if err != nil { if err != nil {
return true return true, false
} }
var life = this.Life var life = this.Life
@@ -65,7 +65,7 @@ func (this *JSCookieAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, re
if len(cookieValue) > 10 { if len(cookieValue) > 10 {
var timestamp = cookieValue[:10] var timestamp = cookieValue[:10]
if types.Int64(timestamp) >= time.Now().Unix()-int64(life) && fmt.Sprintf("%x", md5.Sum([]byte(timestamp+"@"+nodeConfig.NodeId))) == cookieValue[10:] { if types.Int64(timestamp) >= time.Now().Unix()-int64(life) && fmt.Sprintf("%x", md5.Sum([]byte(timestamp+"@"+nodeConfig.NodeId))) == cookieValue[10:] {
return true return true, false
} }
} }
} }
@@ -94,7 +94,7 @@ window.location.reload();
// 记录失败次数 // 记录失败次数
this.increaseFails(req, waf.Id, group.Id, set.Id) this.increaseFails(req, waf.Id, group.Id, set.Id)
return false return false, false
} }
func (this *JSCookieAction) increaseFails(req requests.Request, policyId int64, groupId int64, setId int64) (goNext bool) { func (this *JSCookieAction) increaseFails(req requests.Request, policyId int64, groupId int64, setId int64) (goNext bool) {

View File

@@ -25,6 +25,6 @@ func (this *LogAction) WillChange() bool {
return false return false
} }
func (this *LogAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (allow bool) { func (this *LogAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (continueRequest bool, goNextSet bool) {
return true return true, false
} }

View File

@@ -71,7 +71,7 @@ func (this *NotifyAction) WillChange() bool {
} }
// Perform the action // Perform the action
func (this *NotifyAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (allow bool) { func (this *NotifyAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (continueRequest bool, goNextSet bool) {
select { select {
case notifyChan <- &notifyTask{ case notifyChan <- &notifyTask{
ServerId: request.WAFServerId(), ServerId: request.WAFServerId(),
@@ -84,5 +84,5 @@ func (this *NotifyAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, requ
} }
return true return true, false
} }

View File

@@ -32,10 +32,10 @@ func (this *PageAction) WillChange() bool {
} }
// Perform the action // Perform the action
func (this *PageAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (allow bool) { func (this *PageAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (continueRequest bool, goNextSet bool) {
writer.Header().Set("Content-Type", "text/html; charset=utf-8") writer.Header().Set("Content-Type", "text/html; charset=utf-8")
writer.WriteHeader(this.Status) writer.WriteHeader(this.Status)
_, _ = writer.Write([]byte(request.Format(this.Body))) _, _ = writer.Write([]byte(request.Format(this.Body)))
return false return false, false
} }

View File

@@ -33,17 +33,17 @@ func (this *Post307Action) WillChange() bool {
return true return true
} }
func (this *Post307Action) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (allow bool) { func (this *Post307Action) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (continueRequest bool, goNextSet bool) {
var cookieName = "WAF_VALIDATOR_ID" var cookieName = "WAF_VALIDATOR_ID"
// 仅限于POST // 仅限于POST
if request.WAFRaw().Method != http.MethodPost { if request.WAFRaw().Method != http.MethodPost {
return true return true, false
} }
// 是否已经在白名单中 // 是否已经在白名单中
if SharedIPWhiteList.Contains("set:"+types.String(set.Id), this.Scope, request.WAFServerId(), request.WAFRemoteIP()) { if SharedIPWhiteList.Contains("set:"+types.String(set.Id), this.Scope, request.WAFServerId(), request.WAFRemoteIP()) {
return true return true, false
} }
// 判断是否有Cookie // 判断是否有Cookie
@@ -57,7 +57,7 @@ func (this *Post307Action) Perform(waf *WAF, group *RuleGroup, set *RuleSet, req
} }
var setId = m.GetString("setId") var setId = m.GetString("setId")
SharedIPWhiteList.RecordIP("set:"+setId, this.Scope, request.WAFServerId(), request.WAFRemoteIP(), time.Now().Unix()+life, m.GetInt64("policyId"), false, m.GetInt64("groupId"), m.GetInt64("setId"), "") SharedIPWhiteList.RecordIP("set:"+setId, this.Scope, request.WAFServerId(), request.WAFRemoteIP(), time.Now().Unix()+life, m.GetInt64("policyId"), false, m.GetInt64("groupId"), m.GetInt64("setId"), "")
return true return true, false
} }
} }
@@ -73,7 +73,7 @@ func (this *Post307Action) Perform(waf *WAF, group *RuleGroup, set *RuleSet, req
info, err := utils.SimpleEncryptMap(m) info, err := utils.SimpleEncryptMap(m)
if err != nil { if err != nil {
remotelogs.Error("WAF_POST_302_ACTION", "encode info failed: "+err.Error()) remotelogs.Error("WAF_POST_302_ACTION", "encode info failed: "+err.Error())
return true return true, false
} }
// 设置Cookie // 设置Cookie
@@ -90,5 +90,5 @@ func (this *Post307Action) Perform(waf *WAF, group *RuleGroup, set *RuleSet, req
_ = this.CloseConn(writer) _ = this.CloseConn(writer)
} }
return false return false, false
} }

View File

@@ -99,10 +99,10 @@ func (this *RecordIPAction) WillChange() bool {
return this.Type == "black" return this.Type == "black"
} }
func (this *RecordIPAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (allow bool) { func (this *RecordIPAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (continueRequest bool, goNextSet bool) {
// 是否在本地白名单中 // 是否在本地白名单中
if SharedIPWhiteList.Contains("set:"+types.String(set.Id), this.Scope, request.WAFServerId(), request.WAFRemoteIP()) { if SharedIPWhiteList.Contains("set:"+types.String(set.Id), this.Scope, request.WAFServerId(), request.WAFRemoteIP()) {
return true return true, false
} }
timeout := this.Timeout timeout := this.Timeout
@@ -147,5 +147,5 @@ func (this *RecordIPAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, re
} }
} }
return this.Type != "black" return this.Type != "black", false
} }

View File

@@ -27,6 +27,6 @@ func (this *TagAction) WillChange() bool {
return false return false
} }
func (this *TagAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (allow bool) { func (this *TagAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (continueRequest bool, goNextSet bool) {
return true return true, true
} }

View File

@@ -667,7 +667,7 @@ func (this *Rule) execFilter(value interface{}) interface{} {
} }
value, goNext, err = filterInstance.Do(value, filter.Options) value, goNext, err = filterInstance.Do(value, filter.Options)
if err != nil { if err != nil {
remotelogs.Println("WAF", "filter error: "+err.Error()) remotelogs.Error("WAF", "filter error: "+err.Error())
break break
} }
if !goNext { if !goNext {

View File

@@ -136,19 +136,19 @@ func (this *RuleSet) ActionCodes() []string {
return this.actionCodes return this.actionCodes
} }
func (this *RuleSet) PerformActions(waf *WAF, group *RuleGroup, req requests.Request, writer http.ResponseWriter) bool { func (this *RuleSet) PerformActions(waf *WAF, group *RuleGroup, req requests.Request, writer http.ResponseWriter) (continueRequest bool, goNextSet bool) {
if len(waf.Mode) != 0 && waf.Mode != firewallconfigs.FirewallModeDefend { if len(waf.Mode) != 0 && waf.Mode != firewallconfigs.FirewallModeDefend {
return true return true, false
} }
// 先执行allow // 先执行allow
for _, instance := range this.actionInstances { for _, instance := range this.actionInstances {
if !instance.WillChange() { if !instance.WillChange() {
goNext := req.WAFOnAction(instance) continueRequest = req.WAFOnAction(instance)
if !goNext { if !continueRequest {
return false return false, false
} }
instance.Perform(waf, group, this, req, writer) _, goNextSet = instance.Perform(waf, group, this, req, writer)
} }
} }
@@ -156,15 +156,15 @@ func (this *RuleSet) PerformActions(waf *WAF, group *RuleGroup, req requests.Req
for _, instance := range this.actionInstances { for _, instance := range this.actionInstances {
// 只执行第一个可能改变请求的动作,其余的都会被忽略 // 只执行第一个可能改变请求的动作,其余的都会被忽略
if instance.WillChange() { if instance.WillChange() {
goNext := req.WAFOnAction(instance) continueRequest = req.WAFOnAction(instance)
if !goNext { if !continueRequest {
return false return false, false
} }
return instance.Perform(waf, group, this, req, writer) return instance.Perform(waf, group, this, req, writer)
} }
} }
return true return true, goNextSet
} }
func (this *RuleSet) MatchRequest(req requests.Request) (b bool, hasRequestBody bool, err error) { func (this *RuleSet) MatchRequest(req requests.Request) (b bool, hasRequestBody bool, err error) {

View File

@@ -241,7 +241,7 @@ func (this *WAF) MoveOutboundRuleGroup(fromIndex int, toIndex int) {
this.Outbound = result this.Outbound = result
} }
func (this *WAF) MatchRequest(req requests.Request, writer http.ResponseWriter) (goNext bool, hasRequestBody bool, group *RuleGroup, set *RuleSet, err error) { func (this *WAF) MatchRequest(req requests.Request, writer http.ResponseWriter) (goNext bool, hasRequestBody bool, group *RuleGroup, sets *RuleSet, err error) {
if !this.hasInboundRules { if !this.hasInboundRules {
return true, hasRequestBody, nil, nil, nil return true, hasRequestBody, nil, nil, nil
} }
@@ -272,8 +272,10 @@ func (this *WAF) MatchRequest(req requests.Request, writer http.ResponseWriter)
return true, hasRequestBody, nil, nil, err return true, hasRequestBody, nil, nil, err
} }
if b { if b {
goNext = set.PerformActions(this, group, req, writer) continueRequest, goNextSet := set.PerformActions(this, group, req, writer)
return goNext, hasRequestBody, group, set, nil if !goNextSet {
return continueRequest, hasRequestBody, group, set, nil
}
} }
} }
return true, hasRequestBody, nil, nil, nil return true, hasRequestBody, nil, nil, nil
@@ -296,8 +298,10 @@ func (this *WAF) MatchResponse(req requests.Request, rawResp *http.Response, wri
return true, hasRequestBody, nil, nil, err return true, hasRequestBody, nil, nil, err
} }
if b { if b {
goNext = set.PerformActions(this, group, req, writer) continueRequest, goNextSet := set.PerformActions(this, group, req, writer)
return goNext, hasRequestBody, group, set, nil if !goNextSet {
return continueRequest, hasRequestBody, group, set, nil
}
} }
} }
return true, hasRequestBody, nil, nil, nil return true, hasRequestBody, nil, nil, nil