mirror of
https://github.com/TeaOSLab/EdgeNode.git
synced 2025-11-03 23:20:25 +08:00
299 lines
7.7 KiB
Go
299 lines
7.7 KiB
Go
package nodes
|
|
|
|
import (
|
|
"bytes"
|
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
|
"github.com/TeaOSLab/EdgeNode/internal/iplibrary"
|
|
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
|
"github.com/TeaOSLab/EdgeNode/internal/stats"
|
|
"github.com/TeaOSLab/EdgeNode/internal/waf"
|
|
"github.com/iwind/TeaGo/lists"
|
|
"github.com/iwind/TeaGo/types"
|
|
"io"
|
|
"io/ioutil"
|
|
"net/http"
|
|
)
|
|
|
|
// 调用WAF
|
|
func (this *HTTPRequest) doWAFRequest() (blocked bool) {
|
|
// 当前服务的独立设置
|
|
if this.web.FirewallPolicy != nil && this.web.FirewallPolicy.IsOn {
|
|
blocked, breakChecking := this.checkWAFRequest(this.web.FirewallPolicy)
|
|
if blocked {
|
|
return true
|
|
}
|
|
if breakChecking {
|
|
return false
|
|
}
|
|
}
|
|
|
|
// 公用的防火墙设置
|
|
if sharedNodeConfig.HTTPFirewallPolicy != nil {
|
|
blocked, breakChecking := this.checkWAFRequest(sharedNodeConfig.HTTPFirewallPolicy)
|
|
if blocked {
|
|
return true
|
|
}
|
|
if breakChecking {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (this *HTTPRequest) checkWAFRequest(firewallPolicy *firewallconfigs.HTTPFirewallPolicy) (blocked bool, breakChecking bool) {
|
|
// 检查配置是否为空
|
|
if firewallPolicy == nil || !firewallPolicy.IsOn || firewallPolicy.Inbound == nil || !firewallPolicy.Inbound.IsOn {
|
|
return
|
|
}
|
|
|
|
// 检查IP白名单
|
|
remoteAddrs := this.requestRemoteAddrs()
|
|
inbound := firewallPolicy.Inbound
|
|
if inbound == nil {
|
|
return
|
|
}
|
|
for _, ref := range inbound.AllAllowListRefs() {
|
|
if ref.IsOn && ref.ListId > 0 {
|
|
list := iplibrary.SharedIPListManager.FindList(ref.ListId)
|
|
if list != nil {
|
|
found, _ := list.ContainsIPStrings(remoteAddrs)
|
|
if found {
|
|
breakChecking = true
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 检查IP黑名单
|
|
for _, ref := range inbound.AllDenyListRefs() {
|
|
if ref.IsOn && ref.ListId > 0 {
|
|
list := iplibrary.SharedIPListManager.FindList(ref.ListId)
|
|
if list != nil {
|
|
found, item := list.ContainsIPStrings(remoteAddrs)
|
|
if found {
|
|
// 触发事件
|
|
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("HTTP_REQUEST_WAF", "do action '"+err.Error()+"' failed: "+err.Error())
|
|
return true, false
|
|
}
|
|
if !goNext {
|
|
this.disableLog = true
|
|
return true, false
|
|
}
|
|
}
|
|
}
|
|
|
|
// TODO 需要记录日志信息
|
|
|
|
this.writer.WriteHeader(http.StatusForbidden)
|
|
this.writer.Close()
|
|
|
|
// 停止日志
|
|
this.disableLog = true
|
|
|
|
return true, false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 检查地区封禁
|
|
if iplibrary.SharedLibrary != nil {
|
|
if firewallPolicy.Inbound.Region != nil && firewallPolicy.Inbound.Region.IsOn {
|
|
regionConfig := firewallPolicy.Inbound.Region
|
|
if regionConfig.IsNotEmpty() {
|
|
for _, remoteAddr := range remoteAddrs {
|
|
result, err := iplibrary.SharedLibrary.Lookup(remoteAddr)
|
|
if err != nil {
|
|
remotelogs.Error("HTTP_REQUEST_WAF", "iplibrary lookup failed: "+err.Error())
|
|
} else if result != nil {
|
|
// 检查国家级别封禁
|
|
if len(regionConfig.DenyCountryIds) > 0 && len(result.Country) > 0 {
|
|
countryId := iplibrary.SharedCountryManager.Lookup(result.Country)
|
|
if countryId > 0 && lists.ContainsInt64(regionConfig.DenyCountryIds, countryId) {
|
|
// TODO 可以配置对封禁的处理方式等
|
|
// TODO 需要记录日志信息
|
|
this.writer.WriteHeader(http.StatusForbidden)
|
|
this.writer.Close()
|
|
|
|
// 停止日志
|
|
this.disableLog = true
|
|
|
|
return true, false
|
|
}
|
|
}
|
|
|
|
// 检查省份封禁
|
|
if len(regionConfig.DenyProvinceIds) > 0 && len(result.Province) > 0 {
|
|
provinceId := iplibrary.SharedProvinceManager.Lookup(result.Province)
|
|
if provinceId > 0 && lists.ContainsInt64(regionConfig.DenyProvinceIds, provinceId) {
|
|
// TODO 可以配置对封禁的处理方式等
|
|
// TODO 需要记录日志信息
|
|
this.writer.WriteHeader(http.StatusForbidden)
|
|
this.writer.Close()
|
|
|
|
// 停止日志
|
|
this.disableLog = true
|
|
|
|
return true, false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 规则测试
|
|
w := sharedWAFManager.FindWAF(firewallPolicy.Id)
|
|
if w == nil {
|
|
return
|
|
}
|
|
|
|
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.HasSpecialActions() {
|
|
this.firewallPolicyId = firewallPolicy.Id
|
|
this.firewallRuleGroupId = types.Int64(ruleGroup.Id)
|
|
this.firewallRuleSetId = types.Int64(ruleSet.Id)
|
|
|
|
if ruleSet.HasAttackActions() {
|
|
this.isAttack = true
|
|
}
|
|
|
|
// 添加统计
|
|
stats.SharedHTTPRequestStatManager.AddFirewallRuleGroupId(this.Server.Id, this.firewallRuleGroupId, ruleSet.Actions)
|
|
}
|
|
|
|
this.firewallActions = ruleSet.ActionCodes()
|
|
}
|
|
|
|
return !goNext, false
|
|
}
|
|
|
|
// call response waf
|
|
func (this *HTTPRequest) doWAFResponse(resp *http.Response) (blocked bool) {
|
|
// 当前服务的独立设置
|
|
if this.web.FirewallPolicy != nil && this.web.FirewallPolicy.IsOn {
|
|
blocked := this.checkWAFResponse(this.web.FirewallPolicy, resp)
|
|
if blocked {
|
|
return true
|
|
}
|
|
}
|
|
|
|
// 公用的防火墙设置
|
|
if sharedNodeConfig.HTTPFirewallPolicy != nil {
|
|
blocked := this.checkWAFResponse(sharedNodeConfig.HTTPFirewallPolicy, resp)
|
|
if blocked {
|
|
return true
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (this *HTTPRequest) checkWAFResponse(firewallPolicy *firewallconfigs.HTTPFirewallPolicy, resp *http.Response) (blocked bool) {
|
|
if firewallPolicy == nil || !firewallPolicy.IsOn || !firewallPolicy.Outbound.IsOn {
|
|
return
|
|
}
|
|
|
|
w := sharedWAFManager.FindWAF(firewallPolicy.Id)
|
|
if w == nil {
|
|
return
|
|
}
|
|
|
|
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.HasSpecialActions() {
|
|
this.firewallPolicyId = firewallPolicy.Id
|
|
this.firewallRuleGroupId = types.Int64(ruleGroup.Id)
|
|
this.firewallRuleSetId = types.Int64(ruleSet.Id)
|
|
|
|
if ruleSet.HasAttackActions() {
|
|
this.isAttack = true
|
|
}
|
|
|
|
// 添加统计
|
|
stats.SharedHTTPRequestStatManager.AddFirewallRuleGroupId(this.Server.Id, this.firewallRuleGroupId, ruleSet.Actions)
|
|
}
|
|
|
|
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
|
|
}
|