流量过滤规则可用于在 CDN 层阻止或允许请求,这在以下场景中可能很有用:
所有 AEM as a Cloud Service Sites 和 Forms 客户均可使用大多数此类流量过滤器规则。这些规则主要作用于请求属性和请求标头,包括 IP、主机名、路径和用户代理。
流量过滤规则的子类别需要“增强安全性”许可证或“WAF-DDoS 保护”许可证,今年晚些时候将提供这些许可证。这些强有力的规则称为 WAF(Web 应用程序防火墙)流量过滤规则(或简称为 WAF 规则),它们可访问本文稍后所述的 WAF 标志。
可通过 Cloud Manager 配置管道将流量过滤规则部署到生产(非沙盒)程序中的开发、暂存和生产环境类型。未来还将支持 RDE。
按照教程进行操作,快速建立有关此功能的具体专业知识。
本文分为以下几个部分:
cdn.yaml
配置文件中声明流量过滤规则。这包括适用于所有Sites和Forms客户的流量过滤器规则,以及许可此功能的WAF规则的子类别。我们邀请您通过发送电子邮件至 aemcs-waf-adopter@adobe.com 提供反馈或询问有关流量过滤规则的问题。
在当前的数字环境中,恶意流量是一种始终存在的威胁。我们意识到此类风险的危害性,因此提供若干方法以保护客户应用程序并在发生攻击时减轻其影响。
Adobe Managed CDN 在边缘的网络层(第 3 层和第 4 层)承受 DoS 攻击,其中包括洪泛和反射/放大攻击。
Adobe 默认采取措施,以防因规模超预期的突发流量超出特定阈值而导致性能下降。如果 DoS 攻击影响站点可用性,则提醒 Adobe 的运营团队采取措施以减轻影响。
客户可采取主动措施以通过在内容投放流的各层配置规则而减轻应用层(第 7 层)受到的攻击。
例如,客户可在 Apache 层配置调度程序模块或 ModSecurity 以限制访问某些内容。
此外如本文所述,还可使用 Cloud Manager 的配置管道将流量过滤器规则部署到 Adobe Managed CDN。除了基于 IP 地址、路径和标头等属性的流量过滤规则或基于设置速率限制的规则之外,客户还可许可过滤规则的一个强有力的子类别,称为 WAF 规则。
以下大致介绍推荐用于提出正确的流量过滤规则的整个流程:
cdn.yaml
,并在日志模式下将配置部署到生产环境。首先,在您在 Git 中的项目的顶层文件夹中创建以下文件夹和文件结构:
config/
cdn.yaml
cdn.yaml
应包含元数据,以及流量过滤器规则和WAF规则的列表。
kind: "CDN"
version: "1"
metadata:
envTypes: ["dev"]
data:
trafficFilters:
rules:
# Block simple path
- name: block-path
when:
allOf:
- reqProperty: tier
matches: "author|publish"
- reqProperty: path
equals: '/block/me'
action: block
应将 kind
参数应设置为 CDN
,并应将 version 设置为架构版本,当前为 1
。请进一步参阅下例。
如果许可了 WAF 规则,则应在 Cloud Manager 中为新的和现有的程序场景启用它,如下所述。
对于 RDE 以外的环境类型,请在 Cloud Manager 中创建目标部署配置管道。
对于 RDE,将使用命令行,但目前不支持 RDE。
注释
yq
在本地验证配置文件(例如 yq cdn.yaml
)的 YAML 格式。您可以配置 traffic filter rules
以匹配 IPS、用户代理、请求标头、主机名、地理位置和 URL 等模式。
许可“增强安全性”或“WAF-DDoS 保护”安全产品的客户还可配置一种特殊类别的流量过滤器规则,称为 WAF traffic filter rules
(或简称为 WAF 规则),它们引用一个或多个 WAF 标志。
下面是一组流量过滤规则(其中还包括 WAF 规则)的示例。
kind: "CDN"
version: "1"
metadata:
envTypes: ["dev"]
data:
trafficFilters:
rules:
- name: "path-rule"
when: { reqProperty: path, equals: /block-me }
action:
type: block
- name: "Enable-SQL-Injection-and-XSS-waf-rules-globally"
when: { reqProperty: path, like: "*" }
action:
type: block
wafFlags: [ SQLI, XSS]
cdn.yaml
文件中的流量过滤规则的格式如下所述。查看一些 其他示例 在后面的部分中,以及在 费率限制规则.
属性 | 大多数流量过滤规则 | WAF 流量过滤规则 | 类型 | 默认值 | 描述 |
---|---|---|---|---|---|
name | X | X | string |
- | 规则名称(长度为 64 个字符,只能包含字母数字和 -) |
when | X | X | Condition |
- | 基本结构为:{ <getter>: <value>, <predicate>: <value> } 请在下方参阅条件结构语法,其中描述 getter、谓词以及如何组合多个条件。 |
动作 | X | X | Action |
log | log、allow、block 或 Action 对象。默认为 log。 |
rateLimit | X | RateLimit |
未定义 | 速率限制配置。如果未定义,则禁用速率限制。 以下单独部分描述了 rateLimit 语法及示例。 |
条件可以是一个简单条件或一组条件。
简单条件
简单条件由一个 getter 和一个谓词组成。
{ <getter>: <value>, <predicate>: <value> }
组条件
一组条件由多个简单和/或组条件组成。
<allOf|anyOf>:
- { <getter>: <value>, <predicate>: <value> }
- { <getter>: <value>, <predicate>: <value> }
- <allOf|anyOf>:
- { <getter>: <value>, <predicate>: <value> }
属性 | 类型 | 含义 |
---|---|---|
allOf | array[Condition] |
and 运算。如果所有列出的条件都返回 true,则为 true |
anyOf | array[Condition] |
or 运算。如果列出的任意条件返回 true,则为 true |
Getter
属性 | 类型 | 描述 |
---|---|---|
reqProperty | string |
请求属性。 以下各项之一:
|
reqHeader | string |
返回具有指定名称的请求头 |
queryParam | string |
返回具有指定名称的查询参数 |
reqCookie | string |
返回具有指定名称的 Cookie |
postParam | string |
从请求正文返回具有指定名称的 Post 参数。只有正文的内容类型为 application/x-www-form-urlencoded 才能发挥作用 |
谓词
属性 | 类型 | 含义 |
---|---|---|
equals | string |
如果 getter 结果等于提供的值,则为 true |
doesNotEqual | string |
如果 getter 结果不等于提供的值,则为 true |
like | string |
如果 getter 结果与提供的模式匹配,则为 true |
notLike | string |
如果 getter 结果与提供的模式不匹配,则为 true |
matches | string |
如果 getter 结果与提供的正则表达式匹配,则为 true |
doesNotMatch | string |
如果 getter 结果与提供的正则表达式不匹配,则为 true |
in | array[string] |
如果提供的列表包含 getter 结果,则为 true |
notIn | array[string] |
如果提供的列表不包含 getter 结果,则为 true |
exists | boolean |
当设置为 true 且属性存在或当设置为 false 且属性不存在时为 true |
注释
clientIp
只能与以下谓词一起使用:equals
、doesNotEqual
、in
、notIn
。当使用 in
和 notIn
谓词时,还可比较 clientIp
与 IP 范围。以下示例实现一个条件以评估客户端 IP 是否在 192.168.0.0/24 的 IP 范围内(即从 192.168.0.0 到 192.168.0.255):when:
reqProperty: clientIp
in: [ "192.168.0.0/24" ]
action
可以是指定操作(允许、阻止或日志)的字符串,也可以是由操作类型(允许、阻止或日志)和 wafFlags 和/或状态等选项组成的对象。
操作类型
根据下表中的操作类型设定操作的优先级,优先级将进行排序以反映操作的执行顺序:
名称 | 允许的属性 | 含义 |
---|---|---|
allow | wafFlags (可选) |
如果 wafFlags 不存在,则停止进一步的规则处理并继续提供响应。如果 wafFlags 存在,则禁用指定的 WAF 保护并继续执行进一步的规则处理。 |
block | status, wafFlags (可选且互斥) |
如果 wafFlags 不存在,则绕过所有其他属性来返回 HTTP 错误,错误代码由状态属性定义或默认为 406。如果 wafFlags 存在,则启用指定的 WAF 保护并继续执行进一步的规则处理。 |
log | wafFlags (可选) |
记录规则已触发这一事实,否则对处理不起作用。wafFlags 不起作用 |
wafFlags
属性可用在可许可的 WAF 流量过滤规则中,该属性可能会引用以下各项:
标志 ID | 标志名称 | 描述 |
---|---|---|
SQLI | SQL 注入 | SQL 注入是指尝试通过执行任意数据库查询来获取应用程序的访问权限或特权信息。 |
BACKDOOR | 后门 | 后门信号是指尝试确定系统上是否存在公共后门文件的请求。 |
CMDEXE | 命令执行 | 命令执行是指尝试通过用户输入的任意系统命令来获得控制权限或损坏目标系统。 |
XSS | 跨站点脚本 | 跨站点脚本是指尝试通过恶意 JavaScript 代码来劫持用户帐户或 Web 浏览会话。 |
TRAVERSAL | 目录遍历 | 目录遍历是指尝试在整个系统中导航特权文件夹以获取敏感信息。 |
USERAGENT | 攻击工具 | 攻击工具是指使用自动化软件来找出安全漏洞或尝试利用已发现的漏洞。 |
LOG4J-JNDI | Log4J JNDI | Log4J JNDI 攻击尝试利用 2.16.0 版之前的 Log4J 版本中存在的 Log4Shell 漏洞 |
BHH | 错误跳头 | 错误跳头是指尝试通过格式错误的 Transfer-Encoding (TE) 或 Content-Length (CL) 头或格式良好的 TE 和 CL 头进行 HTTP 走私 |
ABNORMALPATH | 异常路径 | 异常路径表示原始路径与规范化路径不同(例如,/foo/./bar 标准化为 /foo/bar ) |
DOUBLEENCODING | 双重编码 | 双重编码检查双重编码 html 字符的规避技术 |
NOTUTF8 | 无效编码 | 无效编码可能会促使服务器将请求中的恶意字符转换为响应,从而导致拒绝服务或 XSS |
JSON-ERROR | JSON 编码错误 | 指定为在“Content-Type”请求头中包含 JSON,但包含 JSON 解析错误的 POST、PUT 或 PATCH 请求正文。这通常与编程错误或自动或恶意请求有关。 |
MALFORMED-DATA | 请求正文中的格式错误的数据 | 根据“Content-Type”请求头,格式错误的 POST、PUT 或 PATCH 请求正文。例如,如果指定了“Content-Type: application/x-www-form-urlencoded”请求头并包含 POST 正文 json。这通常是编程错误、自动或恶意请求。需要代理 3.2 版或更高版本。 |
SANS | 恶意 IP 流量 | 已报告从事恶意活动的 IP 地址的 SANS Internet Storm Center 列表 |
NO-CONTENT-TYPE | 缺少“Content-Type”请求头 | 不具有“Content-Type”请求头的 POST、PUT 或 PATCH 请求。在此示例中,默认情况下,应用程序服务器应假定“Content-Type: text/plain; charset=us-ascii”。许多自动和恶意请求可能缺少“内容类型”。 |
NOUA | 无用户代理 | 许多自动和恶意请求使用虚假或缺失的用户代理,导致难以识别发出请求的设备类型。 |
TORNODE | Tor 流量 | Tor 是可以隐藏用户身份的软件。Tor 流量尖峰可能表明攻击者正在试图掩盖其位置。 |
NULLBYTE | 空字节 | 空字节通常不会出现在请求中,并表明请求的格式错误且可能是恶意请求。 |
PRIVATEFILE | 私有文件 | 私有文件通常是机密性的,例如 Apache .htaccess 文件或可能泄露敏感信息的配置文件 |
SCANNER | 扫描程序 | 标识常用的扫描服务和工具 |
RESPONSESPLIT | HTTP 响应拆分 | 标识何时将 CRLF 字符作为输入提交给应用程序以将标头注入 HTTP 响应 |
XML-ERROR | XML 编码错误 | 指定为在“Content-Type”请求头中包含 XML,但包含 XML 解析错误的 POST、PUT 或 PATCH 请求正文。这通常与编程错误或自动或恶意请求有关。 |
在创建两个发生冲突的规则时,allow 规则将始终优先于 block 规则。例如,如果您创建一个规则来阻止特定路径,并创建一个规则来允许一个特定的 IP 地址,则来自被阻止路径的 IP 地址的请求将被允许。
如果规则匹配但被阻止,CDN 会提供 406
返回代码。
配置文件不应包含机密信息,因为任何有权访问 Git 存储库的人员都能读取这些文件。
在 Cloud Manager 中定义的 IP 允许列表优先于流量过滤器规则。
WAF 规则匹配只显示在 CDN 未命中和通过(而非命中)的 CDN 日志中。
下面是一些规则示例。请参阅速率限制部分以找到速率限制规则的更多示例。
示例 1
此规则阻止来自 IP 192.168.1.1 的请求:
kind: "CDN"
version: "1"
metadata:
envTypes: ["dev"]
data:
trafficFilters:
rules:
- name: "block-request-from-ip"
when: { reqProperty: clientIp, equals: "192.168.1.1" }
action:
type: block
示例 2
此规则阻止发布时带包含 Chrome 的 User-Agent 的路径/helloworld
的请求:
kind: "CDN"
version: "1"
metadata:
envTypes: ["dev"]
data:
trafficFilters:
rules:
- name: "block-request-from-chrome-on-path-helloworld-for-publish-tier"
when:
allOf:
- { reqProperty: path, equals: /helloworld }
- { reqProperty: tier, equals: publish }
- { reqHeader: user-agent, matches: '.*Chrome.*' }
action:
type: block
示例 3
此规则阻止包含查询参数 foo
的请求,但允许来自 IP 192.168.1.1 的每个请求:
kind: "CDN"
version: "1"
metadata:
envTypes: ["dev"]
data:
trafficFilters:
rules:
- name: "block-request-that-contains-query-parameter-foo"
when: { queryParam: url-param, equals: foo }
action:
type: block
- name: "allow-all-requests-from-ip"
when: { reqProperty: clientIp, equals: 192.168.1.1 }
action:
type: allow
示例 4
此规则阻止对路径 /block-me
的请求,并阻止每个匹配 SQLI
或 XSS
模式的请求:此示例包括 WAF 流量过滤规则,它引用 SQLI
和 XSS
WAF 标志,因此需要一个单独的许可证。
kind: "CDN"
version: "1"
metadata:
envTypes: ["dev"]
data:
trafficFilters:
rules:
- name: "path-rule"
when: { reqProperty: path, equals: /block-me }
action:
type: block
- name: "Enable-SQL-Injection-and-XSS-waf-rules-globally"
when: { reqProperty: path, like: "*" }
action:
type: block
wafFlags: [ SQLI, XSS]
示例 5
此规则阻止访问 OFAC 国家/地区:
kind: "CDN"
version: "1"
metadata:
envTypes: ["dev"]
data:
trafficFilters:
rules:
- name: block-ofac-countries
when:
allOf:
- reqProperty: tier
matches: "author|publish"
- reqProperty: clientCountry
in:
- SY
- BY
- MM
- KP
- IQ
- CD
- SD
- IR
- LR
- ZW
- CU
- CI
action: block
如果流量超过传入请求的特定速率,有时最好可能根据某个具体的条件阻止流量。为 rateLimit
属性设置一个值可限制符合规则条件的那些请求的速率。
速率限制规则不能引用 WAF 标志。所有 Sites 和 Forms 客户均可使用它们。
根据每个 CDN POP 计算得出速率限制。例如,假设蒙特利尔、迈阿密和都柏林的 POP 的流量速率分别为每秒 80、90 和 120 个请求,并将速率限制规则设置为以 100 为限。在该情况下,仅对通往都柏林的流量进行速率限制。
属性 | 类型 | 默认 | 含义 |
---|---|---|---|
limit | 10 和 10000 之间的整数 | 必填 | 为其触发规则的请求速率(每个 CDN POP),以每秒请求数为单位。 |
window | 整数枚举:1、10 或 60 | 10 | 计算请求速率的取样窗口(以秒为单位)。 计数器的准确性取决于时段的大小(时段越大越准确)。例如,1秒窗口可以达到50%的精度,60秒窗口可以达到90%的精度。 |
penalty | 60 和 3600 之间的整数 | 300(5 分钟) | 阻止匹配请求的时段(以秒为单位)(舍入到最接近的分钟)。 |
groupBy | array[Getter] | 无 | 速率限制器计数器将按一组请求属性(例如clientIp)聚合。 |
示例 1
当客户端在过去 60 秒内超过 100 个请求/秒(每个 CDN POP)时,此规则阻止该客户端 5 分钟:
kind: "CDN"
version: "1"
metadata:
envTypes: ["dev"]
data:
trafficFilters:
rules:
- name: limit-requests-client-ip
when:
reqProperty: tier
matches: "author|publish"
rateLimit:
limit: 60
window: 10
penalty: 300
groupBy:
- reqProperty: clientIp
action: block
示例 2
在过去 60 秒内超过 100 个请求/秒(每个 CDN POP)时,阻止对路径 /critical/resource 的请求 60 秒:
kind: "CDN"
version: "1"
metadata:
envTypes: ["dev"]
data:
trafficFilters:
rules:
- name: rate-limit-example
when: { reqProperty: path, equals: /critical/resource }
action:
type: block
rateLimit: { limit: 100, window: 60, penalty: 60 }
通过 AEM as a Cloud Service 可访问 CDN 日志,这些日志对于包括缓存命中率优化以及配置流量过滤规则在内的诸多用例都很有用。在选择创作和发布服务时,CDN 日志显示在 Cloud Manager 的下载日志对话框中。
CDN日志最多可能会延迟五分钟。
rules
属性描述与什么流量过滤规则匹配,并具有以下模式:
"rules": "match=<matching-customer-named-rules-that-are-matched>,waf=<matching-WAF-rules>,action=<action_type>"
例如:
"rules": "match=Block-Traffic-under-private-folder,Enable-SQL-injection-everywhere,waf="SQLI,SANS",action=block"
这些规则的行为方式如下:
match
属性中列出任何匹配的规则的由客户声明的规则名称。action
属性决定规则发挥阻止、允许还是日志记录的作用。waf
属性将列出任何检测到的 WAF 标志(如 SQLI),无论是否在任何规则中列出了这些 WAF 标志都是如此。这样做是为了深入展示可能要声明的新规则。rules
属性将为空。如前所述,WAF 规则匹配只会显示在 CDN 未命中和通过(而非命中)的 CDN 日志中。
下面的示例展示一个示例 cdn.yaml
和两个 CDN 日志条目:
kind: "CDN"
version: "1"
metadata:
envTypes: ["dev"]
data:
trafficFilters:
rules:
- name: "path-rule"
when: { reqProperty: path, equals: /block-me }
action: block
- name: "Enable-SQL-Injection-and-XSS-waf-rules-globally"
when: { reqProperty: path, like: "*" }
action:
type: block
wafFlags: [ SQLI, XSS ]
{
"timestamp": "2023-05-26T09:20:01+0000",
"ttfb": 19,
"cli_ip": "147.160.230.112",
"cli_country": "CH",
"rid": "974e67f6",
"req_ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Safari/605.1.15",
"host": "example.com",
"url": "/block-me",
"method": "GET",
"res_ctype": "",
"cache": "PASS",
"status": 406,
"res_age": 0,
"pop": "PAR",
"rules": "match=path-rule,action=blocked"
}
{
"timestamp": "2023-05-26T09:20:01+0000",
"ttfb": 19,
"cli_ip": "147.160.230.112",
"cli_country": "CH",
"req_ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Safari/605.1.15",
"rid": "974e67f6",
"host": "example.com",
"url": "/?sqli=%27%29%20UNION%20ALL%20SELECT%20NULL%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL%2CNULL--%20fAPK",
"method": "GET",
"res_ctype": "image/png",
"cache": "PASS",
"status": 406,
"res_age": 0,
"pop": "PAR",
"rules": "match=Enable-SQL-Injection-and-XSS-waf-rules-globally,waf=SQLI,action=blocked"
}
以下是 CDN 日志中使用的字段名称列表以及简要说明。
字段名 | 描述 |
---|---|
timestamp | TLS终止后请求开始的时间。 |
ttfb | 首字节时间的缩写。从请求开始到响应正文开始流式传输之前的时间间隔。 |
cli_ip | 客户端 IP 地址。 |
cli_country | 客户国家/地区的两字母 ISO 3166-1 alpha-2 国家/地区代码。 |
rid | 用于唯一标识请求的请求头的值。 |
req_ua | 负责发出给定 HTTP 请求的用户代理。 |
host | 请求所针对的颁发机构。 |
url | 完整路径,包括查询参数。 |
method | 客户端发送的 HTTP 方法,例如“GET”或“POST”。 |
res_ctype | 用于指示资源的原始媒体类型的 Content-Type。 |
cache | 缓存的状态。可能的值为 HIT、MISS 或 PASS |
status | 整数值形式的 HTTP 状态代码。 |
res_age | 响应已缓存(在所有节点中)的时间量(以秒为单位)。 |
pop | CDN 缓存服务器的数据中心。 |
rules | 任何匹配的规则的名称。 还指示匹配是否产生块。 例如,“ match=Enable-SQL-Injection-and-XSS-waf-rules-globally,waf=SQLI,action=blocked ”如果没有匹配的规则,则为空。 |
Adobe 提供一种机制,它将仪表板工具下载到您的计算机上以摄取通过 Cloud Manager 下载的 CDN 日志。使用此工具,您可分析您的流量以帮助提出要声明的相应流量过滤器规则,包括 WAF 规则。
可直接从 AEMCS-CDN-Log-Analysis-ELK-Tool Github 存储库克隆仪表板工具。
请查看教程以切实地了解如何使用仪表板工具。
可将以下推荐的规则复制到您的 cdn.yaml
中以快速入门。首先进入日志模式,分析您的流量,感到满意时改为阻止模式。您可能要根据您网站的实时流量的独有特征修改规则。
kind: "CDN"
version: "1"
metadata:
envTypes: ["dev", "stage", "prod"]
data:
trafficFilters:
rules:
# Block client for 5m when it exceeds 100 req/sec on a time window of 1sec
- name: limit-requests-client-ip
when:
reqProperty: path
like: '*'
rateLimit:
limit: 100
window: 1
penalty: 300
groupBy:
- reqProperty: clientIp
action: log
# Block requests coming from OFAC countries
- name: block-ofac-countries
when:
allOf:
- { reqProperty: tier, equals: publish }
- reqProperty: clientCountry
in:
- SY
- BY
- MM
- KP
- IQ
- CD
- SD
- IR
- LR
- ZW
- CU
- CI
action: log
# Enable recommended WAF protections (only works if WAF is licensed enabled for your environment)
- name: block-waf-flags-globally
when:
reqProperty: tier
matches: "author|publish"
action:
type: log
wafFlags:
- SANS
- TORNODE
- NOUA
- SCANNER
- USERAGENT
- PRIVATEFILE
- ABNORMALPATH
- TRAVERSAL
- NULLBYTE
- BACKDOOR
- LOG4J-JNDI
- SQLI
- XSS
- CODEINJECTION
- CMDEXE
- NO-CONTENT-TYPE
- UTF8
# Disable protection against CMDEXE on /bin (only works if WAF is licensed enabled for your environment)
- name: allow-cdmexe-on-root-bin
when:
allOf:
- reqProperty: tier
matches: "author|publish"
- reqProperty: path
matches: "^/bin/.*"
action:
type: log
wafFlags:
- CMDEXE
查阅一个教程以获得有关流量过滤规则的实用知识和经验。
本教程带领您完成以下操作: