WAF增加多个动作

This commit is contained in:
刘祥超
2021-07-18 15:51:49 +08:00
parent 0486f86898
commit d775dfeeaa
98 changed files with 1999 additions and 903 deletions

View File

@@ -68,12 +68,15 @@ type HTTPRequest struct {
cacheKey string // 缓存使用的Key
isCached bool // 是否已经被缓存
isAttack bool // 是否是攻击请求
bodyData []byte // 读取的Body内容
// WAF相关
firewallPolicyId int64
firewallRuleGroupId int64
firewallRuleSetId int64
firewallRuleId int64
firewallActions []string
tags []string
logAttrs map[string]string
@@ -1197,5 +1200,10 @@ func (this *HTTPRequest) canIgnore(err error) bool {
return true
}
// HTTP内部错误
if strings.HasPrefix(err.Error(), "http:") || strings.HasPrefix(err.Error(), "http2:") {
return true
}
return false
}

View File

@@ -128,6 +128,8 @@ func (this *HTTPRequest) log() {
FirewallRuleGroupId: this.firewallRuleGroupId,
FirewallRuleSetId: this.firewallRuleSetId,
FirewallRuleId: this.firewallRuleId,
FirewallActions: this.firewallActions,
Tags: this.tags,
Attrs: this.logAttrs,
}

View File

@@ -1,6 +1,7 @@
package nodes
import (
"bytes"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
"github.com/TeaOSLab/EdgeNode/internal/iplibrary"
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
@@ -8,6 +9,8 @@ import (
"github.com/TeaOSLab/EdgeNode/internal/waf"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/types"
"io"
"io/ioutil"
"net/http"
)
@@ -152,27 +155,36 @@ func (this *HTTPRequest) checkWAFRequest(firewallPolicy *firewallconfigs.HTTPFir
if w == nil {
return
}
goNext, ruleGroup, ruleSet, err := w.MatchRequest(this.RawReq, this.writer)
w.OnAction(func(action waf.ActionInterface) (goNext bool) {
switch action.Code() {
case waf.ActionTag:
this.tags = action.(*waf.TagAction).Tags
}
return true
})
goNext, ruleGroup, ruleSet, err := w.MatchRequest(this, this.writer)
if err != nil {
remotelogs.Error("HTTP_REQUEST_WAF", this.rawURI+": "+err.Error())
return
}
if ruleSet != nil {
if ruleSet.Action != waf.ActionAllow {
if ruleSet.HasSpecialActions() {
this.firewallPolicyId = firewallPolicy.Id
this.firewallRuleGroupId = types.Int64(ruleGroup.Id)
this.firewallRuleSetId = types.Int64(ruleSet.Id)
if ruleSet.Action == waf.ActionBlock {
if ruleSet.HasAttackActions() {
this.isAttack = true
}
// 添加统计
stats.SharedHTTPRequestStatManager.AddFirewallRuleGroupId(this.Server.Id, this.firewallRuleGroupId, ruleSet.Action)
stats.SharedHTTPRequestStatManager.AddFirewallRuleGroupId(this.Server.Id, this.firewallRuleGroupId, ruleSet.Actions)
}
this.logAttrs["waf.action"] = ruleSet.Action
this.firewallActions = ruleSet.ActionCodes()
}
return !goNext, false
@@ -208,28 +220,79 @@ func (this *HTTPRequest) checkWAFResponse(firewallPolicy *firewallconfigs.HTTPFi
return
}
goNext, ruleGroup, ruleSet, err := w.MatchResponse(this.RawReq, resp, this.writer)
w.OnAction(func(action waf.ActionInterface) (goNext bool) {
switch action.Code() {
case waf.ActionTag:
this.tags = action.(*waf.TagAction).Tags
}
return true
})
goNext, ruleGroup, ruleSet, err := w.MatchResponse(this, resp, this.writer)
if err != nil {
remotelogs.Error("HTTP_REQUEST_WAF", this.rawURI+": "+err.Error())
return
}
if ruleSet != nil {
if ruleSet.Action != waf.ActionAllow {
if ruleSet.HasSpecialActions() {
this.firewallPolicyId = firewallPolicy.Id
this.firewallRuleGroupId = types.Int64(ruleGroup.Id)
this.firewallRuleSetId = types.Int64(ruleSet.Id)
if ruleSet.Action == waf.ActionBlock {
if ruleSet.HasAttackActions() {
this.isAttack = true
}
// 添加统计
stats.SharedHTTPRequestStatManager.AddFirewallRuleGroupId(this.Server.Id, this.firewallRuleGroupId, ruleSet.Action)
stats.SharedHTTPRequestStatManager.AddFirewallRuleGroupId(this.Server.Id, this.firewallRuleGroupId, ruleSet.Actions)
}
this.logAttrs["waf.action"] = ruleSet.Action
this.firewallActions = ruleSet.ActionCodes()
}
return !goNext
}
// WAFRaw 原始请求
func (this *HTTPRequest) WAFRaw() *http.Request {
return this.RawReq
}
// WAFRemoteIP 客户端IP
func (this *HTTPRequest) WAFRemoteIP() string {
return this.requestRemoteAddr()
}
// WAFGetCacheBody 获取缓存中的Body
func (this *HTTPRequest) WAFGetCacheBody() []byte {
return this.bodyData
}
// WAFSetCacheBody 设置Body
func (this *HTTPRequest) WAFSetCacheBody(body []byte) {
this.bodyData = body
}
// WAFReadBody 读取Body
func (this *HTTPRequest) WAFReadBody(max int64) (data []byte, err error) {
if this.RawReq.ContentLength > 0 {
data, err = ioutil.ReadAll(io.LimitReader(this.RawReq.Body, max))
}
return
}
// WAFRestoreBody 恢复Body
func (this *HTTPRequest) WAFRestoreBody(data []byte) {
if len(data) > 0 {
rawReader := bytes.NewBuffer(data)
buf := make([]byte, 1024)
_, _ = io.CopyBuffer(rawReader, this.RawReq.Body, buf)
this.RawReq.Body = ioutil.NopCloser(rawReader)
}
}
// WAFServerId 服务ID
func (this *HTTPRequest) WAFServerId() int64 {
return this.Server.Id
}

View File

@@ -7,7 +7,7 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/types"
http2 "golang.org/x/net/http2"
"golang.org/x/net/http2"
"sync"
)

View File

@@ -2,7 +2,10 @@
package nodes
import "net"
import (
"github.com/TeaOSLab/EdgeNode/internal/waf"
"net"
)
// TrafficListener 用于统计流量的网络监听
type TrafficListener struct {
@@ -18,6 +21,17 @@ func (this *TrafficListener) Accept() (net.Conn, error) {
if err != nil {
return nil, err
}
// 是否在WAF名单中
ip, _, err := net.SplitHostPort(conn.RemoteAddr().String())
if err == nil {
if !waf.SharedIPWhiteList.Contains(waf.IPTypeAll, ip) && waf.SharedIPBlackLIst.Contains(waf.IPTypeAll, ip) {
go func() {
_ = conn.Close()
}()
return conn, nil
}
}
return NewTrafficConn(conn), nil
}

View File

@@ -11,20 +11,20 @@ import (
var sharedWAFManager = NewWAFManager()
// WAF管理器
// WAFManager WAF管理器
type WAFManager struct {
mapping map[int64]*waf.WAF // policyId => WAF
locker sync.RWMutex
}
// 获取新对象
// NewWAFManager 获取新对象
func NewWAFManager() *WAFManager {
return &WAFManager{
mapping: map[int64]*waf.WAF{},
}
}
// 更新策略
// UpdatePolicies 更新策略
func (this *WAFManager) UpdatePolicies(policies []*firewallconfigs.HTTPFirewallPolicy) {
this.locker.Lock()
defer this.locker.Unlock()
@@ -44,7 +44,7 @@ func (this *WAFManager) UpdatePolicies(policies []*firewallconfigs.HTTPFirewallP
this.mapping = m
}
// 查找WAF
// FindWAF 查找WAF
func (this *WAFManager) FindWAF(policyId int64) *waf.WAF {
this.locker.RLock()
w, _ := this.mapping[policyId]
@@ -78,14 +78,15 @@ func (this *WAFManager) convertWAF(policy *firewallconfigs.HTTPFirewallPolicy) (
// rule sets
for _, set := range group.Sets {
s := &waf.RuleSet{
Id: strconv.FormatInt(set.Id, 10),
Code: set.Code,
IsOn: set.IsOn,
Name: set.Name,
Description: set.Description,
Connector: set.Connector,
Action: set.Action,
ActionOptions: set.ActionOptions,
Id: strconv.FormatInt(set.Id, 10),
Code: set.Code,
IsOn: set.IsOn,
Name: set.Name,
Description: set.Description,
Connector: set.Connector,
}
for _, a := range set.Actions {
s.AddAction(a.Code, a.Options)
}
// rules
@@ -132,14 +133,16 @@ func (this *WAFManager) convertWAF(policy *firewallconfigs.HTTPFirewallPolicy) (
// rule sets
for _, set := range group.Sets {
s := &waf.RuleSet{
Id: strconv.FormatInt(set.Id, 10),
Code: set.Code,
IsOn: set.IsOn,
Name: set.Name,
Description: set.Description,
Connector: set.Connector,
Action: set.Action,
ActionOptions: set.ActionOptions,
Id: strconv.FormatInt(set.Id, 10),
Code: set.Code,
IsOn: set.IsOn,
Name: set.Name,
Description: set.Description,
Connector: set.Connector,
}
for _, a := range set.Actions {
s.AddAction(a.Code, a.Options)
}
// rules
@@ -164,10 +167,11 @@ func (this *WAFManager) convertWAF(policy *firewallconfigs.HTTPFirewallPolicy) (
// action
if policy.BlockOptions != nil {
w.ActionBlock = &waf.BlockAction{
w.DefaultBlockAction = &waf.BlockAction{
StatusCode: policy.BlockOptions.StatusCode,
Body: policy.BlockOptions.Body,
URL: "",
URL: policy.BlockOptions.URL,
Timeout: policy.BlockOptions.Timeout,
}
}