IBM Cloud Docs
使用字段、函数和表达式

使用字段、函数和表达式

除操作外,字段和表达式也是 WAF 自定义规则的构建模块。 在定义匹配自定义规则时要使用的标准时,这两个元素会共同发挥作用。

字段

CIS 收到 HTTP 请求时,会检查该请求,并生成与之相匹配的字段表。 此字段表在当前请求处理期间始终存在。 请将其视为用于保存要与表达式匹配的请求属性的一个表。

每个字段值可以源自不同位置,例如:

  • 原语属性,直接从流量中获取 - 例如 http.request.uri.path
  • 派生值,由转换、组合或基本操作产生--例如,将 http.request.uri.path 的值全部小写并作为另一个字段的字段。
  • 计算机值,通过查找、计算或其他智能功能生成 - 例如,由用于检查相关原语值和派生值的机器学习过程动态计算的 cf.threat_score

可用字段

可用字段
字段名称 Type 示例值 注释
http.cookie 字符串 session=A12345;-background=light 作为字符串的整个 cookie
http.host 字符串 www.example.com 在完整请求 URI 中使用的主机名
http.referer 字符串 HTTP 引用头
http.request.full_uri 字符串 https://www.example.com/articles/index?section=539061&expand=comments Web 服务器收到的完整 URI(不包括未发送到 Web 服务器的 #fragment
http.request.method 字符串 POST HTTP 方法(大写)
http.request.uri 字符串 /articles/index?section=539061&expand=comments 请求的绝对 URI
http.request.uri.path 字符串 /articles/index 请求的路径
http.request.uri.query 字符串 section=539061&expand=comments 整个查询字符串,去掉定界前缀“?”
http.user_agent 字符串 Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36 整个 HTTP 用户代理
http.x_forwarded_for 字符串 完整的 X-Forwarded-For HTTP 标头
ip.src IP 地址 93.155.208.22 客户端 TCP IP 地址,可酌情调整以反映原始客户端的真实客户端 IP(例如,使用 HTTP 标头,如 X-Forwarded-For 或 X-Real-IP)
ip.geoip.asnum 编号 222 自治系统 (AS) 编号
ip.geoip.country 字符串 GB 2位字母的国家代码
ssl 布尔值 客户机的 HTTP 连接是否已加密

这些标准字段遵循 Wireshark 显示字段引用的命名约定。 然而,前面的示例值可能存在一些细微的差异。

除标准字段外,还提供以下 Cloudflare 定义的字段:

可用的Cloudflare字段
字段名称 Type 示例值 注释
cf.client.bot 布尔值 此字段指示请求是否来自已知机器人或搜寻器,无论其意图好坏。
cf.threat_score 编号 0-100 之间的值 此字段表示风险分数,0 指示由 Cloudflare 确定的低风险。 超过 10 的数值可能代表垃圾邮件发送者或机器人,而超过 40 的数值则代表互联网上的不良行为者。 60 以上的值很少见,因此要调整 WAF 自定义规则,挑战 10 以上的值,并阻止 50 以上的值。

函数

自定义规则语言有许多转换字段的功能。

表达式生成器目前不支持这些功能。

自定义规则功能
函数名 自变量类型 返回类型 用法示例 注释
lower 字符串 字符串 lower(http.host) == "www.example.com" 将字符串字段转换为小写。 仅转换大写 ASCII 字节,其他每个字节都保留原样。
upper 字符串 字符串 upper(http.host) == "www.example.com" 将字符串字段转换为大写。 仅转换小写 ASCII 字节,其他每个字节都保留原样。

表达式

表达式根据与入局流量的匹配情况返回 true 或 false。 例如:

http.host eq "www.example.com" and ip.src in 92.182.212.0/24

在本例中,两个单一表达式组成了一个复合表达式。 请将每个单一表达式视为一个条件。 每个条件会分别进行求值,然后再应用任何逻辑以确定复合表达式的最终结果。

从第一个单一表达式中可以看出,它包含了

  • 字段 - http.host
  • 比较运算符 - eq
  • 值 - "www.example.com"

并非所有条件都具有相同的结构。 在下一部分中将讨论使用不同结构的其他示例。

比较运算符

以下比较运算符可用于表达式:

表达式的比较运算符
英语 类 C 描述
eq == 等于
ne != 不等于
lt < 小于
le <= 小于或等于
GT > 大于
ge >= 大于或等于
contains 完全包含
匹配 ~ Re2 激发的正则表达式
in 值出现在一组值中。 支持使用"... "符号的范围。
not ! 请参阅“布尔值比较”
bitwise_and & 比较位字段值

目前,表达式生成器只支持英文运算符。

一个表达式可能包含英语和类似 C 语言的混合运算符。 例如,ip.src eq 93.184.216.34 等效于 ip.src == 93.184.216.34

某些比较运算符适用于基于类型的特定字段。 以下矩阵提供了可用于各种字段类型的运算符的示例:

字段的比较运算符
英语 类 C 字符串 IP 地址 编号
eq == http.request.uri.path eq "/articles/2008/" ip.src eq 93.184.216.0 cf.threat_score eq 10
ne != http.request.uri.path ne "/articles/2010/" ip.src ne 93.184.216.0 cf.threat_score ne 60
lt < http.request.uri.path lt "/articles/2009/" cf.threat_score lt 10
le <= http.request.uri.path le "/articles/2008/" cf.threat_score le 20
GT > http.request.uri.path gt "/articles/2006/" cf.threat_score gt 25
ge >= 大于或等于 cf.threat_score ge 60
contains http.request.uri.path contains "/articles/"
匹配 ~ http.request.uri.path ~ " [^/articles/2007-8/$] "
in http.request.method in { "HEAD" "GET" } ip.src in { 93.184.216.0 93.184.216.1 } cf.threat_score in {0 2 10}

对使用字符串值的表达式求值是区分大小写的。 因此,自定义规则可能需要定义多个测试条件。 企业客户可以使用包含匹配运算符的正则表达式来捕获单个表达式的多个变体。

布尔值比较

对于布尔值类型的字段(例如,ssl),当求值为 true 条件时,该字段本身会出现在表达式中。 对于 false 条件,会应用 not 运算符。

布尔值比较
True
ssl not ssl

复合表达

可以通过使用逻辑运算符对两个或更多单一表达式分组,以创建复合表达式。

复合表达
英语 类 C 描述 示例 优先顺序
not ! 逻辑 NOT not ( http.host eq "www.example.com" and ip.src in 93.184.216.0/24 ) 1
&& 逻辑 AND http.host eq "www.example.com" and ip.src in 93.184.216.0/24 2
xor ^^ 逻辑 XOR http.host eq "www.example.com" xor ip.src in 93.184.216.0/24 3
|| 逻辑 OR http.host eq "www.example.com" or ip.src in 93.184.216.0/24 4

要更改优先顺序,可以使用括号对表达式分组。 不使用括号时,表达式将根据标准优先顺序隐式分组:

ssl and http.request.uri.path eq /login or http.request.uri.path eq /oauth

应用显式分组:

(ssl and http.request.uri.path eq /login) or http.request.uri.path eq /oauth

给予优先顺序或使用括号:

ssl and (http.request.uri.path eq /login or http.request.uri.path eq /oauth)

请注意,虽然 not 用于分组,但只能用于否定单个比较。 例如,not ip.src eq 93.184.216.0 等效于 not (ip.src eq 93.184.216.0)

最后,还可以否定分组表达式:

not (http.request.method eq "POST" and http.request.uri.path eq "/login")

与 Wireshark 显示过滤器的偏差

自定义规则表达式的灵感来自 Wireshark 显示过滤器。 但是,实现在以下方面有偏差:

  • 对于 CIDR IP 等同性测试,Wireshark 允许使用格式为 ip.src == 1.2.3.0/24 的范围,而 CIS 仅支持使用单个 IP 地址进行等同性测试。 要比较 CIDR,请使用 in 运算符;例如,ip.src in {1.2.3.0/24}
  • 在 Wireshark 中,ssl 是一个协议字段,包含各种类型的数百个其他字段,可用于在多个方面进行比较。 不过,在自定义规则中,ssl 是一个单一的布尔字段,用于确定从客户端到 CIS 的连接是否经过加密。
  • 不支持 slice 运算符。
  • 并非所有函数都受支持。 目前,len()count() 不支持。