- 后端
- 网络/通信
- 云原生
【免费下载链接】bfe
A modern layer 7 load balancer from baidu
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两个字段。下表为原文档给出的完整字段定义:
| 配置项 | 类型 | 含义 | 必填 | 补充说明 | 合法性条件 |
|---|---|---|---|---|---|
| Version | String | 配置文件版本号 | Y | 通常为时间戳,如20190101000000 | 类型为 Version |
| Config | Object | 各产品线的 WAF 规则 | Y | key 为产品线名称 | - |
| Config{k} | String | 产品线名称 | Y | - | - |
| Config{v} | Array | 该产品线下的 WAF 规则列表 | Y | - | - |
| Config{v}[] | Object | 一条 WAF 规则 | Y | - | - |
| Config{v}[].Cond | String | 匹配请求的条件表达式 | Y | 语法见 条件表达式语法 | - |
| Config{v}[].BlockRules | []String | 命中后直接阻断的规则名列表 | N | BlockRules与CheckRules至少配置其一 | 规则名必须被当前模块支持 |
| Config{v}[].CheckRules | []String | 命中后仅记录的规则名列表 | N | BlockRules与CheckRules至少配置其一 | 规则名必须被当前模块支持 |
对几个关键字段的进一步说明:
- Version:标识配置文件版本,属于通用类型 Version,通常使用时间戳字符串。结合源码看,加载时若缺失
Version字段会直接报错no version(见下文校验流程)。 - Cond:条件表达式,由 BFE 内置的条件原语(condition primitive)经
&&、||、!等运算符组合而成,返回布尔值。配置示例中使用的default_t()即内置原语之一,表示无条件匹配(恒为真)。完整原语清单与运算优先级见 条件表达式语法。 - BlockRules 与 CheckRules:两者至少配置其一,且其中的规则名必须被
mod_waf当前实现所支持,否则配置校验失败(错误信息为unknow rule,见下文)。
3. 支持的 WAF 规则
原文档当前列出了如下内置规则:
| 规则名 | 含义 |
|---|---|
| RuleBashCmd | Bash 命令注入检测 |
该规则由源码 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判定:
- 使用
checkHeaderValuePrefix匹配形如( ) {的前缀(允许空格/Tab 分隔),对应漏洞利用特征() { :; };的开头部分; - 若前缀命中,再用
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 函数)依次保证:
Version与Config均不能缺失,否则报no version/no Config;- 每个产品线的规则列表不能为空(
product[%s] has empty rulelist); - 单条规则的
Cond不能为空字符串; BlockRules与CheckRules不能同时为空(对应原文档"至少配置其一"的要求,错误信息为block rules and check rule both empty);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时建议注意以下几点:
- 先定产品线维度:
Config的 key 必须与 BFE 路由识别出的产品线名称一致,规则才能命中对应流量; - 条件表达式尽量收敛:
Cond支持任意内置原语组合,生产环境建议结合req_host_in、req_method_in、req_path_in等原语缩小检测范围,避免对全量流量开启检测带来的性能开销; - 区分阻断与记录:新规则上线或策略调整期,可先用
CheckRules观察命中日志,确认无误后再切换为BlockRules; - 规则名必须存在:配置中出现的每个规则名都必须位于
implementedRule注册表(当前仅RuleBashCmd),否则整份配置将加载失败; - 校验先行:可利用 bfe_modules/mod_waf/waf_rule_load_test.go 与 testdata 中的正反例,理解各类失败场景的报错信息,减少线上配置事故。
通过本文,你已经完整掌握了waf_rule.data的字段语义、合法取值、加载校验链路以及RuleBashCmd的检测原理,可以在此基础上为不同产品线制定差异化的 WAF 防护策略。
- 后端
- 网络/通信
- 云原生
【免费下载链接】bfe
A modern layer 7 load balancer from baidu
相关推荐
BFE mod_waf 规则配置文件 waf_rule.data 完全指南:语法、字段、校验与实战
BFE mod_waf 规则配置文件 waf_rule.data 完全指南:语法、字段、校验与实战 waf_rule.data 是 BFE 七层负载均衡器中 m
后端网络/通信云原生BFE mod_waf 配置详解:从基础配置到 WAF 规则文件的完整实战指南
BFE mod_waf 配置详解:从基础配置到 WAF 规则文件的完整实战指南 导读 : mod_waf 是 BFE(Baidu Front End,百度自研的
后端网络/通信云原生BFE mod_waf 模块实战指南:基于规则的 WAF 检测、配置与指标监控
BFE mod_waf 模块实战指南:基于规则的 WAF 检测、配置与指标监控 BFE 的 mod_waf 模块为七层负载均衡器提供 Web 应用防火墙(WAF
后端网络/通信云原生
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考