mirror of
https://gitee.com/samwaf/SamWaf.git
synced 2025-12-06 14:59:18 +08:00
@@ -65,9 +65,18 @@ func (w *WafLogAPi) GetListApi(c *gin.Context) {
|
||||
}
|
||||
func (w *WafLogAPi) ExportDBApi(c *gin.Context) {
|
||||
if global.GWAF_CAN_EXPORT_DOWNLOAD_LOG == false {
|
||||
global.GQEQUE_MESSAGE_DB.Enqueue(innerbean.OperatorMessageInfo{
|
||||
BaseMessageInfo: innerbean.BaseMessageInfo{OperaType: "导出失败"},
|
||||
OperaCnt: "当前不允许导出",
|
||||
// 使用操作结果消息格式
|
||||
serverName := global.GWAF_CUSTOM_SERVER_NAME
|
||||
if serverName == "" {
|
||||
serverName = "未命名服务器"
|
||||
}
|
||||
global.GQEQUE_MESSAGE_DB.Enqueue(innerbean.OpResultMessageInfo{
|
||||
BaseMessageInfo: innerbean.BaseMessageInfo{
|
||||
OperaType: "导出失败",
|
||||
Server: serverName,
|
||||
},
|
||||
Msg: "当前不允许导出",
|
||||
Success: "false",
|
||||
})
|
||||
response.FailWithMessage("当前不允许导出", c)
|
||||
return
|
||||
@@ -121,9 +130,18 @@ func (w *WafLogAPi) ExportDBApi(c *gin.Context) {
|
||||
}
|
||||
func (w *WafLogAPi) DownloadApi(c *gin.Context) {
|
||||
if global.GWAF_CAN_EXPORT_DOWNLOAD_LOG == false {
|
||||
global.GQEQUE_MESSAGE_DB.Enqueue(innerbean.OperatorMessageInfo{
|
||||
BaseMessageInfo: innerbean.BaseMessageInfo{OperaType: "下载失败"},
|
||||
OperaCnt: "当前不允许下载",
|
||||
// 使用操作结果消息格式
|
||||
serverName := global.GWAF_CUSTOM_SERVER_NAME
|
||||
if serverName == "" {
|
||||
serverName = "未命名服务器"
|
||||
}
|
||||
global.GQEQUE_MESSAGE_DB.Enqueue(innerbean.OpResultMessageInfo{
|
||||
BaseMessageInfo: innerbean.BaseMessageInfo{
|
||||
OperaType: "下载失败",
|
||||
Server: serverName,
|
||||
},
|
||||
Msg: "当前不允许下载",
|
||||
Success: "false",
|
||||
})
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"message": "当前不允许下载"})
|
||||
return
|
||||
|
||||
@@ -11,12 +11,13 @@ import (
|
||||
"SamWaf/model/common/response"
|
||||
"SamWaf/model/request"
|
||||
response2 "SamWaf/model/response"
|
||||
"SamWaf/service/waf_service"
|
||||
"SamWaf/utils"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/pquerna/otp/totp"
|
||||
"time"
|
||||
)
|
||||
|
||||
type WafLoginApi struct {
|
||||
@@ -68,7 +69,8 @@ func (w *WafLoginApi) LoginApi(c *gin.Context) {
|
||||
hitCounter++
|
||||
global.GCACHE_WAFCACHE.SetWithTTl(cacheKey, hitCounter, time.Duration(global.GCONFIG_RECORD_LOGIN_LIMIT_MINTUTES)*time.Minute)
|
||||
|
||||
loginError := fmt.Sprintf("输入密码错误超过次数限制,IP:%s 归属地区:%s", clientIP, clientCountry)
|
||||
clientCountryStr := strings.Join(clientCountry, ",")
|
||||
loginError := fmt.Sprintf("输入密码错误超过次数限制,IP:%s 归属地区:%s", clientIP, clientCountryStr)
|
||||
wafSysLog := model.WafSysLog{
|
||||
BaseOrm: baseorm.BaseOrm{
|
||||
Id: uuid.GenUUID(),
|
||||
@@ -82,9 +84,19 @@ func (w *WafLoginApi) LoginApi(c *gin.Context) {
|
||||
}
|
||||
global.GQEQUE_LOG_DB.Enqueue(&wafSysLog)
|
||||
|
||||
global.GQEQUE_MESSAGE_DB.Enqueue(innerbean.OperatorMessageInfo{
|
||||
BaseMessageInfo: innerbean.BaseMessageInfo{OperaType: "登录错误"},
|
||||
OperaCnt: loginError,
|
||||
// 使用新的系统错误消息格式
|
||||
serverName := global.GWAF_CUSTOM_SERVER_NAME
|
||||
if serverName == "" {
|
||||
serverName = "未命名服务器"
|
||||
}
|
||||
global.GQEQUE_MESSAGE_DB.Enqueue(innerbean.SystemErrorMessageInfo{
|
||||
BaseMessageInfo: innerbean.BaseMessageInfo{
|
||||
OperaType: "登录错误",
|
||||
Server: serverName,
|
||||
},
|
||||
ErrorType: "登录失败",
|
||||
ErrorMsg: fmt.Sprintf("密码错误超限,IP:%s (%s)", clientIP, clientCountryStr),
|
||||
Time: time.Now().Format("2006-01-02 15:04:05"),
|
||||
})
|
||||
response.FailWithMessage("登录密码错误", c)
|
||||
return
|
||||
@@ -133,13 +145,27 @@ func (w *WafLoginApi) LoginApi(c *gin.Context) {
|
||||
//令牌记录到cache里
|
||||
global.GCACHE_WAFCACHE.SetWithTTl(enums.CACHE_TOKEN+accessToken, *tokenInfo, time.Duration(global.GCONFIG_RECORD_TOKEN_EXPIRE_MINTUTES)*time.Minute)
|
||||
|
||||
//通知信息
|
||||
noticeStr := fmt.Sprintf("登录IP:%s 归属地区:%s", clientIP, clientCountry)
|
||||
global.GQEQUE_MESSAGE_DB.Enqueue(innerbean.OperatorMessageInfo{
|
||||
BaseMessageInfo: innerbean.BaseMessageInfo{OperaType: "登录信息"},
|
||||
OperaCnt: noticeStr,
|
||||
//通知信息(使用新的消息格式,通过队列统一处理)
|
||||
currentTime := time.Now().Format("2006-01-02 15:04:05")
|
||||
clientCountryStr := strings.Join(clientCountry, ",")
|
||||
noticeStr := fmt.Sprintf("登录IP:%s 归属地区:%s", clientIP, clientCountryStr)
|
||||
|
||||
// 将用户登录信息加入消息队列(新格式)
|
||||
serverName := global.GWAF_CUSTOM_SERVER_NAME
|
||||
if serverName == "" {
|
||||
serverName = "未命名服务器"
|
||||
}
|
||||
global.GQEQUE_MESSAGE_DB.Enqueue(innerbean.UserLoginMessageInfo{
|
||||
BaseMessageInfo: innerbean.BaseMessageInfo{
|
||||
OperaType: "登录信息",
|
||||
Server: serverName,
|
||||
},
|
||||
Username: bean.LoginAccount,
|
||||
Ip: clientIP + " (" + clientCountryStr + ")",
|
||||
Time: currentTime,
|
||||
})
|
||||
|
||||
// 记录系统日志
|
||||
wafSysLog := model.WafSysLog{
|
||||
BaseOrm: baseorm.BaseOrm{
|
||||
Id: uuid.GenUUID(),
|
||||
@@ -153,16 +179,6 @@ func (w *WafLoginApi) LoginApi(c *gin.Context) {
|
||||
}
|
||||
global.GQEQUE_LOG_DB.Enqueue(&wafSysLog)
|
||||
|
||||
// 发送用户登录通知
|
||||
go func() {
|
||||
title, content := waf_service.WafNotifySenderServiceApp.FormatUserLoginMessage(
|
||||
bean.LoginAccount,
|
||||
clientIP,
|
||||
time.Now().Format("2006-01-02 15:04:05"),
|
||||
)
|
||||
waf_service.WafNotifySenderServiceApp.SendNotification(model.MSG_TYPE_USER_LOGIN, title, content)
|
||||
}()
|
||||
|
||||
response.OkWithDetailed(response2.LoginRep{
|
||||
AccessToken: tokenInfo.AccessToken,
|
||||
}, "登录成功", c)
|
||||
|
||||
@@ -63,6 +63,74 @@ type OpResultMessageInfo struct {
|
||||
Success string `json:"success"`
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
用户登录信息
|
||||
*/
|
||||
type UserLoginMessageInfo struct {
|
||||
BaseMessageInfo
|
||||
Username string `json:"username"` // 用户名
|
||||
Ip string `json:"ip"` // 登录IP
|
||||
Time string `json:"time"` // 登录时间
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
攻击信息
|
||||
*/
|
||||
type AttackInfoMessageInfo struct {
|
||||
BaseMessageInfo
|
||||
AttackType string `json:"attack_type"` // 攻击类型
|
||||
Url string `json:"url"` // 攻击URL
|
||||
Ip string `json:"ip"` // 攻击IP
|
||||
Time string `json:"time"` // 攻击时间
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
周报信息
|
||||
*/
|
||||
type WeeklyReportMessageInfo struct {
|
||||
BaseMessageInfo
|
||||
TotalRequests int64 `json:"total_requests"` // 总请求数
|
||||
BlockedRequests int64 `json:"blocked_requests"` // 拦截请求数
|
||||
WeekRange string `json:"week_range"` // 周期范围
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
SSL证书过期信息
|
||||
*/
|
||||
type SSLExpireMessageInfo struct {
|
||||
BaseMessageInfo
|
||||
Domain string `json:"domain"` // 域名
|
||||
ExpireTime string `json:"expire_time"` // 过期时间
|
||||
DaysLeft int `json:"days_left"` // 剩余天数
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
系统错误信息
|
||||
*/
|
||||
type SystemErrorMessageInfo struct {
|
||||
BaseMessageInfo
|
||||
ErrorType string `json:"error_type"` // 错误类型
|
||||
ErrorMsg string `json:"error_msg"` // 错误信息
|
||||
Time string `json:"time"` // 发生时间
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
IP封禁信息
|
||||
*/
|
||||
type IPBanMessageInfo struct {
|
||||
BaseMessageInfo
|
||||
Ip string `json:"ip"` // IP地址
|
||||
Reason string `json:"reason"` // 封禁原因
|
||||
Duration int `json:"duration"` // 封禁时长(分钟)
|
||||
Time string `json:"time"` // 封禁时间
|
||||
}
|
||||
|
||||
func (r RuleMessageInfo) ToFormat() map[string]*wechat.DataItem {
|
||||
Data := map[string]*wechat.DataItem{}
|
||||
Data["domain"] = &wechat.DataItem{
|
||||
|
||||
@@ -19,6 +19,8 @@ type NotifySubscription struct {
|
||||
|
||||
// 消息类型常量
|
||||
const (
|
||||
MSG_TYPE_RULE_TRIGGER = "rule_trigger" // 规则触发
|
||||
MSG_TYPE_OPERATION_NOTICE = "operation_notice" // 操作通知
|
||||
MSG_TYPE_USER_LOGIN = "user_login" // 用户登录
|
||||
MSG_TYPE_ATTACK_INFO = "attack_info" // 攻击信息
|
||||
MSG_TYPE_WEEKLY_REPORT = "weekly_report" // 周报
|
||||
|
||||
@@ -3,6 +3,7 @@ package waf_service
|
||||
import (
|
||||
"SamWaf/common/zlog"
|
||||
"SamWaf/global"
|
||||
"SamWaf/innerbean"
|
||||
"SamWaf/model"
|
||||
"SamWaf/wafnotify/dingtalk"
|
||||
"SamWaf/wafnotify/feishu"
|
||||
@@ -126,3 +127,95 @@ func (receiver *WafNotifySenderService) FormatIPBanMessage(ip, reason, time stri
|
||||
content := fmt.Sprintf("**IP地址:** %s\n\n**封禁原因:** %s\n\n**封禁时长:** %d分钟\n\n**封禁时间:** %s", ip, reason, duration, time)
|
||||
return title, content
|
||||
}
|
||||
|
||||
// ========== 消息映射方法:将旧消息结构转换为新格式 ==========
|
||||
|
||||
// FormatMessageByType 根据消息类型格式化消息(统一入口)
|
||||
func (receiver *WafNotifySenderService) FormatMessageByType(messageInfo interface{}) (messageType, title, content string) {
|
||||
switch msg := messageInfo.(type) {
|
||||
case innerbean.RuleMessageInfo:
|
||||
return receiver.FormatRuleMessage(msg)
|
||||
case innerbean.OperatorMessageInfo:
|
||||
return receiver.FormatOperatorMessage(msg)
|
||||
case innerbean.UserLoginMessageInfo:
|
||||
return receiver.FormatUserLoginMessageFromBean(msg)
|
||||
case innerbean.AttackInfoMessageInfo:
|
||||
return receiver.FormatAttackInfoMessageFromBean(msg)
|
||||
case innerbean.WeeklyReportMessageInfo:
|
||||
return receiver.FormatWeeklyReportMessageFromBean(msg)
|
||||
case innerbean.SSLExpireMessageInfo:
|
||||
return receiver.FormatSSLExpireMessageFromBean(msg)
|
||||
case innerbean.SystemErrorMessageInfo:
|
||||
return receiver.FormatSystemErrorMessageFromBean(msg)
|
||||
case innerbean.IPBanMessageInfo:
|
||||
return receiver.FormatIPBanMessageFromBean(msg)
|
||||
default:
|
||||
return "", "", ""
|
||||
}
|
||||
}
|
||||
|
||||
// FormatRuleMessage 格式化规则触发消息(映射旧的 RuleMessageInfo)
|
||||
func (receiver *WafNotifySenderService) FormatRuleMessage(msg innerbean.RuleMessageInfo) (string, string, string) {
|
||||
messageType := "rule_trigger" // 规则触发类型
|
||||
title := "安全规则触发通知"
|
||||
content := fmt.Sprintf("**操作类型:** %s\n\n**服务器:** %s\n\n**域名:** %s\n\n**规则信息:** %s\n\n**IP地址:** %s",
|
||||
msg.OperaType,
|
||||
msg.Server,
|
||||
msg.Domain,
|
||||
msg.RuleInfo,
|
||||
msg.Ip)
|
||||
return messageType, title, content
|
||||
}
|
||||
|
||||
// FormatOperatorMessage 格式化操作消息(映射旧的 OperatorMessageInfo)
|
||||
func (receiver *WafNotifySenderService) FormatOperatorMessage(msg innerbean.OperatorMessageInfo) (string, string, string) {
|
||||
messageType := "operation_notice" // 操作通知类型
|
||||
title := "操作通知"
|
||||
content := fmt.Sprintf("**操作类型:** %s\n\n**服务器:** %s\n\n**操作内容:** %s",
|
||||
msg.OperaType,
|
||||
msg.Server,
|
||||
msg.OperaCnt)
|
||||
return messageType, title, content
|
||||
}
|
||||
|
||||
// FormatUserLoginMessageFromBean 格式化用户登录消息(从Bean)
|
||||
func (receiver *WafNotifySenderService) FormatUserLoginMessageFromBean(msg innerbean.UserLoginMessageInfo) (string, string, string) {
|
||||
messageType := "user_login" // 用户登录类型
|
||||
title, content := receiver.FormatUserLoginMessage(msg.Username, msg.Ip, msg.Time)
|
||||
return messageType, title, content
|
||||
}
|
||||
|
||||
// FormatAttackInfoMessageFromBean 格式化攻击信息消息(从Bean)
|
||||
func (receiver *WafNotifySenderService) FormatAttackInfoMessageFromBean(msg innerbean.AttackInfoMessageInfo) (string, string, string) {
|
||||
messageType := "attack_info" // 攻击信息类型
|
||||
title, content := receiver.FormatAttackInfoMessage(msg.AttackType, msg.Url, msg.Ip, msg.Time)
|
||||
return messageType, title, content
|
||||
}
|
||||
|
||||
// FormatWeeklyReportMessageFromBean 格式化周报消息(从Bean)
|
||||
func (receiver *WafNotifySenderService) FormatWeeklyReportMessageFromBean(msg innerbean.WeeklyReportMessageInfo) (string, string, string) {
|
||||
messageType := "weekly_report" // 周报类型
|
||||
title, content := receiver.FormatWeeklyReportMessage(msg.TotalRequests, msg.BlockedRequests, msg.WeekRange)
|
||||
return messageType, title, content
|
||||
}
|
||||
|
||||
// FormatSSLExpireMessageFromBean 格式化SSL证书过期消息(从Bean)
|
||||
func (receiver *WafNotifySenderService) FormatSSLExpireMessageFromBean(msg innerbean.SSLExpireMessageInfo) (string, string, string) {
|
||||
messageType := "ssl_expire" // SSL证书过期类型
|
||||
title, content := receiver.FormatSSLExpireMessage(msg.Domain, msg.ExpireTime, msg.DaysLeft)
|
||||
return messageType, title, content
|
||||
}
|
||||
|
||||
// FormatSystemErrorMessageFromBean 格式化系统错误消息(从Bean)
|
||||
func (receiver *WafNotifySenderService) FormatSystemErrorMessageFromBean(msg innerbean.SystemErrorMessageInfo) (string, string, string) {
|
||||
messageType := "system_error" // 系统错误类型
|
||||
title, content := receiver.FormatSystemErrorMessage(msg.ErrorType, msg.ErrorMsg, msg.Time)
|
||||
return messageType, title, content
|
||||
}
|
||||
|
||||
// FormatIPBanMessageFromBean 格式化IP封禁消息(从Bean)
|
||||
func (receiver *WafNotifySenderService) FormatIPBanMessageFromBean(msg innerbean.IPBanMessageInfo) (string, string, string) {
|
||||
messageType := "ip_ban" // IP封禁类型
|
||||
title, content := receiver.FormatIPBanMessage(msg.Ip, msg.Reason, msg.Time, msg.Duration)
|
||||
return messageType, title, content
|
||||
}
|
||||
|
||||
@@ -69,8 +69,15 @@ func (waf *WafEngine) ApplySSLOrder(chanType int, bean model.SslOrder) {
|
||||
}
|
||||
global.GQEQUE_LOG_DB.Enqueue(&wafSysLog)
|
||||
|
||||
serverName := global.GWAF_CUSTOM_SERVER_NAME
|
||||
if serverName == "" {
|
||||
serverName = "未命名服务器"
|
||||
}
|
||||
global.GQEQUE_MESSAGE_DB.Enqueue(innerbean.OperatorMessageInfo{
|
||||
BaseMessageInfo: innerbean.BaseMessageInfo{OperaType: "SSL证书申请失败"},
|
||||
BaseMessageInfo: innerbean.BaseMessageInfo{
|
||||
OperaType: "SSL证书申请失败",
|
||||
Server: serverName,
|
||||
},
|
||||
OperaCnt: sslError,
|
||||
})
|
||||
} else {
|
||||
@@ -94,8 +101,15 @@ func (waf *WafEngine) ApplySSLOrder(chanType int, bean model.SslOrder) {
|
||||
}
|
||||
global.GQEQUE_LOG_DB.Enqueue(&wafSysLog)
|
||||
|
||||
serverName := global.GWAF_CUSTOM_SERVER_NAME
|
||||
if serverName == "" {
|
||||
serverName = "未命名服务器"
|
||||
}
|
||||
global.GQEQUE_MESSAGE_DB.Enqueue(innerbean.OperatorMessageInfo{
|
||||
BaseMessageInfo: innerbean.BaseMessageInfo{OperaType: "SSL证书申请成功"},
|
||||
BaseMessageInfo: innerbean.BaseMessageInfo{
|
||||
OperaType: "SSL证书申请成功",
|
||||
Server: serverName,
|
||||
},
|
||||
OperaCnt: sslSuccess,
|
||||
})
|
||||
}
|
||||
@@ -122,8 +136,15 @@ func (waf *WafEngine) ApplySSLOrder(chanType int, bean model.SslOrder) {
|
||||
}
|
||||
global.GQEQUE_LOG_DB.Enqueue(&wafSysLog)
|
||||
|
||||
serverName := global.GWAF_CUSTOM_SERVER_NAME
|
||||
if serverName == "" {
|
||||
serverName = "未命名服务器"
|
||||
}
|
||||
global.GQEQUE_MESSAGE_DB.Enqueue(innerbean.OperatorMessageInfo{
|
||||
BaseMessageInfo: innerbean.BaseMessageInfo{OperaType: "SSL证书申请失败"},
|
||||
BaseMessageInfo: innerbean.BaseMessageInfo{
|
||||
OperaType: "SSL证书申请失败",
|
||||
Server: serverName,
|
||||
},
|
||||
OperaCnt: sslError,
|
||||
})
|
||||
}
|
||||
@@ -162,8 +183,15 @@ func (waf *WafEngine) ApplySSLOrder(chanType int, bean model.SslOrder) {
|
||||
}
|
||||
global.GQEQUE_LOG_DB.Enqueue(&wafSysLog)
|
||||
|
||||
serverName := global.GWAF_CUSTOM_SERVER_NAME
|
||||
if serverName == "" {
|
||||
serverName = "未命名服务器"
|
||||
}
|
||||
global.GQEQUE_MESSAGE_DB.Enqueue(innerbean.OperatorMessageInfo{
|
||||
BaseMessageInfo: innerbean.BaseMessageInfo{OperaType: "SSL证书续期失败"},
|
||||
BaseMessageInfo: innerbean.BaseMessageInfo{
|
||||
OperaType: "SSL证书续期失败",
|
||||
Server: serverName,
|
||||
},
|
||||
OperaCnt: sslError,
|
||||
})
|
||||
} else {
|
||||
@@ -187,8 +215,15 @@ func (waf *WafEngine) ApplySSLOrder(chanType int, bean model.SslOrder) {
|
||||
}
|
||||
global.GQEQUE_LOG_DB.Enqueue(&wafSysLog)
|
||||
|
||||
serverName := global.GWAF_CUSTOM_SERVER_NAME
|
||||
if serverName == "" {
|
||||
serverName = "未命名服务器"
|
||||
}
|
||||
global.GQEQUE_MESSAGE_DB.Enqueue(innerbean.OperatorMessageInfo{
|
||||
BaseMessageInfo: innerbean.BaseMessageInfo{OperaType: "SSL证书续期成功"},
|
||||
BaseMessageInfo: innerbean.BaseMessageInfo{
|
||||
OperaType: "SSL证书续期成功",
|
||||
Server: serverName,
|
||||
},
|
||||
OperaCnt: sslSuccess,
|
||||
})
|
||||
}
|
||||
@@ -214,8 +249,15 @@ func (waf *WafEngine) ApplySSLOrder(chanType int, bean model.SslOrder) {
|
||||
}
|
||||
global.GQEQUE_LOG_DB.Enqueue(&wafSysLog)
|
||||
|
||||
serverName := global.GWAF_CUSTOM_SERVER_NAME
|
||||
if serverName == "" {
|
||||
serverName = "未命名服务器"
|
||||
}
|
||||
global.GQEQUE_MESSAGE_DB.Enqueue(innerbean.OperatorMessageInfo{
|
||||
BaseMessageInfo: innerbean.BaseMessageInfo{OperaType: "SSL证书续期失败"},
|
||||
BaseMessageInfo: innerbean.BaseMessageInfo{
|
||||
OperaType: "SSL证书续期失败",
|
||||
Server: serverName,
|
||||
},
|
||||
OperaCnt: sslError,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -338,10 +338,21 @@ func (waf *WafEngine) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
// 检测是否已经被CC封禁
|
||||
ccCacheKey := enums.CACHE_CCVISITBAN_PRE + weblogbean.NetSrcIp
|
||||
if global.GCACHE_WAFCACHE.IsKeyExist(ccCacheKey) {
|
||||
visitIPError := fmt.Sprintf("当前IP已经被CC封禁,IP:%s 归属地区:%s", weblogbean.NetSrcIp, region)
|
||||
global.GQEQUE_MESSAGE_DB.Enqueue(innerbean.OperatorMessageInfo{
|
||||
BaseMessageInfo: innerbean.BaseMessageInfo{OperaType: "CC封禁提醒"},
|
||||
OperaCnt: visitIPError,
|
||||
// 使用新的IP封禁消息格式
|
||||
regionStr := strings.Join(region, ",")
|
||||
serverName := global.GWAF_CUSTOM_SERVER_NAME
|
||||
if serverName == "" {
|
||||
serverName = "未命名服务器"
|
||||
}
|
||||
global.GQEQUE_MESSAGE_DB.Enqueue(innerbean.IPBanMessageInfo{
|
||||
BaseMessageInfo: innerbean.BaseMessageInfo{
|
||||
OperaType: "CC封禁提醒",
|
||||
Server: serverName,
|
||||
},
|
||||
Ip: weblogbean.NetSrcIp + " (" + regionStr + ")",
|
||||
Reason: "CC攻击,访问频次过高",
|
||||
Duration: 0, // CC封禁时长由配置决定
|
||||
Time: time.Now().Format("2006-01-02 15:04:05"),
|
||||
})
|
||||
EchoErrorInfo(w, r, &weblogbean, "", "当前IP由于访问频次太高暂时无法访问", hostTarget, waf.HostTarget[waf.HostCode[global.GWAF_GLOBAL_HOST_CODE]], false)
|
||||
return
|
||||
|
||||
@@ -7,9 +7,11 @@ import (
|
||||
"SamWaf/global"
|
||||
"SamWaf/innerbean"
|
||||
"SamWaf/model"
|
||||
"SamWaf/service/waf_service"
|
||||
"SamWaf/utils"
|
||||
"SamWaf/wafsec"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@@ -31,84 +33,27 @@ func ProcessMessageDequeEngine() {
|
||||
zlog.Error("来得信息未空")
|
||||
continue
|
||||
}
|
||||
messageinfo := popFront.(interface{})
|
||||
isCanSend := false
|
||||
switch messageinfo.(type) {
|
||||
|
||||
// 处理不同类型的消息
|
||||
switch msg := popFront.(type) {
|
||||
case innerbean.RuleMessageInfo:
|
||||
rulemessage := messageinfo.(innerbean.RuleMessageInfo)
|
||||
|
||||
isCanSend = checkCanSend(rulemessage.RuleInfo)
|
||||
if isCanSend {
|
||||
if global.GWAF_NOTICE_ENABLE == false {
|
||||
zlog.Debug("通知关闭状态")
|
||||
} else {
|
||||
utils.NotifyHelperApp.SendRuleInfo(rulemessage)
|
||||
}
|
||||
if rulemessage.BaseMessageInfo.OperaType == "命中保护规则" {
|
||||
//发送websocket
|
||||
for _, ws := range global.GWebSocket.GetAllWebSocket() {
|
||||
|
||||
if ws != nil {
|
||||
msgBody, _ := json.Marshal(model.MsgDataPacket{
|
||||
MessageId: uuid.GenUUID(),
|
||||
MessageType: "命中保护规则",
|
||||
MessageData: rulemessage.RuleInfo + rulemessage.Ip,
|
||||
MessageAttach: nil,
|
||||
MessageDateTime: time.Now().Format("2006-01-02 15:04:05"),
|
||||
MessageUnReadStatus: true,
|
||||
})
|
||||
encryptStr, _ := wafsec.AesEncrypt(msgBody, global.GWAF_COMMUNICATION_KEY)
|
||||
//写入ws数据
|
||||
msgBytes, err := json.Marshal(model.MsgPacket{
|
||||
MsgCode: "200",
|
||||
MsgDataPacket: encryptStr,
|
||||
MsgCmdType: "Info",
|
||||
})
|
||||
err = ws.WriteMessage(1, msgBytes)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break
|
||||
handleRuleMessage(msg)
|
||||
case innerbean.OperatorMessageInfo:
|
||||
operatorMessage := messageinfo.(innerbean.OperatorMessageInfo)
|
||||
isCanSend = checkCanSend(operatorMessage.OperaType)
|
||||
if !isCanSend {
|
||||
continue
|
||||
}
|
||||
utils.NotifyHelperApp.SendNoticeInfo(operatorMessage)
|
||||
//发送websocket
|
||||
for _, ws := range global.GWebSocket.GetAllWebSocket() {
|
||||
|
||||
if ws != nil {
|
||||
msgBody, _ := json.Marshal(model.MsgDataPacket{
|
||||
MessageId: uuid.GenUUID(),
|
||||
MessageType: operatorMessage.OperaType,
|
||||
MessageData: operatorMessage.OperaCnt,
|
||||
MessageAttach: nil,
|
||||
MessageDateTime: time.Now().Format("2006-01-02 15:04:05"),
|
||||
MessageUnReadStatus: true,
|
||||
})
|
||||
encryptStr, _ := wafsec.AesEncrypt(msgBody, global.GWAF_COMMUNICATION_KEY)
|
||||
//写入ws数据
|
||||
msgBytes, err := json.Marshal(model.MsgPacket{
|
||||
MsgCode: "200",
|
||||
MsgDataPacket: encryptStr,
|
||||
MsgCmdType: "Info",
|
||||
})
|
||||
err = ws.WriteMessage(1, msgBytes)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
handleOperatorMessage(msg)
|
||||
case innerbean.UserLoginMessageInfo:
|
||||
handleUserLoginMessage(msg)
|
||||
case innerbean.AttackInfoMessageInfo:
|
||||
handleAttackInfoMessage(msg)
|
||||
case innerbean.WeeklyReportMessageInfo:
|
||||
handleWeeklyReportMessage(msg)
|
||||
case innerbean.SSLExpireMessageInfo:
|
||||
handleSSLExpireMessage(msg)
|
||||
case innerbean.SystemErrorMessageInfo:
|
||||
handleSystemErrorMessage(msg)
|
||||
case innerbean.IPBanMessageInfo:
|
||||
handleIPBanMessage(msg)
|
||||
case innerbean.ExportResultMessageInfo:
|
||||
exportResult := messageinfo.(innerbean.ExportResultMessageInfo)
|
||||
exportResult := msg
|
||||
//发送websocket
|
||||
for _, ws := range global.GWebSocket.GetAllWebSocket() {
|
||||
if ws != nil {
|
||||
@@ -135,10 +80,9 @@ func ProcessMessageDequeEngine() {
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
case innerbean.UpdateResultMessageInfo:
|
||||
//升级结果
|
||||
updatemessage := messageinfo.(innerbean.UpdateResultMessageInfo)
|
||||
updatemessage := msg
|
||||
//发送websocket
|
||||
for _, ws := range global.GWebSocket.GetAllWebSocket() {
|
||||
if ws != nil {
|
||||
@@ -165,10 +109,9 @@ func ProcessMessageDequeEngine() {
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
case innerbean.OpResultMessageInfo:
|
||||
//操作实时结果
|
||||
updatemessage := messageinfo.(innerbean.OpResultMessageInfo)
|
||||
updatemessage := msg
|
||||
//发送websocket
|
||||
for _, ws := range global.GWebSocket.GetAllWebSocket() {
|
||||
if ws != nil {
|
||||
@@ -195,9 +138,8 @@ func ProcessMessageDequeEngine() {
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
case innerbean.SystemStatsData:
|
||||
statsData := messageinfo.(innerbean.SystemStatsData)
|
||||
statsData := msg
|
||||
//发送websocket
|
||||
for _, ws := range global.GWebSocket.GetAllWebSocket() {
|
||||
if ws != nil {
|
||||
@@ -224,8 +166,6 @@ func ProcessMessageDequeEngine() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
@@ -237,7 +177,8 @@ func ProcessMessageDequeEngine() {
|
||||
// checkCanSend 抑止发送频率
|
||||
func checkCanSend(key string) bool {
|
||||
isCanSend := false
|
||||
if strings.HasPrefix(key, "SSL证书申请") {
|
||||
// SSL证书相关的消息(包括申请和续期)都直接发送,不受频率限制
|
||||
if strings.HasPrefix(key, "SSL证书") {
|
||||
isCanSend = true
|
||||
return isCanSend
|
||||
}
|
||||
@@ -268,3 +209,151 @@ func checkCanSend(key string) bool {
|
||||
}
|
||||
return isCanSend
|
||||
}
|
||||
|
||||
// ========== 各类消息处理函数(保持队列+WebSocket方式,集成新的通知系统) ==========
|
||||
|
||||
// handleRuleMessage 处理规则触发消息
|
||||
func handleRuleMessage(msg innerbean.RuleMessageInfo) {
|
||||
isCanSend := checkCanSend(msg.RuleInfo)
|
||||
if !isCanSend {
|
||||
return
|
||||
}
|
||||
|
||||
// 1. 发送到新的通知订阅系统(使用格式化后的消息)
|
||||
messageType, title, content := waf_service.WafNotifySenderServiceApp.FormatRuleMessage(msg)
|
||||
waf_service.WafNotifySenderServiceApp.SendNotification(messageType, title, content)
|
||||
|
||||
// 2. 保留原有的通知方式(兼容旧系统)
|
||||
if global.GWAF_NOTICE_ENABLE {
|
||||
utils.NotifyHelperApp.SendRuleInfo(msg)
|
||||
} else {
|
||||
zlog.Debug("通知关闭状态")
|
||||
}
|
||||
|
||||
// 3. 发送到 WebSocket(保持原有功能)
|
||||
if msg.BaseMessageInfo.OperaType == "命中保护规则" {
|
||||
sendToWebSocket("命中保护规则", msg.RuleInfo+msg.Ip, nil, "Info")
|
||||
}
|
||||
}
|
||||
|
||||
// handleOperatorMessage 处理操作消息
|
||||
func handleOperatorMessage(msg innerbean.OperatorMessageInfo) {
|
||||
isCanSend := checkCanSend(msg.OperaType)
|
||||
if !isCanSend {
|
||||
return
|
||||
}
|
||||
|
||||
// 1. 发送到新的通知订阅系统
|
||||
messageType, title, content := waf_service.WafNotifySenderServiceApp.FormatOperatorMessage(msg)
|
||||
waf_service.WafNotifySenderServiceApp.SendNotification(messageType, title, content)
|
||||
|
||||
// 2. 保留原有的通知方式
|
||||
utils.NotifyHelperApp.SendNoticeInfo(msg)
|
||||
|
||||
// 3. 发送到 WebSocket
|
||||
sendToWebSocket(msg.OperaType, msg.OperaCnt, nil, "Info")
|
||||
}
|
||||
|
||||
// handleUserLoginMessage 处理用户登录消息
|
||||
func handleUserLoginMessage(msg innerbean.UserLoginMessageInfo) {
|
||||
// 1. 发送到新的通知订阅系统
|
||||
messageType, title, content := waf_service.WafNotifySenderServiceApp.FormatUserLoginMessageFromBean(msg)
|
||||
waf_service.WafNotifySenderServiceApp.SendNotification(messageType, title, content)
|
||||
|
||||
// 2. 发送到 WebSocket
|
||||
wsContent := fmt.Sprintf("用户 %s 从 %s 登录", msg.Username, msg.Ip)
|
||||
sendToWebSocket("用户登录", wsContent, nil, "Info")
|
||||
}
|
||||
|
||||
// handleAttackInfoMessage 处理攻击信息消息
|
||||
func handleAttackInfoMessage(msg innerbean.AttackInfoMessageInfo) {
|
||||
isCanSend := checkCanSend(msg.AttackType)
|
||||
if !isCanSend {
|
||||
return
|
||||
}
|
||||
|
||||
// 1. 发送到新的通知订阅系统
|
||||
messageType, title, content := waf_service.WafNotifySenderServiceApp.FormatAttackInfoMessageFromBean(msg)
|
||||
waf_service.WafNotifySenderServiceApp.SendNotification(messageType, title, content)
|
||||
|
||||
// 2. 发送到 WebSocket
|
||||
wsContent := fmt.Sprintf("检测到 %s 攻击,来源IP: %s", msg.AttackType, msg.Ip)
|
||||
sendToWebSocket("攻击告警", wsContent, nil, "Info")
|
||||
}
|
||||
|
||||
// handleWeeklyReportMessage 处理周报消息
|
||||
func handleWeeklyReportMessage(msg innerbean.WeeklyReportMessageInfo) {
|
||||
// 1. 发送到新的通知订阅系统
|
||||
messageType, title, content := waf_service.WafNotifySenderServiceApp.FormatWeeklyReportMessageFromBean(msg)
|
||||
waf_service.WafNotifySenderServiceApp.SendNotification(messageType, title, content)
|
||||
|
||||
// 2. 发送到 WebSocket
|
||||
wsContent := fmt.Sprintf("周期: %s, 总请求: %d, 拦截: %d", msg.WeekRange, msg.TotalRequests, msg.BlockedRequests)
|
||||
sendToWebSocket("WAF周报", wsContent, nil, "Info")
|
||||
}
|
||||
|
||||
// handleSSLExpireMessage 处理SSL证书过期消息
|
||||
func handleSSLExpireMessage(msg innerbean.SSLExpireMessageInfo) {
|
||||
// SSL证书消息总是发送(不受频率限制)
|
||||
// 1. 发送到新的通知订阅系统
|
||||
messageType, title, content := waf_service.WafNotifySenderServiceApp.FormatSSLExpireMessageFromBean(msg)
|
||||
waf_service.WafNotifySenderServiceApp.SendNotification(messageType, title, content)
|
||||
|
||||
// 2. 发送到 WebSocket
|
||||
wsContent := fmt.Sprintf("域名 %s 的SSL证书将在 %d 天后过期", msg.Domain, msg.DaysLeft)
|
||||
sendToWebSocket("SSL证书过期提醒", wsContent, nil, "Info")
|
||||
}
|
||||
|
||||
// handleSystemErrorMessage 处理系统错误消息
|
||||
func handleSystemErrorMessage(msg innerbean.SystemErrorMessageInfo) {
|
||||
// 1. 发送到新的通知订阅系统
|
||||
messageType, title, content := waf_service.WafNotifySenderServiceApp.FormatSystemErrorMessageFromBean(msg)
|
||||
waf_service.WafNotifySenderServiceApp.SendNotification(messageType, title, content)
|
||||
|
||||
// 2. 发送到 WebSocket
|
||||
wsContent := fmt.Sprintf("系统错误: %s - %s", msg.ErrorType, msg.ErrorMsg)
|
||||
sendToWebSocket("系统错误", wsContent, nil, "Info")
|
||||
}
|
||||
|
||||
// handleIPBanMessage 处理IP封禁消息
|
||||
func handleIPBanMessage(msg innerbean.IPBanMessageInfo) {
|
||||
isCanSend := checkCanSend(msg.Ip)
|
||||
if !isCanSend {
|
||||
return
|
||||
}
|
||||
|
||||
// 1. 发送到新的通知订阅系统
|
||||
messageType, title, content := waf_service.WafNotifySenderServiceApp.FormatIPBanMessageFromBean(msg)
|
||||
waf_service.WafNotifySenderServiceApp.SendNotification(messageType, title, content)
|
||||
|
||||
// 2. 发送到 WebSocket
|
||||
wsContent := fmt.Sprintf("IP %s 已被封禁,原因: %s", msg.Ip, msg.Reason)
|
||||
sendToWebSocket("IP封禁通知", wsContent, nil, "Info")
|
||||
}
|
||||
|
||||
// sendToWebSocket 统一的 WebSocket 发送函数
|
||||
func sendToWebSocket(messageType, messageData string, messageAttach interface{}, cmdType string) {
|
||||
for _, ws := range global.GWebSocket.GetAllWebSocket() {
|
||||
if ws != nil {
|
||||
msgBody, _ := json.Marshal(model.MsgDataPacket{
|
||||
MessageId: uuid.GenUUID(),
|
||||
MessageType: messageType,
|
||||
MessageData: messageData,
|
||||
MessageAttach: messageAttach,
|
||||
MessageDateTime: time.Now().Format("2006-01-02 15:04:05"),
|
||||
MessageUnReadStatus: true,
|
||||
})
|
||||
encryptStr, _ := wafsec.AesEncrypt(msgBody, global.GWAF_COMMUNICATION_KEY)
|
||||
msgBytes, err := json.Marshal(model.MsgPacket{
|
||||
MsgCode: "200",
|
||||
MsgDataPacket: encryptStr,
|
||||
MsgCmdType: cmdType,
|
||||
})
|
||||
err = ws.WriteMessage(1, msgBytes)
|
||||
if err != nil {
|
||||
zlog.Debug("发送websocket错误", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,15 @@ func TaskStatusNotify() {
|
||||
if err == nil {
|
||||
noticeStr := fmt.Sprintf("今日访问量:%d 今天恶意访问量:%d 昨日恶意访问量:%d", statHomeInfo.VisitCountOfToday, statHomeInfo.AttackCountOfToday, statHomeInfo.AttackCountOfYesterday)
|
||||
|
||||
serverName := global.GWAF_CUSTOM_SERVER_NAME
|
||||
if serverName == "" {
|
||||
serverName = "未命名服务器"
|
||||
}
|
||||
global.GQEQUE_MESSAGE_DB.Enqueue(innerbean.OperatorMessageInfo{
|
||||
BaseMessageInfo: innerbean.BaseMessageInfo{OperaType: "汇总通知"},
|
||||
BaseMessageInfo: innerbean.BaseMessageInfo{
|
||||
OperaType: "汇总通知",
|
||||
Server: serverName,
|
||||
},
|
||||
OperaCnt: noticeStr,
|
||||
})
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user