diff --git a/internal/waf/action_allow.go b/internal/waf/action_allow.go index 2f55770..165a440 100644 --- a/internal/waf/action_allow.go +++ b/internal/waf/action_allow.go @@ -25,7 +25,7 @@ func (this *AllowAction) WillChange() bool { 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 - return true + return true, false } diff --git a/internal/waf/action_block.go b/internal/waf/action_block.go index 09ed741..136f507 100644 --- a/internal/waf/action_block.go +++ b/internal/waf/action_block.go @@ -58,11 +58,11 @@ func (this *BlockAction) WillChange() bool { 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 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, "") @@ -82,14 +82,14 @@ func (this *BlockAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, reque req, err := http.NewRequest(http.MethodGet, this.URL, nil) if err != nil { logs.Error(err) - return false + return false, false } req.Header.Set("User-Agent", teaconst.GlobalProductName+"/"+teaconst.Version) resp, err := httpClient.Do(req) if err != nil { logs.Error(err) - return false + return false, false } defer func() { _ = resp.Body.Close() @@ -113,11 +113,11 @@ func (this *BlockAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, reque data, err := os.ReadFile(path) if err != nil { logs.Error(err) - return false + return false, false } _, _ = writer.Write(data) } - return false + return false, false } if len(this.Body) > 0 { _, _ = 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 } diff --git a/internal/waf/action_captcha.go b/internal/waf/action_captcha.go index cd565ae..623e59d 100644 --- a/internal/waf/action_captcha.go +++ b/internal/waf/action_captcha.go @@ -98,10 +98,10 @@ func (this *CaptchaAction) WillChange() bool { 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()) { - return true + return true, false } 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) if err != nil { 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) - return false + return false, false } diff --git a/internal/waf/action_get_302.go b/internal/waf/action_get_302.go index fe1d432..021176c 100644 --- a/internal/waf/action_get_302.go +++ b/internal/waf/action_get_302.go @@ -41,15 +41,15 @@ func (this *Get302Action) WillChange() bool { 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 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()) { - return true + return true, false } var m = maps.Map{ @@ -64,7 +64,7 @@ func (this *Get302Action) Perform(waf *WAF, group *RuleGroup, set *RuleSet, requ info, err := utils.SimpleEncryptMap(m) if err != nil { 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) @@ -73,5 +73,5 @@ func (this *Get302Action) Perform(waf *WAF, group *RuleGroup, set *RuleSet, requ _ = this.CloseConn(writer) } - return false + return false, false } diff --git a/internal/waf/action_go_group.go b/internal/waf/action_go_group.go index 252fd35..1c61265 100644 --- a/internal/waf/action_go_group.go +++ b/internal/waf/action_go_group.go @@ -1,8 +1,8 @@ package waf import ( + "github.com/TeaOSLab/EdgeNode/internal/remotelogs" "github.com/TeaOSLab/EdgeNode/internal/waf/requests" - "github.com/iwind/TeaGo/logs" "github.com/iwind/TeaGo/types" "net/http" ) @@ -29,20 +29,20 @@ func (this *GoGroupAction) WillChange() bool { 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)) if nextGroup == nil || !nextGroup.IsOn { - return true + return true, true } b, _, nextSet, err := nextGroup.MatchRequest(request) if err != nil { - logs.Error(err) - return true + remotelogs.Error("WAF", "GO_GROUP_ACTION: "+err.Error()) + return true, false } if !b { - return true + return true, false } return nextSet.PerformActions(waf, nextGroup, request, writer) diff --git a/internal/waf/action_go_set.go b/internal/waf/action_go_set.go index 76cf84a..507554a 100644 --- a/internal/waf/action_go_set.go +++ b/internal/waf/action_go_set.go @@ -1,8 +1,8 @@ package waf import ( + "github.com/TeaOSLab/EdgeNode/internal/remotelogs" "github.com/TeaOSLab/EdgeNode/internal/waf/requests" - "github.com/iwind/TeaGo/logs" "github.com/iwind/TeaGo/types" "net/http" ) @@ -30,23 +30,23 @@ func (this *GoSetAction) WillChange() bool { 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)) if nextGroup == nil || !nextGroup.IsOn { - return true + return true, true } nextSet := nextGroup.FindRuleSet(types.Int64(this.SetId)) if nextSet == nil || !nextSet.IsOn { - return true + return true, true } b, _, err := nextSet.MatchRequest(request) if err != nil { - logs.Error(err) - return true + remotelogs.Error("WAF", "GO_GROUP_ACTION: "+err.Error()) + return true, false } if !b { - return true + return true, false } return nextSet.PerformActions(waf, nextGroup, request, writer) } diff --git a/internal/waf/action_interface.go b/internal/waf/action_interface.go index a9de7ac..11d9162 100644 --- a/internal/waf/action_interface.go +++ b/internal/waf/action_interface.go @@ -27,5 +27,5 @@ type ActionInterface interface { WillChange() bool // 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) } diff --git a/internal/waf/action_js_cookie.go b/internal/waf/action_js_cookie.go index 3c62f07..71fbd51 100644 --- a/internal/waf/action_js_cookie.go +++ b/internal/waf/action_js_cookie.go @@ -41,15 +41,15 @@ func (this *JSCookieAction) WillChange() bool { 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()) { - return true + return true, false } nodeConfig, err := nodeconfigs.SharedNodeConfig() if err != nil { - return true + return true, false } var life = this.Life @@ -65,7 +65,7 @@ func (this *JSCookieAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, re if len(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:] { - return true + return true, false } } } @@ -94,7 +94,7 @@ window.location.reload(); // 记录失败次数 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) { diff --git a/internal/waf/action_log.go b/internal/waf/action_log.go index 5d7f334..6d2f2e9 100644 --- a/internal/waf/action_log.go +++ b/internal/waf/action_log.go @@ -25,6 +25,6 @@ func (this *LogAction) WillChange() bool { return false } -func (this *LogAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (allow bool) { - return true +func (this *LogAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (continueRequest bool, goNextSet bool) { + return true, false } diff --git a/internal/waf/action_notify.go b/internal/waf/action_notify.go index b6b5eb6..77bc068 100644 --- a/internal/waf/action_notify.go +++ b/internal/waf/action_notify.go @@ -71,7 +71,7 @@ func (this *NotifyAction) WillChange() bool { } // 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 { case notifyChan <- ¬ifyTask{ ServerId: request.WAFServerId(), @@ -84,5 +84,5 @@ func (this *NotifyAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, requ } - return true + return true, false } diff --git a/internal/waf/action_page.go b/internal/waf/action_page.go index ab5b905..499ad3a 100644 --- a/internal/waf/action_page.go +++ b/internal/waf/action_page.go @@ -32,10 +32,10 @@ func (this *PageAction) WillChange() bool { } // 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.WriteHeader(this.Status) _, _ = writer.Write([]byte(request.Format(this.Body))) - return false + return false, false } diff --git a/internal/waf/action_post_307.go b/internal/waf/action_post_307.go index c8c7c76..5f701dd 100644 --- a/internal/waf/action_post_307.go +++ b/internal/waf/action_post_307.go @@ -33,17 +33,17 @@ func (this *Post307Action) WillChange() bool { 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" // 仅限于POST 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()) { - return true + return true, false } // 判断是否有Cookie @@ -57,7 +57,7 @@ func (this *Post307Action) Perform(waf *WAF, group *RuleGroup, set *RuleSet, req } 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"), "") - 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) if err != nil { remotelogs.Error("WAF_POST_302_ACTION", "encode info failed: "+err.Error()) - return true + return true, false } // 设置Cookie @@ -90,5 +90,5 @@ func (this *Post307Action) Perform(waf *WAF, group *RuleGroup, set *RuleSet, req _ = this.CloseConn(writer) } - return false + return false, false } diff --git a/internal/waf/action_record_ip.go b/internal/waf/action_record_ip.go index 936f1d5..78741f7 100644 --- a/internal/waf/action_record_ip.go +++ b/internal/waf/action_record_ip.go @@ -99,10 +99,10 @@ func (this *RecordIPAction) WillChange() bool { 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()) { - return true + return true, false } 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 } diff --git a/internal/waf/action_tag.go b/internal/waf/action_tag.go index 1e84512..03ea356 100644 --- a/internal/waf/action_tag.go +++ b/internal/waf/action_tag.go @@ -27,6 +27,6 @@ func (this *TagAction) WillChange() bool { return false } -func (this *TagAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (allow bool) { - return true +func (this *TagAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (continueRequest bool, goNextSet bool) { + return true, true } diff --git a/internal/waf/rule.go b/internal/waf/rule.go index 4367313..8ece2d5 100644 --- a/internal/waf/rule.go +++ b/internal/waf/rule.go @@ -667,7 +667,7 @@ func (this *Rule) execFilter(value interface{}) interface{} { } value, goNext, err = filterInstance.Do(value, filter.Options) if err != nil { - remotelogs.Println("WAF", "filter error: "+err.Error()) + remotelogs.Error("WAF", "filter error: "+err.Error()) break } if !goNext { diff --git a/internal/waf/rule_set.go b/internal/waf/rule_set.go index 4946251..8d2b200 100644 --- a/internal/waf/rule_set.go +++ b/internal/waf/rule_set.go @@ -136,19 +136,19 @@ func (this *RuleSet) ActionCodes() []string { 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 { - return true + return true, false } // 先执行allow for _, instance := range this.actionInstances { if !instance.WillChange() { - goNext := req.WAFOnAction(instance) - if !goNext { - return false + continueRequest = req.WAFOnAction(instance) + if !continueRequest { + 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 { // 只执行第一个可能改变请求的动作,其余的都会被忽略 if instance.WillChange() { - goNext := req.WAFOnAction(instance) - if !goNext { - return false + continueRequest = req.WAFOnAction(instance) + if !continueRequest { + return false, false } 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) { diff --git a/internal/waf/waf.go b/internal/waf/waf.go index 6d73995..5c9e9f3 100644 --- a/internal/waf/waf.go +++ b/internal/waf/waf.go @@ -241,7 +241,7 @@ func (this *WAF) MoveOutboundRuleGroup(fromIndex int, toIndex int) { 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 { 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 } if b { - goNext = set.PerformActions(this, group, req, writer) - return goNext, hasRequestBody, group, set, nil + continueRequest, goNextSet := set.PerformActions(this, group, req, writer) + if !goNextSet { + return continueRequest, hasRequestBody, group, set, 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 } if b { - goNext = set.PerformActions(this, group, req, writer) - return goNext, hasRequestBody, group, set, nil + continueRequest, goNextSet := set.PerformActions(this, group, req, writer) + if !goNextSet { + return continueRequest, hasRequestBody, group, set, nil + } } } return true, hasRequestBody, nil, nil, nil