Merge pull request #458 from samwafgo/feat_rule_headers

feat:add rule header
This commit is contained in:
samwafgo
2025-09-26 08:53:10 +08:00
committed by GitHub
2 changed files with 108 additions and 0 deletions
+42
View File
@@ -1,5 +1,7 @@
package innerbean
import "strings"
type WebLog struct {
WafInnerDFlag string `json:"waf_inner_dflag"` //日志队列处理方式
HOST string `json:"host"`
@@ -49,6 +51,46 @@ type WebLog struct {
LogOnlyMode int `json:"log_only_mode"` //是否只记录日志 1 是 0 不是
}
// GetHeaderValue 从HEADER字段中提取指定header的值
// headerName: 要查找的header名称(不区分大小写)
// 返回: header的值,如果不存在则返回空字符串
func (w *WebLog) GetHeaderValue(headerName string) string {
if w.HEADER == "" || headerName == "" {
return ""
}
// 将header名称转换为小写进行比较
headerName = strings.ToLower(headerName)
// 按行分割header字符串
lines := strings.Split(w.HEADER, "\r\n")
for _, line := range lines {
// 跳过空行
if strings.TrimSpace(line) == "" {
continue
}
// 查找冒号分隔符
colonIndex := strings.Index(line, ":")
if colonIndex == -1 {
continue
}
// 提取header名称和值
key := strings.ToLower(strings.TrimSpace(line[:colonIndex]))
value := strings.TrimSpace(line[colonIndex+1:])
// 如果找到匹配的header,返回其值
if key == headerName {
return value
}
}
// 未找到指定的header,返回空字符串
return ""
}
// 在 GORM 的 Model 方法中定义复合索引
func (WebLog) TableName() string {
return "web_logs"
+66
View File
@@ -59,6 +59,72 @@ rule R1ca0bf1c409e4c1b823c995afe7733b0 "禁止一些robotahrefs" salience 10 {
}
// TestWebLog_GetHeaderValue 测试WebLog的GetHeaderValue方法
func TestWebLog_GetHeaderValue(t *testing.T) {
//加载主机对于的规则
ruleHelper := &RuleHelper{}
ruleHelper.InitRuleEngine()
drls := `
rule R1ca0bf1c409e4c1b823c995afe7733b0 "判断header里面的组合信息" salience 10 {
when
MF.GetHeaderValue("Accept").Contains("text/plain") == True && MF.GetHeaderValue("X-Real-IP").Contains("10.0.0.1") == True
then
Retract("R1ca0bf1c409e4c1b823c995afe7733b0");
} `
var ruleconfigs []model.Rules
rule := model.Rules{
HostCode: "",
RuleCode: "",
RuleName: "我是规则",
RuleContent: drls,
RuleContentJSON: "",
RuleVersionName: "",
RuleVersion: 0,
IsPublicRule: 0,
IsManualRule: 0,
RuleStatus: 0,
}
ruleconfigs = append(ruleconfigs, rule)
ruleHelper.LoadRules(ruleconfigs)
//weblog
logs := innerbean.WebLog{
USER_AGENT: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.2.5 (KHTML, like Gecko) Version/8.0.2 Safari/600.2.5 (Amazonbot/0.1; +https://developer.amazon.com/support/amazonbot)",
HEADER: "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36\r\n" +
"Accept: application/json, text/plain, */*\r\n" +
"Accept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\n" +
"Accept-Encoding: gzip, deflate, br\r\n" +
"Content-Type: application/json\r\n" +
"Content-Length: 123\r\n" +
"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9\r\n" +
"X-Forwarded-For: 10.0.0.1, 192.168.1.1\r\n" +
"X-Real-IP: 10.0.0.1\r\n" +
"X-Custom-Header: custom-value-123\r\n" +
"Cookie: session_id=abc123; user_pref=dark_mode\r\n" +
"Referer: https://example.com/login\r\n" +
"Origin: https://example.com\r\n" +
"Connection: keep-alive\r\n" +
"Cache-Control: no-cache\r\n",
}
ruleMatchs, err := ruleHelper.Match("MF", &logs)
if err == nil {
if len(ruleMatchs) > 0 {
fmt.Printf("header里面的组合信息匹配成功,规则描述:%s\n", ruleMatchs[0].RuleDescription)
rulestr := ""
for _, v := range ruleMatchs {
rulestr = rulestr + v.RuleDescription + ","
}
fmt.Printf("%s", rulestr)
return
} else {
fmt.Printf("header里面的组合信息匹配失败\n")
}
}
}
// TestAllRulesInDirectory 测试rule_tests目录下所有规则文件
func TestAllRulesInDirectory(t *testing.T) {
// 初始化规则引擎