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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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 <- &notifyTask{
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
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
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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