☰
BFE mod_waf 规则文件 waf_rule.data 配置指南:从字段结构到 RuleBashCmd 检测原理
2026/10/10 1:37:06 网站建设 项目流程
  • 后端
  • 网络/通信
  • 云原生

【免费下载链接】bfe

A modern layer 7 load balancer from baidu

项目地址:https://gitcode.com/gh_mirrors/bf/bfe
点击查看免费下载

waf_rule.data是 BFE 七层负载均衡器中mod_waf模块的规则配置文件,它按产品线(product)组织 WAF 检测规则,决定哪些请求需要经过 Bash 命令注入(Shellshock 类攻击)检测,以及命中后是直接阻断还是仅记录。阅读本文后,你将掌握该文件的 JSON 结构、每个字段的校验规则与合法取值,并能结合源码理解规则从加载、校验到执行命中的完整链路,从而为自己的产品线正确配置 WAF 防护策略。

1. 文件定位:mod_waf 的规则入口

在 BFE 中,mod_waf模块由两个配置文件共同驱动:

  • waf_rule.data:WAF 检测规则文件,即本文主题,声明"哪些产品线的哪些请求走哪些检测规则、命中后如何处理";
  • mod_waf.conf:模块基础配置,其中Basic.ProductRulePath指定规则文件的路径,默认值为mod_waf/waf_rule.data,见 mod_waf.conf 配置说明。

仓库自带的示例配置位于 conf/mod_waf/mod_waf.conf 与 conf/mod_waf/waf_rule.data,可作为实际部署时的参考模板。

2. 配置项详解

waf_rule.data采用 JSON 格式,顶层包含Version与Config两个字段。下表为原文档给出的完整字段定义:

配置项类型含义必填补充说明合法性条件
VersionString配置文件版本号Y通常为时间戳,如20190101000000类型为 Version
ConfigObject各产品线的 WAF 规则Ykey 为产品线名称-
Config{k}String产品线名称Y--
Config{v}Array该产品线下的 WAF 规则列表Y--
Config{v}[]Object一条 WAF 规则Y--
Config{v}[].CondString匹配请求的条件表达式Y语法见 条件表达式语法-
Config{v}[].BlockRules[]String命中后直接阻断的规则名列表NBlockRules与CheckRules至少配置其一规则名必须被当前模块支持
Config{v}[].CheckRules[]String命中后仅记录的规则名列表NBlockRules与CheckRules至少配置其一规则名必须被当前模块支持

对几个关键字段的进一步说明:

  • Version:标识配置文件版本,属于通用类型 Version,通常使用时间戳字符串。结合源码看,加载时若缺失Version字段会直接报错no version(见下文校验流程)。
  • Cond:条件表达式,由 BFE 内置的条件原语(condition primitive)经&&、||、!等运算符组合而成,返回布尔值。配置示例中使用的default_t()即内置原语之一,表示无条件匹配(恒为真)。完整原语清单与运算优先级见 条件表达式语法。
  • BlockRules 与 CheckRules:两者至少配置其一,且其中的规则名必须被mod_waf当前实现所支持,否则配置校验失败(错误信息为unknow rule,见下文)。

3. 支持的 WAF 规则

原文档当前列出了如下内置规则:

规则名含义
RuleBashCmdBash 命令注入检测

该规则由源码 bfe_modules/mod_waf/waf_rule/rule_bash_cmd.go 实现,用于检测针对 GNU Bash 远程代码执行漏洞(即 Shellshock,CVE-2014-6271 与 CVE-2014-7169)的利用流量,规则思路参考了 OWASP ModSecurity Core Rule Set 中的 932170/932171 规则。

从源码可以了解其检测原理:RuleBashCmdExe实现了WafRule接口,其Check方法遍历请求的所有 Header 值,逐个调用checkHeaderValue判定:

  1. 使用checkHeaderValuePrefix匹配形如( ) {的前缀(允许空格/Tab 分隔),对应漏洞利用特征() { :; };的开头部分;
  2. 若前缀命中,再用checkHeaderValueContent检查}之后首个非空白字符是否为;,对应漏洞利用中紧随函数定义的分号命令序列。

因此,形如() { :; }; echo; echo; rm -rf ./*的请求头值会触发该规则。需要注意的是,规则名称的注册表位于 bfe_modules/mod_waf/waf_rule/waf_rule.go:implementedRule映射定义了RuleBashCmd与实现的对应关系,IsValidRule即依据该映射判断配置中的规则名是否合法。若后续模块扩展新规则,只需在该映射中注册即可被waf_rule.data引用。

4. 配置示例

原文档给出的完整示例(这也是仓库中 bfe_modules/mod_waf/testdata/mod_waf/waf_rule.data 与 conf/mod_waf/waf_rule.data 的实际内容):

{ "Version": "2019-12-10184356", "Config": { "example_product": [ { "Cond": "default_t()", "BlockRules": [ "RuleBashCmd" ] } ] } }

逐层解读:

  • Version:2019-12-10184356,该文件版本的标识;
  • Config.example_product:为产品线example_product配置规则列表;
  • 规则对象中Cond: "default_t()"表示对所有进入该产品线的请求都执行检测;
  • BlockRules: ["RuleBashCmd"]表示命中 Bash 命令注入特征时直接阻断请求;同时因为未配置CheckRules,命中行为只有"阻断"一种。

5. 源码级解析:加载与校验流程

waf_rule.data的加载入口是 bfe_modules/mod_waf/waf_rule_load.go 中的ProductWafRuleConfLoad函数,整体流程为:打开文件 → JSON 解码 → 逐层校验 → 转换编译,任何一步失败都会返回错误并拒绝加载。

数据结构:文件先解码到带指针的productWafRuleConfigFile结构(Version *string、Config *productWafRuleFile),其内层wafRuleFile即对应 JSON 中单条规则的三个字段Cond、BlockRules、CheckRules。

校验逻辑(productWafRuleConfFileCheck及各层 Check 函数)依次保证:

  1. Version与Config均不能缺失,否则报no version/no Config;
  2. 每个产品线的规则列表不能为空(product[%s] has empty rulelist);
  3. 单条规则的Cond不能为空字符串;
  4. BlockRules与CheckRules不能同时为空(对应原文档"至少配置其一"的要求,错误信息为block rules and check rule both empty);
  5. BlockRules/CheckRules中的每个规则名必须通过waf_rule.IsValidRule检查,否则报unknow rule。

转换编译:校验通过后,wafRuleConvert会调用condition.Build(ruleFile.Cond)把条件表达式字符串编译为可执行的condition.Condition对象,并将规则名列表拷贝到运行时的wafRule结构(Cond condition.Condition、BlockRules []string、CheckRules []string)。也就是说,运行阶段不再解析字符串,条件表达式在加载期已被预编译,检测时直接求值。

仓库中 bfe_modules/mod_waf/testdata 下的多组用例正好覆盖了上述校验分支,可作为配置自查清单:

  • waf_rule_invalid_json.data:JSON 格式非法;
  • waf_rule_no_version.data:缺少Version;
  • waf_rule_no_config.data:缺少Config;
  • waf_rule_invalid_cond.data:Cond为空或表达式非法;
  • waf_rule_both_empty.data:BlockRules与CheckRules同时为空;
  • waf_rule_both_nil.data:两个规则列表均为 nil;
  • waf_rule_both_block_rules.data/waf_rule_both_check_rules.data:仅配置BlockRules或仅配置CheckRules的合法场景。

6. 规则匹配与命中处理:从加载表到 Handler

加载完成的规则存放在WarRuleTable(bfe_modules/mod_waf/waf_rule_table.go)中,该表用读写锁保护version与productRule两个字段,Update用于热更新整份规则(支持配置热加载),Search(product)按产品线取出规则列表。

实际检测由 bfe_modules/mod_waf/waf_handler.go 中的wafHandler执行:

  • HandleBlockJob(rule, req)与HandleCheckJob(rule, req)分别对应BlockRules与CheckRules的处理入口;
  • 两者都先通过IsValidRule二次确认规则名合法,然后构造wafJob并调用doJob;
  • doJob从WafRuleTable取出规则实现,调用其Check方法完成检测,随后job.SetHit(hit)记录命中结果,并通过wafLogger.DumpLog(job)输出 WAF 明细日志。

检测所需的数据来自 bfe_modules/mod_waf/waf_rule/rule_request_info.go 中的RuleRequestInfo,它由bfe_basic.Request转换而来,携带请求方法、HTTP 版本、Header 集合、URI 及解析后的查询参数等字段,供各规则实现消费。

7. 命中行为验证:测试用例给出的直观样例

bfe_modules/mod_waf/mod_waf_test.go 中的TestModuleWafHandleWaf用最直观的方式演示了"检测→阻断"的完整效果:

  • 构造产品线为unittest的普通请求,handleWaf返回BfeHandlerGoOn(请求继续放行);
  • 同一请求将user-agent头设置为() { :; }; echo; echo; rm -rf ./*(典型 Shellshock 利用载荷),handleWaf返回BfeHandlerFinish(请求被 WAF 命中并终止处理)。

该测试同时演示了规则热更新:加载waf_rule_check.data(将RuleBashCmd移入CheckRules)后,同样的攻击载荷再次访问时返回BfeHandlerGoOn,即由"阻断"切换为"仅记录",与BlockRules/CheckRules的语义完全一致。

8. 配置实践要点

综合原文档与源码实现,落地waf_rule.data时建议注意以下几点:

  1. 先定产品线维度:Config的 key 必须与 BFE 路由识别出的产品线名称一致,规则才能命中对应流量;
  2. 条件表达式尽量收敛:Cond支持任意内置原语组合,生产环境建议结合req_host_in、req_method_in、req_path_in等原语缩小检测范围,避免对全量流量开启检测带来的性能开销;
  3. 区分阻断与记录:新规则上线或策略调整期,可先用CheckRules观察命中日志,确认无误后再切换为BlockRules;
  4. 规则名必须存在:配置中出现的每个规则名都必须位于implementedRule注册表(当前仅RuleBashCmd),否则整份配置将加载失败;
  5. 校验先行:可利用 bfe_modules/mod_waf/waf_rule_load_test.go 与 testdata 中的正反例,理解各类失败场景的报错信息,减少线上配置事故。

通过本文,你已经完整掌握了waf_rule.data的字段语义、合法取值、加载校验链路以及RuleBashCmd的检测原理,可以在此基础上为不同产品线制定差异化的 WAF 防护策略。

  • 后端
  • 网络/通信
  • 云原生

【免费下载链接】bfe

A modern layer 7 load balancer from baidu

项目地址:https://gitcode.com/gh_mirrors/bf/bfe
点击查看免费下载

相关推荐

上一篇:专家容量控制:提升makeMoE训练效率的5大关键技术实现
下一篇:Nativefier 扩展文档贡献者指南:贡献方式与规范

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询