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 }