每个 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 安全政策。
控制台
在 Google Cloud 控制台中,前往 Cloud Armor 政策页面。
点击安全政策的名称以打开政策详情页面,然后点击规则标签页。
点击添加规则。
可选:输入规则的说明。
选择模式:
- 基本模式:根据 IP 地址或 IP 范围允许或拒绝流量。
- 高级模式:根据规则表达式允许或拒绝流量。
在匹配字段中,指定规则适用的条件:
基本模式:输入 1 到 10 个要与规则匹配的 IP 地址范围。您最多可以添加 10 个 IP 地址范围。如需了解限制,请参阅 Cloud Armor 配额和限制。
高级模式:
在操作列表中,选择允许或拒绝。
如果您要配置拒绝规则,请在响应代码列表中选择一个响应代码。
如需为规则启用预览模式,请选择启用。
在优先级字段中,输入 0 到 2,147,483,646 之间的整数。 Cloud Armor 会按优先级顺序评估规则,从 0(最高)到 2,147,483,647(最低)。默认规则的优先级为 2,147,483,647。
点击 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 安全政策中的规则。
控制台
在 Google Cloud 控制台中,前往 Cloud Armor 政策页面。
点击特定安全政策的名称。政策详情页面会在规则标签页中显示政策规则。
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
运行
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 地址概览。
如果您未配置 |
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 请求标头的字符串到字符串映射。如果某个标头有多个值,则此映射中的对应值是一个包含所有值的字符串,各值之间用英文逗号分隔。此映射中的键全部为小写。外部应用负载均衡器会检查所有接受的标头,并应用相同的标头限制。 使用 您可以遍历映射,以检查键和值。
不过,您只能在同一表达式中将 |
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 地址前缀的网络运营商确定。 |
reCAPTCHA 属性
本部分列出了仅适用于 reCAPTCHA 令牌或豁免 Cookie 的属性。如果要评估的 reCAPTCHA 令牌或豁免 Cookie 因以下任一原因而不可用或无效,则基于这些属性的子表达式会返回 false:
- 令牌格式不正确,无法解码。
- 令牌包含无效属性。例如,令牌是使用与规则的关联 reCAPTCHA 密钥不匹配的 reCAPTCHA 密钥生成的。
- 令牌已过期。
豁免 Cookie 特性
| 字段 | 类型 | 字段说明 |
|---|---|---|
token.recaptcha_exemption.valid |
bool |
是否存在有效的 reCAPTCHA 豁免 Cookie。 |
操作令牌特性
| 字段 | 类型 | 字段说明 |
|---|---|---|
token.recaptcha_action.score |
float |
reCAPTCHA 操作令牌中的分数。有效分数的范围为 0.0 到 1.0,其中 0.0 表示很可能是非法用户,1.0 表示很可能是合法用户。 |
token.recaptcha_action.captcha_status |
string |
reCAPTCHA 操作令牌中的人机识别系统状态。有效状态为 NONE、PASS 或 FAIL,其中 NONE 表示 reCAPTCHA 评估期间未涉及任何验证,因此操作令牌中缺少人机识别系统字段。 |
token.recaptcha_action.action |
string |
reCAPTCHA 操作令牌中的操作名称(最多 100 个字符)。请参阅操作名称。 |
token.recaptcha_action.valid |
bool |
是否存在有效的 reCAPTCHA 操作令牌。 |
会话令牌特性
| 字段 | 类型 | 字段说明 |
|---|---|---|
token.recaptcha_session.score |
float |
reCAPTCHA 会话令牌的分数。有效分数的范围为 0.0 到 1.0,其中 0.0 表示很可能是非法用户,1.0 表示很可能是合法用户。 |
token.recaptcha_session.valid |
bool |
是否存在有效的 reCAPTCHA 会话令牌。 |
表达式示例
对于这些表达式中的每一个,所采取的操作取决于该表达式是包含在拒绝规则还是允许规则中。
根据 IPv4 或 IPv6 的 IP 地址范围允许或拒绝访问
以下表达式与来自
198.51.100.0/24IP 地址范围的请求匹配:inIpRange(origin.ip, '198.51.100.0/24')
以下表达式与来自
2001:db8::/32IP 地址范围的请求匹配:inIpRange(origin.ip, '2001:db8::/32')
根据上游代理后面的自定义客户端 IP 地址范围允许或拒绝访问
如果您已配置 origin.user_ip 运算符,则可以根据在 advancedOptionsConfig.userIpRequestHeaders[] 字段中指定的标头值进行匹配。
以下表达式与源自
192.0.2.0/24IP 地址范围的请求匹配:inIpRange(origin.user_ip, '192.0.2.0/24')
以下表达式与源自
2001:db8::/32IP 地址范围的请求匹配:inIpRange(origin.user_ip, '2001:db8::/32')
使用特定 Cookie 允许或拒绝流量
以下表达式与具有包含
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_000000000000t13d1516h2_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 签名。接受的键包括:
键 |
evaluatePreconfiguredWaf(string, LIST) |
如果指定的预配置 WAF 规则中的任何一个表达式返回 第一个参数是预配置的 WAF 规则的名称,例如 |
预配置的 WAF 规则示例
以下表达式使用
xss-v422-stable预配置的 WAF 规则来缓解 XSS 攻击:evaluatePreconfiguredWaf('xss-v422-stable')以下表达式使用
xss-v422-stable预配置的 WAF 规则中的所有表达式,但成员 ID941100和941110除外:evaluatePreconfiguredWaf('xss-v422-stable', {'opt_out_rule_ids': ['owasp-crs-v042200-id941100-xss', 'owasp-crs-v042200-id941110-xss']})以下表达式使用预配置的 WAF 规则来缓解来自
198.51.100.0/24IP 地址范围的 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')
托管式规则
Google Cloud Armor 托管式规则通过自动更新的安全签名保护您的 Web 应用和 API 端点。托管式规则由 Thales Imperva 提供支持,并直接集成到 Cloud Armor 中,可简化您的安全运维。借助代管式规则,您无需手动更新签名,并可减少配置偏移,让您的安全团队专注于开发和运营。
托管式规则的运算符
| 表达式 | 说明 |
|---|---|
evaluateManagedRules(string, MAP<string, dyn>) |
如果指定托管式规则中的任一签名返回 true,则返回 true。第一个参数是类别的完全限定名称,例如 google:xss:stable 或 google:sqli:canary。第二个参数(可选)是一个映射,其中键是一个字符串,值是根据键动态输入的。
接受的键包括:
|
托管式规则示例
以下表达式使用稳定的 SQL 注入 (
sqli) 托管式规则来帮助防范 SQLi 攻击:evaluateManagedRules('google:sqli:stable')仅当请求具有主机
example.com时,以下表达式才会使用稳定的xss托管式规则:request.headers['host'].lower() == 'example.com' && evaluateManagedRules('google:xss:stable')
其他运算符
| 表达式 | 说明 |
|---|---|
evaluateThreatIntelligence(string)evaluateThreatIntelligence(string, LIST)evaluateThreatIntelligence(string, string, LIST)
|
如果客户端 IP 地址与给定 IP 列表中的任何 IP 范围匹配,则返回 第一个参数是 Google Threat Intelligence Feed 名称,例如 |
evaluateAddressGroup(string, string)evaluateAddressGroup(string, string, LIST)evaluateOrganizationAddressGroup(string, string)evaluateOrganizationAddressGroup(string, string, LIST)
|
如果客户端 IP 地址与给定地址组中的任何 IP 范围匹配,则返回 第一个参数是地址组名称。第二个参数用于确定从何处提取 IP 地址,可以是 |
evaluateAdaptiveProtection(string) |
如果请求与 Google Cloud Armor 自动调节式保护生成的攻击签名匹配,则返回 参数是 Adaptive Protection 在检测到攻击时生成的特定提醒的 ID。 |
evaluateAdaptiveProtectionAutoDeploy() |
如果请求来自与 Adaptive Protection 检测到的正在进行的攻击的攻击签名匹配的重量级流量源 IP 地址,则返回 |
示例
以下表达式将传入请求与 Google Threat Intelligence
iplist-known-malicious-ipsFeed 进行匹配,以防范已知恶意 IP 列表:evaluateThreatIntelligence('iplist-known-malicious-ips')以下表达式将传入请求与 Google Threat Intelligence
iplist-known-malicious-ipsFeed 进行匹配,以防范已知恶意 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)
后续步骤
- 创建和查看 Cloud Armor 安全政策
- 管理 Cloud Armor 安全政策
- 管理 Cloud Armor 安全政策规则
- 调整 Cloud Armor 预配置的 WAF 规则
- 排查 Cloud Armor 问题
- 配额和限制