WAF动作增加显示HTML内容

This commit is contained in:
刘祥超
2021-02-26 16:33:58 +08:00
parent 2a7fd997dc
commit a1e93303f9
6 changed files with 130 additions and 21 deletions

View File

@@ -3,6 +3,7 @@ package iplibrary
import ( import (
"encoding/json" "encoding/json"
"github.com/iwind/TeaGo/maps" "github.com/iwind/TeaGo/maps"
"net/http"
) )
type BaseAction struct { type BaseAction struct {
@@ -12,6 +13,11 @@ func (this *BaseAction) Close() error {
return nil return nil
} }
// 处理HTTP请求
func (this *BaseAction) DoHTTP(req *http.Request, resp http.ResponseWriter) (goNext bool, err error) {
return true, nil
}
func (this *BaseAction) convertParams(params maps.Map, ptr interface{}) error { func (this *BaseAction) convertParams(params maps.Map, ptr interface{}) error {
data, err := json.Marshal(params) data, err := json.Marshal(params)
if err != nil { if err != nil {

View File

@@ -0,0 +1,55 @@
package iplibrary
import (
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
"net/http"
)
// HTML动作
type HTMLAction struct {
BaseAction
config *firewallconfigs.FirewallActionHTMLConfig
}
// 获取新对象
func NewHTMLAction() *HTMLAction {
return &HTMLAction{}
}
// 初始化
func (this *HTMLAction) Init(config *firewallconfigs.FirewallActionConfig) error {
this.config = &firewallconfigs.FirewallActionHTMLConfig{}
err := this.convertParams(config.Params, this.config)
if err != nil {
return err
}
return nil
}
// 添加
func (this *HTMLAction) AddItem(listType IPListType, item *pb.IPItem) error {
return nil
}
// 删除
func (this *HTMLAction) DeleteItem(listType IPListType, item *pb.IPItem) error {
return nil
}
// 关闭
func (this *HTMLAction) Close() error {
return nil
}
// 处理HTTP请求
func (this *HTMLAction) DoHTTP(req *http.Request, resp http.ResponseWriter) (goNext bool, err error) {
if this.config == nil {
goNext = true
return
}
resp.WriteHeader(http.StatusForbidden) // TODO改成可以配置
_, _ = resp.Write([]byte(this.config.Content))
return false, nil
}

View File

@@ -3,6 +3,7 @@ package iplibrary
import ( import (
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs" "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
"net/http"
) )
type ActionInterface interface { type ActionInterface interface {
@@ -17,4 +18,7 @@ type ActionInterface interface {
// 关闭 // 关闭
Close() error Close() error
// 处理HTTP请求
DoHTTP(req *http.Request, resp http.ResponseWriter) (goNext bool, err error)
} }

View File

@@ -60,12 +60,12 @@ func (this *ActionManager) UpdateActions(actions []*firewallconfigs.FirewallActi
// 检查配置是否一致 // 检查配置是否一致
oldConfigJSON, err := json.Marshal(this.configMap[newAction.Id]) oldConfigJSON, err := json.Marshal(this.configMap[newAction.Id])
if err != nil { if err != nil {
remotelogs.Error("IPLIBRARY/ACTION_MANAGER", "action "+strconv.FormatInt(newAction.Id, 10) + ", type:" + newAction.Type+": "+err.Error()) remotelogs.Error("IPLIBRARY/ACTION_MANAGER", "action "+strconv.FormatInt(newAction.Id, 10)+", type:"+newAction.Type+": "+err.Error())
continue continue
} }
newConfigJSON, err := json.Marshal(newAction) newConfigJSON, err := json.Marshal(newAction)
if err != nil { if err != nil {
remotelogs.Error("IPLIBRARY/ACTION_MANAGER", "action "+strconv.FormatInt(newAction.Id, 10) + ", type:" + newAction.Type+": "+err.Error()) remotelogs.Error("IPLIBRARY/ACTION_MANAGER", "action "+strconv.FormatInt(newAction.Id, 10)+", type:"+newAction.Type+": "+err.Error())
continue continue
} }
if bytes.Compare(newConfigJSON, oldConfigJSON) != 0 { if bytes.Compare(newConfigJSON, oldConfigJSON) != 0 {
@@ -75,7 +75,7 @@ func (this *ActionManager) UpdateActions(actions []*firewallconfigs.FirewallActi
// 之所以要重新创建,是因为前后的动作类型可能有变化,完全重建可以避免不必要的麻烦 // 之所以要重新创建,是因为前后的动作类型可能有变化,完全重建可以避免不必要的麻烦
newInstance, err := this.createInstance(newAction) newInstance, err := this.createInstance(newAction)
if err != nil { if err != nil {
remotelogs.Error("IPLIBRARY/ACTION_MANAGER", "reload action "+strconv.FormatInt(newAction.Id, 10) + ", type:" + newAction.Type+": "+err.Error()) remotelogs.Error("IPLIBRARY/ACTION_MANAGER", "reload action "+strconv.FormatInt(newAction.Id, 10)+", type:"+newAction.Type+": "+err.Error())
continue continue
} }
remotelogs.Println("IPLIBRARY/ACTION_MANAGER", "reloaded "+strconv.FormatInt(newAction.Id, 10)+", type:"+newAction.Type) remotelogs.Println("IPLIBRARY/ACTION_MANAGER", "reloaded "+strconv.FormatInt(newAction.Id, 10)+", type:"+newAction.Type)
@@ -85,7 +85,7 @@ func (this *ActionManager) UpdateActions(actions []*firewallconfigs.FirewallActi
// 创建 // 创建
instance, err := this.createInstance(newAction) instance, err := this.createInstance(newAction)
if err != nil { if err != nil {
remotelogs.Error("IPLIBRARY/ACTION_MANAGER", "load new action "+strconv.FormatInt(newAction.Id, 10) + ", type:" + newAction.Type+": "+err.Error()) remotelogs.Error("IPLIBRARY/ACTION_MANAGER", "load new action "+strconv.FormatInt(newAction.Id, 10)+", type:"+newAction.Type+": "+err.Error())
continue continue
} }
remotelogs.Println("IPLIBRARY/ACTION_MANAGER", "loaded action "+strconv.FormatInt(newAction.Id, 10)+", type:"+newAction.Type) remotelogs.Println("IPLIBRARY/ACTION_MANAGER", "loaded action "+strconv.FormatInt(newAction.Id, 10)+", type:"+newAction.Type)
@@ -108,6 +108,13 @@ func (this *ActionManager) UpdateActions(actions []*firewallconfigs.FirewallActi
} }
} }
// 查找事件对应的动作
func (this *ActionManager) FindEventActions(eventLevel string) []ActionInterface {
this.locker.Lock()
defer this.locker.Unlock()
return this.eventMap[eventLevel]
}
// 执行添加IP动作 // 执行添加IP动作
func (this *ActionManager) AddItem(listType IPListType, item *pb.IPItem) { func (this *ActionManager) AddItem(listType IPListType, item *pb.IPItem) {
instances, ok := this.eventMap[item.EventLevel] instances, ok := this.eventMap[item.EventLevel]
@@ -147,6 +154,8 @@ func (this *ActionManager) createInstance(config *firewallconfigs.FirewallAction
instance = NewScriptAction() instance = NewScriptAction()
case firewallconfigs.FirewallActionTypeHTTPAPI: case firewallconfigs.FirewallActionTypeHTTPAPI:
instance = NewHTTPAPIAction() instance = NewHTTPAPIAction()
case firewallconfigs.FirewallActionTypeHTML:
instance = NewHTMLAction()
} }
if instance == nil { if instance == nil {
return nil, errors.New("can not create instance for type '" + config.Type + "'") return nil, errors.New("can not create instance for type '" + config.Type + "'")

View File

@@ -110,27 +110,40 @@ func (this *IPList) Contains(ip uint64) bool {
} }
// 是否包含一组IP // 是否包含一组IP
func (this *IPList) ContainsIPStrings(ipStrings []string) bool { func (this *IPList) ContainsIPStrings(ipStrings []string) (found bool, item *IPItem) {
if len(ipStrings) == 0 { if len(ipStrings) == 0 {
return false return
} }
this.locker.RLock() this.locker.RLock()
if this.isAll { if this.isAll {
itemIds := this.ipMap[0]
if len(itemIds) > 0 {
itemId := itemIds[0]
item = this.itemsMap[itemId]
}
this.locker.RUnlock() this.locker.RUnlock()
return true found = true
return
} }
for _, ipString := range ipStrings { for _, ipString := range ipStrings {
if len(ipString) == 0 { if len(ipString) == 0 {
continue continue
} }
_, ok := this.ipMap[utils.IP2Long(ipString)] itemIds, ok := this.ipMap[utils.IP2Long(ipString)]
if ok { if ok {
if len(itemIds) > 0 {
itemId := itemIds[0]
item = this.itemsMap[itemId]
}
this.locker.RUnlock() this.locker.RUnlock()
return true found = true
return
} }
} }
this.locker.RUnlock() this.locker.RUnlock()
return false return
} }
// 在不加锁的情况下删除某个Item // 在不加锁的情况下删除某个Item

View File

@@ -49,25 +49,47 @@ func (this *HTTPRequest) checkWAFRequest(firewallPolicy *firewallconfigs.HTTPFir
inbound := firewallPolicy.Inbound inbound := firewallPolicy.Inbound
if inbound.AllowListRef != nil && inbound.AllowListRef.IsOn && inbound.AllowListRef.ListId > 0 { if inbound.AllowListRef != nil && inbound.AllowListRef.IsOn && inbound.AllowListRef.ListId > 0 {
list := iplibrary.SharedIPListManager.FindList(inbound.AllowListRef.ListId) list := iplibrary.SharedIPListManager.FindList(inbound.AllowListRef.ListId)
if list != nil && list.ContainsIPStrings(remoteAddrs) { if list != nil {
breakChecking = true found, _ := list.ContainsIPStrings(remoteAddrs)
return if found {
breakChecking = true
return
}
} }
} }
// 检查IP黑名单 // 检查IP黑名单
if inbound.DenyListRef != nil && inbound.DenyListRef.IsOn && inbound.DenyListRef.ListId > 0 { if inbound.DenyListRef != nil && inbound.DenyListRef.IsOn && inbound.DenyListRef.ListId > 0 {
list := iplibrary.SharedIPListManager.FindList(inbound.DenyListRef.ListId) list := iplibrary.SharedIPListManager.FindList(inbound.DenyListRef.ListId)
if list != nil && list.ContainsIPStrings(remoteAddrs) { if list != nil {
// TODO 可以配置对封禁的处理方式等 found, item := list.ContainsIPStrings(remoteAddrs)
// TODO 需要记录日志信息 if found {
this.writer.WriteHeader(http.StatusForbidden) // 触发事件
this.writer.Close() if item != nil && len(item.EventLevel) > 0 {
actions := iplibrary.SharedActionManager.FindEventActions(item.EventLevel)
for _, action := range actions {
goNext, err := action.DoHTTP(this.RawReq, this.RawWriter)
if err != nil {
remotelogs.Error("REQUEST", "do action '"+err.Error()+"' failed: "+err.Error())
return true, false
}
if !goNext {
this.disableLog = true
return true, false
}
}
}
// 停止日志 // TODO 需要记录日志信息
this.disableLog = true
return true, false this.writer.WriteHeader(http.StatusForbidden)
this.writer.Close()
// 停止日志
this.disableLog = true
return true, false
}
} }
} }