创建和查看 Cloud Armor 安全政策规则

每个 Google Cloud Armor 安全政策规则都有优先级、匹配条件和操作。Cloud Armor 会执行与请求匹配的最高优先级规则的操作。优先级低于最高优先级匹配规则的规则不会进行评估,即使它们具有相同的匹配条件也是如此。

每个安全政策规则都支持两种类型的匹配条件:

  • 基本匹配条件包含 IP 地址列表或 IP 地址范围列表。 基本匹配条件是在通过 Google Cloud CLI 创建规则时使用 --src-ip-ranges 标志定义的。
  • 高级匹配条件包含一个最多具有 5 个子表达式的表达式,可匹配传入请求的各种属性。高级匹配条件是在通过 Google Cloud CLI 创建规则时使用 --expression 标志定义的。

本页面介绍了如何创建和查看安全政策规则,并提供了 Cloud Armor 自定义规则语言参考文档,您可以使用该语言在高级匹配条件中编写表达式。Cloud Armor 自定义规则语言是通用表达式语言 (CEL) 的子集。

使用 Cloud Armor 自定义规则语言编写的表达式需要两个组成部分:

  • 属性:要检查的数据
  • 操作:如何使用数据

例如,以下表达式在操作 inIpRange 中使用属性 origin.ip 和 198.51.100.0/24。在这种情况下,如果 origin.ip 在 198.51.100.0/24 IP 地址范围内,则表达式返回 true。

inIpRange(origin.ip, '198.51.100.0/24')

尽管前面的示例表达式仅匹配客户端 IP 地址,但当您在 Cloud Armor 安全政策规则中使用该示例表达式时,该规则在配额方面会被视为具有高级匹配条件的规则。如需了解详情,请参阅 Cloud Armor 配额和限制。

创建安全政策规则

按照本部分中的步骤将规则添加到 Cloud Armor 安全政策。

控制台

  1. 在 Google Cloud 控制台中,前往 Cloud Armor 政策页面。

    前往“Cloud Armor 政策”页面

  2. 点击安全政策的名称以打开政策详情页面,然后点击规则标签页。

  3. 点击添加规则。

  4. 可选:输入规则的说明。

  5. 选择模式:

    • 基本模式:根据 IP 地址或 IP 范围允许或拒绝流量。
    • 高级模式:根据规则表达式允许或拒绝流量。
  6. 在匹配字段中,指定规则适用的条件:

    • 基本模式:输入 1 到 10 个要与规则匹配的 IP 地址范围。您最多可以添加 10 个 IP 地址范围。如需了解限制,请参阅 Cloud Armor 配额和限制。

    • 高级模式:

      • 匹配条件构建器(预览版):使用可视化构建器创建表达式,而无需编写原始 CEL 代码。组合和分组条件,并应用字符串转换。请参阅使用匹配条件构建器。
      • 匹配条件编辑器:输入要根据传入请求进行评估的表达式。如需了解详情,请参阅操作和属性。
  7. 在操作列表中,选择允许或拒绝。

  8. 如果您要配置拒绝规则,请在响应代码列表中选择一个响应代码。

  9. 如需为规则启用预览模式,请选择启用。

  10. 在优先级字段中,输入 0 到 2,147,483,646 之间的整数。 Cloud Armor 会按优先级顺序评估规则,从 0(最高)到 2,147,483,647(最低)。默认规则的优先级为 2,147,483,647。

  11. 点击 Add(添加)。

gcloud

使用 gcloud compute security-policies rules create PRIORITY 命令。将 PRIORITY 替换为政策中规则的优先级:

gcloud compute security-policies rules create PRIORITY \
    --security-policy POLICY_NAME \
    --description DESCRIPTION \
    --src-ip-ranges IP_RANGES | --expression EXPRESSION \
    --action=[ allow | deny-403 | deny-404 | deny-502 ] \
    --preview

例如,以下命令会添加一个优先级为 1000 的规则,以阻止来自 IP 地址范围 192.0.2.0/24 和 198.51.100.0/24 的流量:

gcloud compute security-policies rules create 1000 \
    --security-policy my-policy \
    --description "block traffic from 192.0.2.0/24 and 198.51.100.0/24" \
    --src-ip-ranges "192.0.2.0/24","198.51.100.0/24" \
    --action "deny-403"

使用 --expression 标志指定条件。以下命令将添加一条规则,以允许来自 IP 地址 1.2.3.4 的流量,并且在 User-Agent 标头中包含字符串 example:

gcloud compute security-policies rules create 1000 \
    --security-policy my-policy \
    --expression "inIpRange(origin.ip, '1.2.3.4/32') && has(request.headers['user-agent']) && request.headers['user-agent'].contains('example')" \
    --action allow \
    --description "Block User-Agent 'example'"

以下命令会添加一条规则,以便在请求的 Cookie 包含特定值时阻止请求:

gcloud compute security-policies rules create 1000 \
    --security-policy my-policy \
    --expression "has(request.headers['cookie']) && request.headers['cookie'].contains('80=SomeValue')" \
    --action deny-403 \
    --description "Cookie Block"

以下命令将添加一条规则,以阻止来自地区 AU 的请求:

gcloud compute security-policies rules create 1000 \
    --security-policy my-policy \
    --expression "origin.region_code == 'AU'" \
    --action deny-403 \
    --description "AU block"

以下命令会添加一条规则,以阻止来自不在指定 IP 范围内的 AU 区域的请求:

gcloud compute security-policies rules create 1000 \
    --security-policy my-policy \
    --expression "origin.region_code == \"AU\" && !inIpRange(origin.ip, '1.2.3.0/24')" \
    --action deny-403 \
    --description "country and IP block"

以下命令会添加一条规则,以阻止 URI 与正则表达式匹配的请求:

gcloud compute security-policies rules create 1000 \
    --security-policy my-policy \
    --expression "request.path.matches('/example_path/')" \
    --action deny-502 \
    --description "regex block"

以下命令会添加一条规则,以便在 user-id 标头的 Base64 解码值包含特定值时阻止请求:

gcloud compute security-policies rules create 1000 \
    --security-policy my-policy \
    --expression "has(request.headers['user-id']) && request.headers['user-id'].base64Decode().contains('myValue')" \
    --action deny-403 \
    --description "country and IP block"

以下命令将添加一条规则,该规则使用 OWASP 核心规则集 (CRS) 4.22 中的预配置表达式集来缓解 SQL 注入 (SQLi) 攻击:

gcloud compute security-policies rules create 1000 \
    --security-policy my-policy \
    --expression "evaluatePreconfiguredWaf('sqli-v422-stable')" \
    --action deny-403

使用匹配条件构建器

匹配条件构建器是 Google Cloud 控制台中的一个可视化界面,可帮助您创建复杂的 Cloud Armor 规则表达式,而无需编写通用表达式语言 (CEL) 代码。您可以使用构建器的结构化界面来组合条件和分组逻辑,而无需编写代码,这有助于避免语法错误,并更好地直观呈现规则结构。该构建工具支持扁平列表和嵌套逻辑,最多可支持五级表达式。在配置规则以帮助保护多云后端或混合部署时,您可以使用此工具,因为您可能需要在路由流量之前检查特定的请求属性。

匹配条件构建器的功能

匹配条件构建器包含以下功能:

  • 逻辑和嵌套:使用 AND 和 OR 运算符组合多个条件。该构建器支持对最多五个表达式进行分组和嵌套。
  • 字符串转换:对于基于字符串的属性(例如 request.path 或 request.headers),在评估前应用转换来对数据进行标准化。支持的转换包括:
    • 小写和大写
    • Base64 解码
    • 网址解码和网址解码 (Unicode)
    • UTF-8 转 Unicode
  • 双向解析:在可视化匹配条件构建器和原始文本匹配条件编辑器之间切换。界面会自动将原始 CEL 代码解析为可视化块。
  • 函数支持:构建器为基于函数的表达式(例如预配置的 WAF 规则、地址组和威胁情报)提供界面控件。

限制

匹配条件构建器是用于创建高级规则的默认界面。 如果表达式包含不受支持的逻辑(例如未知宏),则构建器会被停用。在这种情况下,请使用匹配条件编辑器中的原始文本来修改规则。

此外,构建器中某些表达式的可用性取决于项目的 Google Cloud Armor Enterprise 层级和安全政策类型。

示例表达式

下面是示例表达式。如需详细了解支持的操作和属性,请参阅操作和属性。

如果您的规则或表达式使用 ISO 3166-1 alpha-2 国家或区域代码,Cloud Armor 会独立处理每个代码。Cloud Armor 规则和表达式使用这些代码来允许或拒绝请求。

  • 以下表达式与来自 IP 地址 1.2.3.4 且在 User-Agent 标头中包含字符串 example 的请求匹配:

    inIpRange(origin.ip, '1.2.3.4/32') && has(request.headers['user-agent']) && request.headers['user-agent'].contains('example')
    

    或者,您可以使用 origin.user_ip 属性来匹配自定义客户端 IP 地址标头的 IP 地址范围:

    inIpRange(origin.user_ip, '1.2.3.4/32') && has(request.headers['user-agent']) && request.headers['user-agent'].contains('example')
    
  • 以下表达式与具有特定值的 Cookie 的请求匹配:

    has(request.headers['cookie']) && request.headers['cookie'].contains('cookie_name=cookie_value')
    
  • 以下表达式与来自 AU 区域的请求匹配:

    origin.region_code == 'AU'
    
  • 以下表达式与来自区域 AU 且不在指定 IP 范围内的请求匹配:

    origin.region_code == "AU" && !inIpRange(origin.ip, '1.2.3.0/24')
    
  • 如果 URI 与正则表达式匹配,则以下表达式与具有特定文件的编号变量路径的请求匹配:

    request.path.matches('/path/[0-9]+/target_file.html')
    
  • 如果 user-id 标头的 Base64 解码值包含特定值,则以下表达式与请求匹配:

    has(request.headers['user-id']) && request.headers['user-id'].base64Decode().contains('myValue')
    
  • 以下表达式使用 OWASP CRS 4.22 规则集中的预配置表达式集来匹配 SQLi 攻击:

    evaluatePreconfiguredWaf('sqli-v422-stable')
    

路径遍历和规范化

在基于路径的规则中对内容进行规范化处理,以管理路径遍历和编码规则,并创建避免使用大写字母或特定于内容的编码的通用规则。

当您编写使用 startsWith、endsWith 或 contains 来匹配 request.path 的规则时,请使用 lower 和 urlDecode 在匹配之前对路径进行规范化处理。这有助于防止使用网址编码或大小写变体的绕过。

例如,如需阻止对 /admin 目录的访问,请使用以下表达式:

request.path.lower().urlDecode().startsWith('/admin')

此规则会屏蔽对 /admin、/Admin、/a%64min 和其他变体的请求。

在编写使用 matches 匹配 request.path 的规则时,请在正则表达式中考虑反斜杠字符 (\)。

例如,如需阻止对 /admin 目录的访问,请使用以下表达式来阻止使用反斜杠字符 (\) 的绕过行为:

request.path.matches(r'^/\\*admin')

将此与 urlDecode 结合使用,以同时处理网址编码和反斜杠字符 (\) 绕过:

request.path.urlDecode().matches(r'^/\\*admin')

查看安全政策规则

以下部分介绍了如何列出安全政策中配置的规则以及查看可用的预配置 WAF 规则。

列出安全政策中的规则

按照本部分中的步骤列出 Cloud Armor 安全政策中的规则。

控制台

  1. 在 Google Cloud 控制台中,前往 Cloud Armor 政策页面。

    前往“Cloud Armor 政策”页面

  2. 点击特定安全政策的名称。政策详情页面会在规则标签页中显示政策规则。

gcloud

使用以下 gcloud 命令列出安全政策中的所有规则:

gcloud compute security-policies describe NAME

使用以下 gcloud 命令列出指定区域中单个安全政策的所有规则以及该政策的说明:

gcloud compute security-policies describe NAME \
  --region REGION

使用以下 gcloud 命令描述规则:

gcloud compute security-policies rules describe PRIORITY \
    --security-policy POLICY_NAME

例如,以下命令描述了安全政策 my-policy 中优先级为 1000 的规则:

gcloud compute security-policies rules describe 1000 \
    --security-policy my-policy

输出:

action: deny(403)
description: block traffic from 192.0.2.0/24 and 198.51.100.0/24
kind: compute#securityPolicyRule
match:
  srcIpRanges:
  - '192.0.2.0/24'
  - '198.51.100.0/24'
preview: false
priority: 1000

如需了解详情,请参阅 gcloud compute security-policies describe。

列出可用的预配置规则

除了您自己配置的规则之外,Cloud Armor 还提供了可在安全政策中使用的预配置规则。您可以列出预配置规则,以查看 Cloud Armor 提供的预定义应用保护规则和特征签名,例如 OWASP 核心规则集 (CRS)。这些规则包含内置特征签名,Cloud Armor 会根据这些特征签名评估传入请求。您可以使用自定义规则语言将这些预配置的规则添加到新规则或现有规则中。我们建议您尽可能使用最新的 CRS 规则版本。

gcloud

  1. 运行 gcloud compute security-policies list-preconfigured-expression-sets 命令:

    gcloud compute security-policies list-preconfigured-expression-sets
    

    以下示例展示了该命令的输出形式:

    EXPRESSION_SET
    expression-set-1
       RULE_ID                SENSITIVITY
       expression-set-1-id-1  sensitivity-value-1
       expression-set-1-id-2  sensitivity-value-2
    expression-set-2
       alias-1
       RULE_ID                SENSITIVITY
       expression-set-2-id-1  sensitivity-value-1
       expression-set-2-id-2  sensitivity-value-2
    

    以下示例包含命令的实际输出示例。 请注意,实际输出包含调整 Cloud Armor WAF 规则中列出的所有规则。

    gcloud compute security-policies list-preconfigured-expression-sets
    
    EXPRESSION_SET
    sqli-canary
        RULE_ID                          SENSITIVITY
        owasp-crs-v042200-id942120-sqli  2
        …
    xss-canary
        RULE_ID                         SENSITIVITY
        owasp-crs-v042200-id941110-xss  1
        owasp-crs-v042200-id941120-xss  2
    …
    sourceiplist-fastly
    sourceiplist-cloudflare
    sourceiplist-imperva
    

操作

以下参考信息描述了可与属性(由 x、y 和 k 表示)搭配使用来定义规则表达式的运算符。

运维 表达式 说明
相等 x == y 如果 x 等于 y,则返回 true。
相等,字符串字面量 x == "foo" 如果 x 等于指定常量字符串字面量,则返回 true。
相等,原始字符串字面量 x == R"fo'o" 如果 x 等于不解释转义序列的指定原始字符串字面量,则返回 true。原始字符串字面量便于表示自己必须使用转义序列字符的字符串。
逻辑非 !x 如果布尔值 x 为 false,则返回 true;如果布尔值 x 为 true,则返回 false。
不相等 x != y 如果 x 不等于 y,则返回 true。
串联 x + y 返回串联的字符串 xy。
逻辑与 x && y 如果 x 和 y 均为 true,则返回 true。
逻辑或 x || y 如果 x、y 或两者均为 true,则返回 true。
包含子字符串 x.contains(y) 如果字符串 x 包含子字符串 y,则返回 true。
以子字符串开头 x.startsWith(y) 如果字符串 x 以子字符串 y 开头,则返回 true。
以子字符串结尾 x.endsWith(y) 如果字符串 x 以子字符串 y 结尾,则返回 true。
正则表达式匹配 x.matches(y) 如果字符串 x 与指定的 RE2 模式 y 部分匹配,则返回 true。RE2 模式是使用停用 Unicode 功能的 RE2::Latin1 选项编译的。
范围内的 IP 地址 inIpRange(x, y) 如果 IP 地址 x 包含在 IP 范围 y 内,则返回 true。
小写 x.lower() 返回字符串 x 的小写值。x
大写 x.upper() 返回字符串 x 的大写值。x
Base64 解码值 x.base64Decode() 返回 x 的 base64 解码值;下划线 (_) 和连字符 (-) 首先被相应替换为正斜杠 (/) 和加号 (+)。如果 x 不是有效的 base64 值,则返回 ""(空字符串)。
键映射值 m['k'] 如果 k 可用,则返回字符串到字符串映射 m 中的键 k 处的值;否则返回错误。建议先使用 "has(m['k'])==true" 检查可用性。
在映射中检查键可用性 has(m['k']) 如果键 k 在映射 m 中可用,则返回 true。
转换为整数 int(x) 将字符串结果 x 转换为 int 类型。x接着可以将其用于使用标准算术运算符(例如 > 和 <=)进行整数比较。这仅适用于应该为整数的值。
长度 size(x) 返回字符串 x 的长度。x
解码网址 x.urlDecode() 返回 x 的网址解码值;%## 格式的字符序列会被替换为非 ASCII 等效字符,而 + 则被替换为空格。无效编码会按原样返回。
解码网址 (Unicode) x.urlDecodeUni() 返回 x 的网址解码值;除了 urlDecode() 之外,还会处理 %u### 格式的 Unicode 字符序列。无效编码会按原样返回。
将 utf8 转换为 Unicode x.utf8ToUnicode() 返回 UTF-8 编码 xx 的小写 Unicode 表示形式。
Exists m.exists(k, expr) 如果映射 m 中至少有一个条目满足 expr,则返回 true,其中 k 表示每个映射条目的键。
存在一个 m.exists_one(k, expr) 如果映射 m 中恰好有一个条目满足 expr,则返回 true,其中 k 表示每个映射条目的键。
全部 m.all(k, expr) 如果映射 m 中的所有条目都满足 expr,则返回 true,其中 k 表示每个映射条目的键。
过滤 m.filter(k, expr) 返回一个映射,其中仅包含映射 m 中满足 expr 的条目,其中 k 表示每个映射条目的键。
地图 m.map(k, expr) 返回一个列表,其中包含对映射 m 中的每个键求值 expr 的结果,其中 k 表示每个映射条目的键。

属性

属性表示来自传入请求的信息,例如客户端 IP 地址或请求的网址路径。

字段 类型 字段说明
origin.ip 字符串 发起请求的客户端的 IP 地址。
origin.user_ip 字符串 来源客户端的 IP 地址,由上游代理添加在 HTTP-HEADER 中。在使用此属性之前,您必须在安全政策的 advancedOptionsConfig 字段中配置 userIpRequestHeaders[] 选项,以匹配 True-Client-IP、X-Forwarded-For 或 X-Real-IP 等来源。如需了解详情,请参阅用户 IP 地址概览。

如果您未配置 userIpRequestHeaders[] 选项、配置的标头包含无效的 IP 地址值,或者配置的标头不存在,则 origin.user_ip 默认为 origin.ip。如需了解详情,请参阅 securityPolicy 资源参考文档。

origin.tls_ja4_fingerprint 字符串 如果客户端使用 HTTPS、HTTP/2 或 HTTP/3 进行连接,则为 JA4 TLS/SSL 指纹。如果不可用,则返回空字符串。
origin.tls_ja3_fingerprint 字符串 如果客户端使用 HTTPS、HTTP/2 或 HTTP/3 进行连接,则为 JA3 TLS/SSL 指纹。如果不可用,则返回空字符串。
request.headers 地图 HTTP 请求标头的字符串到字符串映射。如果某个标头有多个值,则此映射中的对应值是一个包含所有值的字符串,各值之间用英文逗号分隔。此映射中的键全部为小写。外部应用负载均衡器会检查所有接受的标头,并应用相同的标头限制。

使用 has() 检查可用性(例如 has(request.headers['header-key']) && request.headers['header-key'] != 'header-value')。

您可以遍历映射,以检查键和值。 不过,您只能在同一表达式中将 request.headers 上的映射迭代运算符(exists()、exists_one()、all()、filter() 和 map())与 request.body 或 request.params 结合使用,例如 request.body && request.headers.exists(k, k.lower().startsWith('header-prefix'))。

request.body 字符串 以原始字符串形式表示请求正文。它可以表示任何 Content-Type 的数据。它会将内容存储为字符串,而不会进行任何自动解析。
request.params 地图 附加到网址或包含在请求正文中的键值对的映射。
URI 请求:name1=value1&name2=value2
包含 Content-Type: application/json 的 JSON 请求正文:
{ "username": "johndoe", "email": "johndoe@example.com" }
包含 Content-Type: application/graphql 的 GraphQL POST 请求正文:
{ Username: "exampleUser", query: "/* other fields */" }
包含 Content-Type: application/x-www-form-urlencoded 的表单 POST 请求正文:
"username=exampleUser&email=johndoe%40example.com"
request.method 字符串 HTTP 请求方法。
request.path 字符串 所请求的 HTTP 网址路径。 当您编写与 request.path 匹配的规则时,我们建议您对路径进行规范化,以便在出现网址编码、大小写变体或反斜杠时,能够轻松匹配语法。 如需了解详情和示例,请参阅路径遍历和规范化。
request.scheme 字符串 HTTP 网址架构,例如 http 或 https。此属性的值均为小写。
request.query 字符串 HTTP 网址查询,格式为 name1=value&name2=value2,显示在 HTTP 请求的第一行中。未执行解码。
origin.region_code 字符串 与客户端 IP 相关联的 Unicode 国家/地区代码,例如 US。如果您要创建使用 ISO 3166-1 alpha 2 国家/区域代码的规则或表达式,请注意 Cloud Armor 会独立处理每个代码。Cloud Armor 规则和表达式显式使用这些区域代码来允许或拒绝请求。
origin.asn 整数 与客户端 IP 地址关联的自治系统编号 (ASN)。全局唯一 ASN 根据支持包含客户端 IP 地址的 IP 地址前缀的网络运营商确定。

表达式示例

对于这些表达式中的每一个,所采取的操作取决于该表达式是包含在拒绝规则还是允许规则中。

根据 IPv4 或 IPv6 的 IP 地址范围允许或拒绝访问

  • 以下表达式与来自 198.51.100.0/24 IP 地址范围的请求匹配:

    inIpRange(origin.ip, '198.51.100.0/24')
    
  • 以下表达式与来自 2001:db8::/32 IP 地址范围的请求匹配:

    inIpRange(origin.ip, '2001:db8::/32')
    

根据上游代理后面的自定义客户端 IP 地址范围允许或拒绝访问

如果您已配置 origin.user_ip 运算符,则可以根据在 advancedOptionsConfig.userIpRequestHeaders[] 字段中指定的标头值进行匹配。

  • 以下表达式与源自 192.0.2.0/24 IP 地址范围的请求匹配:

    inIpRange(origin.user_ip, '192.0.2.0/24')
    
  • 以下表达式与源自 2001:db8::/32 IP 地址范围的请求匹配:

    inIpRange(origin.user_ip, '2001:db8::/32')
    
  • 以下表达式与具有包含 80=BLAH 的 Cookie 的请求匹配:

    has(request.headers['cookie']) && request.headers['cookie'].contains('80=BLAH')
    

使用非空 referer 标头允许或拒绝流量

  • 以下表达式与具有非空 referer 标头的请求匹配:

    has(request.headers['referer']) && request.headers['referer'] != ""
    

根据 Host 标头允许或拒绝流量

您可以根据请求中 Host 标头的值来允许或拒绝流量。

  • 以下表达式使用 == 与发送到特定网址的请求匹配:

    request.headers['host'].lower() == 'test.example.com'
    
  • 以下表达式使用 endsWith 与发送到特定网址的请求匹配:

    request.headers['host'].lower().endsWith('.example.com')
    
  • 以下表达式使用 contains 与发送到特定网址的请求匹配:

    request.headers['host'].lower().contains('test.example.com')
    
  • 以下表达式使用 contains 与发送到多个网域的请求匹配:

    request.headers['host'].lower().contains('test.example.com') || request.headers['host'].lower().contains('test22.example.com')
    
  • 以下表达式使用 matches 匹配对网域及其子网域的请求:

    request.headers['host'].matches('(?i:(?:sub\.)?test\.example\.com)')
    

允许或拒绝来自特定区域的流量

如果您的 Web 应用在 AU 区域尚不可用,则必须阻止来自该区域的所有请求。

  • 在拒绝规则中,使用以下表达式,该表达式与来自 AU 区域的请求匹配:

    origin.region_code == 'AU'
    

或者,如果 Web 应用仅在 AU 区域中可用,则来自所有其他区域的请求必须被阻止。

  • 在拒绝规则中,使用以下表达式,该表达式匹配来自 AU 区域以外的所有区域的请求:

    origin.region_code != 'AU'
    

区域代码基于 ISO 3166-1 alpha 2 代码。在某些情况下,一个地区对应一个国家/地区,但并非总是如此。例如,US 代码包括美国各州、一个特区和六个美国本土外地区。

允许或拒绝来自特定 ASN 的流量

如果您的 Web 应用需要阻止由特定网络运营商提供服务的客户,则可以使用网络运营商的 ASN 编号进行阻止。

  • 在拒绝规则中,使用以下表达式,该表达式匹配来自特定 ASN 的请求:

    origin.asn == 123
    

或者,如果您的 Web 应用仅可供特定网络运营商的用户使用,则必须阻止来自所有其他网络运营商的请求。

  • 在拒绝规则中,使用以下表达式,该表达式匹配除您有兴趣允许的网络运营商之外的所有其他网络运营商:

    origin.asn != 123
    

多个表达式

如需在单条规则中添加多个条件,请组合多个子表达式。

  • 在以下示例中,来自 AU 地区中的 1.2.3.0/24(例如您的 Alpha 版测试人员)的请求与以下表达式匹配:

    origin.region_code == "AU" && inIpRange(origin.ip, '1.2.3.0/24')
    
  • 以下表达式与来自 1.2.3.4 的请求匹配,其中用户代理包含字符串 WordPress:

    inIpRange(origin.ip, '1.2.3.4/32') &&
    has(request.headers['user-agent']) && request.headers['user-agent'].contains('WordPress')
    

允许或拒绝与正则表达式匹配的请求 URI 的流量

  • 以下表达式与 URI 中包含字符串 /example_path/ 的请求匹配:

    request.path.matches('/example_path/')
    
  • 以下表达式与 User-Agent 标头字段中包含 Chrome 的请求匹配:

    request.headers['user-agent'].matches('Chrome')
    
  • 以下表达式显示了包含 wordpress 的 User-Agent 标头的不区分大小写的匹配;它与 User-Agent:WordPress/605.1.15、User-Agent:wordPress 以及 wordpress 的其他变体匹配:

    request.headers['user-agent'].matches('(?i:wordpress)')
    

允许或拒绝包含特定 base64 解码值的流量

  • 以下表达式与 user-id 标头的 base64 解码值为 myValue 的请求匹配:

    has(request.headers['user-id']) && request.headers['user-id'].base64Decode().contains('myValue')
    

允许或拒绝包含特定长度的字符串值的流量

  • 以下表达式与网址长度超过 10 个字符的请求匹配:

    size(request.path) > 10
    
  • 以下表达式与标头 x-data 长度大于或等于 1024 个字符的请求匹配:

    size(request.headers['x-data']) >= 1024
    

允许或拒绝 HTTP 正文中 content-length 为零的流量

  • 以下表达式与 HTTP 正文中 content-length 为零的请求匹配:

    int(request.headers["content-length"]) == 0
    

允许或拒绝包含特定网址编码值的流量

  • 以下表达式与 Cookie 值包含 %3c 的请求匹配:

    has(request.headers['cookie']) && request.headers['cookie'].urlDecode().contains('<')
    

允许或拒绝包含 Unicode 字符串的特定网址编码值的流量

  • 以下表达式与 Cookie 值等于 Match%2BValue 或 Match%u002BValue 的请求匹配:

    has(request.headers['cookie']) && request.headers['cookie'].urlDecodeUni() == 'Match+Value'
    

允许或拒绝包含 UTF-8 文本的特定 Unicode 字符串的流量

  • 以下表达式与 Cookie 值等于 ¬ 的请求匹配:

    has(request.headers['cookie']) && request.headers['cookie'].utf8ToUnicode() == '%u00ac'
    

根据已知的 JA4 指纹允许或拒绝流量

  • 以下表达式与具有等于 t13d1516h2_8daaf6152771_b186095e22b6 的 JA4 指纹的请求匹配:

    origin.tls_ja4_fingerprint == 't13d1516h2_8daaf6152771_b186095e22b6'
    

根据 JA4 指纹列表允许或拒绝流量

  • 以下表达式与具有以下任一 JA4 指纹的请求匹配:

    • t00d0000h0_000000000000_000000000000
    • t13d1516h2_8daaf6152771_b186095e22b6
    origin.tls_ja4_fingerprint == 't00d0000h0_000000000000_000000000000' || origin.tls_ja4_fingerprint == 't13d1516h2_8daaf6152771_b186095e22b6'
    

根据请求正文内容允许或拒绝流量

  • 以下表达式与请求正文中包含 malicious-value 的 POST 请求匹配:

    request.method == 'POST' && request.body.contains('malicious-value')
    
  • 以下表达式与以 <!DOCTYPE html> 开头的请求匹配:

    request.body.startsWith('<!DOCTYPE html>')
    
  • 以下表达式与正文匹配正则表达式 \w+@\w+.com 的请求匹配:

    request.body.matches('\w+@\w+.com')
    

根据请求参数允许或拒绝流量

  • 以下表达式与不包含名为 category 的参数的请求匹配:

    !has(request.params.category)
    
  • 以下表达式与 category 参数为 electronics 的请求匹配:

    request.params.category == 'electronics'
    
  • 以下表达式与所有参数值均不为空的请求匹配:

    request.params.all(k, request.params[k] != '')
    
  • 以下表达式与任何参数包含字符串 admin 的请求匹配:

    request.params.exists(k, request.params[k].contains('admin'))
    
  • 以下表达式与恰好有一个参数名称包含 admin 的请求匹配:

    request.params.exists_one(k, k.contains('admin'))
    
  • 以下表达式与至少一个参数名称包含 id 的请求匹配:

    size(request.params.filter(k, k.contains('id'))) > 0
    
  • 以下表达式与参数值包含字符串 admin 的请求匹配:

    request.params.map(k, request.params[k]).contains('admin')
    

根据请求正文中的结构化数据允许或拒绝流量

  • 以下表达式与 JSON 请求正文中的 password 字段包含 123 的请求匹配:

    has(request.params.password) && request.params.password.contains('123')
    
  • 以下表达式与表单数据中的 city 字段为 NewYork 的请求匹配:

    has(request.params.city) && request.params.city == 'NewYork'
    
  • 以下表达式与嵌套 newsletter 字段为 true 的请求匹配:

    has(request.params.preferences) && has(request.params.preferences.newsletter) && request.params.preferences.newsletter == true
    
  • 以下表达式与 friends 数组中第一个元素的 name 字段为 johndoe 的请求匹配:

    request.params['friends'][0]['name'] == 'johndoe'
    

预配置的 WAF 规则

预配置的 WAF 规则使用预配置的静态签名、正则表达式或两者,以匹配 HTTP 请求正文、HTTP 请求标头和查询参数。可用的预配置 WAF 规则基于 OWASP 核心规则集 4.22。Cloud Armor 提供了多种预定义的预配置 WAF 规则。如需查看预配置的 WAF 规则的完整列表,请参阅 Cloud Armor 的预配置 WAF 规则概览。

如需列出所有可用的预配置 WAF 规则,请参阅列出可用的预配置 WAF 规则。

如需详细了解预配置的 WAF 规则,请参阅使用预配置的 WAF 规则缓解应用层攻击应用场景。

预配置的 WAF 规则名称

预配置的 WAF 规则名称的格式为 <attack category>-<OWASP CRS version>-<version field>。攻击类别指定要防御的攻击类型,例如 xss(跨站脚本攻击)或 sqli(SQL 注入攻击)。

支持的版本字段为 stable 和 canary。对规则的添加和修改首先在 canary 版本中发布。在添加和修改被认为是安全稳定时,则会将它们升级为 stable 版本。

预配置的 WAF 规则成员 ID

预配置的 WAF 规则包含多个表达式,每个表达式都有自己的签名。例如,预配置的 WAF 规则 xss-v422-stable 包含一个名为 owasp-crs-v042200-id941100-xss 的表达式,它对应于版本 4.22 的规则 ID id941100。您可以使用签名来排除使用特定的表达式,如果特定的表达式始终触发假正例,这将非常有用。如需了解详情,请参阅假正例问题排查信息。

如需了解核心规则集以及在不同敏感度级层下的调整,请参阅调整 Cloud Armor WAF 规则。

预配置的 WAF 规则的运算符

表达式 说明
evaluatePreconfiguredWaf(string, MAP<string, dyn>) 如果指定 WAF 规则集中的任一 WAF 签名返回 true,则返回 true。第一个参数是 WAF 规则集的名称,例如 xss-v422-stable。第二个参数(可选)是一个映射,其中键是一个字符串,值是根据键动态输入的。此参数的目的是微调所评估的 WAF 签名。接受的键包括:
  • sensitivity:此键对应于 OWASP 核心规则集偏执级别,该级别共有 4 种,范围从 1 到 4。其值为整数,有效范围为 0 到 4。请注意,0 与 opt_in_rule_ids(稍后介绍)一起使用时会预留为有效值。如果指定敏感度 x (x >= 1),则评估敏感度值介于 1 到 x 内的所有关联的 WAF 签名。如果省略,则使用 4 作为敏感度值。
  • opt_out_rule_ids:要退出评估的 WAF 签名(由规则 ID 表示),其中基本集由敏感度值决定。其值是一个字符串列表。允许的规则 ID 数量上限为 128。
  • opt_in_rule_ids:要选择启用以进行评估的 WAF 签名(由规则 ID 表示),其中基本集为空。其值是一个字符串列表。允许的规则 ID 数量上限为 128。使用此键时,必须指定 0 的 sensitivity。

键 opt_out_rule_ids 和 opt_in_rule_ids 相互排斥。如果您想查看并手动选择启用后续添加到现有规则集的新 WAF 签名,可以选择使用 opt_in_rule_ids。

evaluatePreconfiguredWaf(string, LIST)

如果指定的预配置 WAF 规则中的任何一个表达式返回 true,则返回 true。

第一个参数是预配置的 WAF 规则的名称,例如 xss-stable。第二个参数(可选)是必须从评估中排除的 ID 的以逗号分隔字符串列表。当预配置的 WAF 规则的给定成员触发假正例时,排除列表很有用。

预配置的 WAF 规则示例

  • 以下表达式使用 xss-v422-stable 预配置的 WAF 规则来缓解 XSS 攻击:

    evaluatePreconfiguredWaf('xss-v422-stable')
    
  • 以下表达式使用 xss-v422-stable 预配置的 WAF 规则中的所有表达式,但成员 ID 941100 和 941110 除外:

    evaluatePreconfiguredWaf('xss-v422-stable', {'opt_out_rule_ids': ['owasp-crs-v042200-id941100-xss',
    'owasp-crs-v042200-id941110-xss']})
    
  • 以下表达式使用预配置的 WAF 规则来缓解来自 198.51.100.0/24 IP 地址范围的 SQLi 攻击:

    inIpRange(origin.ip, '198.51.100.0/24') && evaluatePreconfiguredWaf('sqli-v422-stable')
    
  • 以下表达式使用 xss-v422-stable 预配置的 WAF 规则来缓解针对 example.com 的请求的 XSS 攻击,但不包括以 /login/api/ 开头的路径:

    request.headers['host'].lower() == 'example.com' && !request.path.startswith('/login/api/') && evaluatePreconfiguredWaf('xss-v422-stable')
    

其他运算符

表达式 说明
evaluateThreatIntelligence(string)
evaluateThreatIntelligence(string, LIST)
evaluateThreatIntelligence(string, string, LIST)

如果客户端 IP 地址与给定 IP 列表中的任何 IP 范围匹配,则返回 true,除非排除列表中明确排除该 IP 地址。

第一个参数是 Google Threat Intelligence Feed 名称,例如 iplist-known-malicious-ips。如果第二个参数是字符串(可选),则它会确定从何处提取 IP 地址,并且可以是 origin.ip、origin.user_ip 或特定标头名称。如果第二个或第三个参数(可选)是以英文逗号分隔的字符串列表,其中每个字符串都是一个 IP 地址或 CIDR 范围,则该参数会从评估中排除。如果 Feed 包含某个会触发误报的 IP 地址,则排除列表很有用。

evaluateAddressGroup(string, string)
evaluateAddressGroup(string, string, LIST)

evaluateOrganizationAddressGroup(string, string)
evaluateOrganizationAddressGroup(string, string, LIST)

如果客户端 IP 地址与给定地址组中的任何 IP 范围匹配,则返回 true,除非排除列表中明确排除该 IP 地址。

第一个参数是地址组名称。第二个参数用于确定从何处提取 IP 地址,可以是 origin.ip、origin.user_ip 或特定标头名称。第三个参数(可选)是以英文逗号分隔的字符串列表,其中每个字符串都是一个 IP 地址或 CIDR 范围,则该参数会从评估中排除。如果地址组包含某个会触发误报的 IP 地址,则排除列表很有用。

evaluateAdaptiveProtection(string)

如果请求与 Google Cloud Armor 自动调节式保护生成的攻击签名匹配,则返回 true。

参数是 Adaptive Protection 在检测到攻击时生成的特定提醒的 ID。

evaluateAdaptiveProtectionAutoDeploy()

如果请求来自与 Adaptive Protection 检测到的正在进行的攻击的攻击签名匹配的重量级流量源 IP 地址,则返回 true。

示例

  • 以下表达式将传入请求与 Google Threat Intelligence iplist-known-malicious-ips Feed 进行匹配,以防范已知恶意 IP 列表:

    evaluateThreatIntelligence('iplist-known-malicious-ips')
    
  • 以下表达式将传入请求与 Google Threat Intelligence iplist-known-malicious-ips Feed 进行匹配,以防范已知恶意 IP 列表,但 203.0.113.0/24 中的 IP 除外:

    evaluateThreatIntelligence('iplist-known-malicious-ips', ['203.0.113.0/24'])
    
  • 以下表达式会将用户 IP 的自定义请求标头与名为 my-own-list-of-bad-ips 的地址组进行匹配:

    evaluateAddressGroup('my-own-list-of-bad-ips', origin.user_ip)
    

后续步骤