github.com/TeaOSLab/EdgeNode@v1.3.8/internal/waf/action_record_ip.go (about)

     1  package waf
     2  
     3  import (
     4  	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
     5  	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
     6  	teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
     7  	"github.com/TeaOSLab/EdgeNode/internal/events"
     8  	"github.com/TeaOSLab/EdgeNode/internal/goman"
     9  	"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
    10  	"github.com/TeaOSLab/EdgeNode/internal/rpc"
    11  	"github.com/TeaOSLab/EdgeNode/internal/waf/requests"
    12  	"github.com/iwind/TeaGo/types"
    13  	"net/http"
    14  	"strings"
    15  	"time"
    16  )
    17  
    18  type recordIPTask struct {
    19  	ip        string
    20  	listId    int64
    21  	expiresAt int64
    22  	level     string
    23  	serverId  int64
    24  
    25  	reason string
    26  
    27  	sourceServerId                int64
    28  	sourceHTTPFirewallPolicyId    int64
    29  	sourceHTTPFirewallRuleGroupId int64
    30  	sourceHTTPFirewallRuleSetId   int64
    31  }
    32  
    33  var recordIPTaskChan = make(chan *recordIPTask, 2048)
    34  
    35  func init() {
    36  	if !teaconst.IsMain {
    37  		return
    38  	}
    39  
    40  	events.On(events.EventLoaded, func() {
    41  		goman.New(func() {
    42  			rpcClient, err := rpc.SharedRPC()
    43  			if err != nil {
    44  				remotelogs.Error("WAF_RECORD_IP_ACTION", "create rpc client failed: "+err.Error())
    45  				return
    46  			}
    47  
    48  			const maxItems = 512 // 每次上传的最大IP数
    49  
    50  			for {
    51  				var pbItemMap = map[string]*pb.CreateIPItemsRequest_IPItem{} // ip => IPItem
    52  
    53  				func() {
    54  					for {
    55  						select {
    56  						case task := <-recordIPTaskChan:
    57  							var ipType = "ipv4"
    58  							if strings.Contains(task.ip, ":") {
    59  								ipType = "ipv6"
    60  							}
    61  							var reason = task.reason
    62  							if len(reason) == 0 {
    63  								reason = "触发WAF规则自动加入"
    64  							}
    65  
    66  							pbItemMap[task.ip] = &pb.CreateIPItemsRequest_IPItem{
    67  								IpListId:                      task.listId,
    68  								Value:                         task.ip,
    69  								IpFrom:                        task.ip,
    70  								IpTo:                          "",
    71  								ExpiredAt:                     task.expiresAt,
    72  								Reason:                        reason,
    73  								Type:                          ipType,
    74  								EventLevel:                    task.level,
    75  								ServerId:                      task.serverId,
    76  								SourceNodeId:                  teaconst.NodeId,
    77  								SourceServerId:                task.sourceServerId,
    78  								SourceHTTPFirewallPolicyId:    task.sourceHTTPFirewallPolicyId,
    79  								SourceHTTPFirewallRuleGroupId: task.sourceHTTPFirewallRuleGroupId,
    80  								SourceHTTPFirewallRuleSetId:   task.sourceHTTPFirewallRuleSetId,
    81  							}
    82  
    83  							if len(pbItemMap) >= maxItems {
    84  								return
    85  							}
    86  						default:
    87  							return
    88  						}
    89  					}
    90  				}()
    91  
    92  				if len(pbItemMap) > 0 {
    93  					var pbItems = []*pb.CreateIPItemsRequest_IPItem{}
    94  					for _, pbItem := range pbItemMap {
    95  						pbItems = append(pbItems, pbItem)
    96  					}
    97  					_, err = rpcClient.IPItemRPC.CreateIPItems(rpcClient.Context(), &pb.CreateIPItemsRequest{IpItems: pbItems})
    98  					if err != nil {
    99  						remotelogs.Error("WAF_RECORD_IP_ACTION", "create ip item failed: "+err.Error())
   100  					}
   101  				} else {
   102  					time.Sleep(1 * time.Second)
   103  				}
   104  			}
   105  		})
   106  	})
   107  }
   108  
   109  type RecordIPAction struct {
   110  	BaseAction
   111  
   112  	Type            string `yaml:"type" json:"type"`
   113  	IPListId        int64  `yaml:"ipListId" json:"ipListId"`
   114  	IPListIsDeleted bool   `yaml:"ipListIsDeleted" json:"ipListIsDeleted"`
   115  	Level           string `yaml:"level" json:"level"`
   116  	Timeout         int32  `yaml:"timeout" json:"timeout"`
   117  	Scope           string `yaml:"scope" json:"scope"`
   118  }
   119  
   120  func (this *RecordIPAction) Init(waf *WAF) error {
   121  	return nil
   122  }
   123  
   124  func (this *RecordIPAction) Code() string {
   125  	return ActionRecordIP
   126  }
   127  
   128  func (this *RecordIPAction) IsAttack() bool {
   129  	return this.Type == "black"
   130  }
   131  
   132  func (this *RecordIPAction) WillChange() bool {
   133  	return this.Type == "black"
   134  }
   135  
   136  func (this *RecordIPAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) PerformResult {
   137  	var ipListId = this.IPListId
   138  	if ipListId <= 0 {
   139  		ipListId = firewallconfigs.GlobalListId
   140  	}
   141  
   142  	// 是否已删除
   143  	var ipListIsAvailable = (ipListId == firewallconfigs.GlobalListId) || (ipListId > 0 && !this.IPListIsDeleted && !ExistDeletedIPList(ipListId))
   144  
   145  	// 是否在本地白名单中
   146  	if SharedIPWhiteList.Contains("set:"+types.String(set.Id), this.Scope, request.WAFServerId(), request.WAFRemoteIP()) {
   147  		return PerformResult{
   148  			ContinueRequest: true,
   149  			IsAllowed:       true,
   150  			AllowScope:      AllowScopeGlobal,
   151  		}
   152  	}
   153  
   154  	var timeout = this.Timeout
   155  	var isForever = false
   156  	if timeout <= 0 {
   157  		isForever = true
   158  		timeout = 86400 // 1天
   159  	}
   160  	var expiresAt = time.Now().Unix() + int64(timeout)
   161  
   162  	if this.Type == "black" {
   163  		request.ProcessResponseHeaders(writer.Header(), http.StatusForbidden)
   164  		writer.WriteHeader(http.StatusForbidden)
   165  
   166  		request.WAFClose()
   167  
   168  		// 先加入本地的黑名单
   169  		if ipListIsAvailable {
   170  			SharedIPBlackList.Add(IPTypeAll, this.Scope, request.WAFServerId(), request.WAFRemoteIP(), expiresAt)
   171  		}
   172  	} else {
   173  		// 加入本地白名单
   174  		if ipListIsAvailable {
   175  			SharedIPWhiteList.Add("set:"+types.String(set.Id), this.Scope, request.WAFServerId(), request.WAFRemoteIP(), expiresAt)
   176  		}
   177  	}
   178  
   179  	// 上报
   180  	if ipListId > 0 && ipListIsAvailable {
   181  		var serverId int64
   182  		if this.Scope == firewallconfigs.FirewallScopeServer {
   183  			serverId = request.WAFServerId()
   184  		}
   185  
   186  		var realExpiresAt = expiresAt
   187  		if isForever {
   188  			realExpiresAt = 0
   189  		}
   190  
   191  		select {
   192  		case recordIPTaskChan <- &recordIPTask{
   193  			ip:                            request.WAFRemoteIP(),
   194  			listId:                        ipListId,
   195  			expiresAt:                     realExpiresAt,
   196  			level:                         this.Level,
   197  			serverId:                      serverId,
   198  			sourceServerId:                request.WAFServerId(),
   199  			sourceHTTPFirewallPolicyId:    waf.Id,
   200  			sourceHTTPFirewallRuleGroupId: group.Id,
   201  			sourceHTTPFirewallRuleSetId:   set.Id,
   202  		}:
   203  		default:
   204  
   205  		}
   206  	}
   207  
   208  	var isWhite = this.Type != "black"
   209  	return PerformResult{
   210  		ContinueRequest: isWhite,
   211  		IsAllowed:       isWhite,
   212  		AllowScope:      AllowScopeGlobal,
   213  	}
   214  }