Skip to content

Commit 5604280

Browse files
committed
[WAF] Update complexity-based rate limiting
1 parent f4b587c commit 5604280

File tree

5 files changed

+86
-29
lines changed

5 files changed

+86
-29
lines changed

src/content/docs/waf/rate-limiting-rules/best-practices.mdx

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -392,24 +392,19 @@ This type of rate limiting requires that the server scores every served request
392392

393393
For example, the following rule defines a total complexity budget of 1,000 per hour:
394394

395-
| Setting | Value |
396-
| --------------------------- | ------------------------------------- |
397-
| Matching criteria | URI Path contains `/graphql` |
398-
| Expression | `http.request.uri.path eq "/graphql"` |
399-
| Counting characteristics | Cookie (`session_id`) |
400-
| Score rate (score / period) | 1,000 / 1 hour |
401-
| Score location | Response header (`score`) |
402-
| Action | Block |
395+
| Setting | Value |
396+
| ------------------------ | ------------------------------------- |
397+
| Matching criteria | URI Path contains `/graphql` |
398+
| Expression | `http.request.uri.path eq "/graphql"` |
399+
| Counting characteristics | Cookie (`session_id`) |
400+
| Score per period | 1,000 |
401+
| Period | 1 hour |
402+
| Response header name | `score` |
403+
| Action | Block |
403404

404405
_This example rule requires Advanced Rate Limiting and payload inspection._
405406

406-
:::note
407-
408-
Currently, you can only create complexity-based (or score-based) rules such as the one above [via API](/waf/rate-limiting-rules/create-api/#example-d---complexity-based-rate-limiting-rule).
409-
410-
:::
411-
412-
When the origin server processes a request, it adds a `score` HTTP header to the response with a value representing how much work the origin has performed to handle it — for example, `400`. In the next hour, the same client can perform requests up to an additional budget of `600`. As soon as this budget is exceeded, later requests will be blocked until the timeout expires.
407+
When the origin server processes a request, it adds a `score` HTTP header to the response with a value representing how much work the origin has performed to handle it — for example, `100`. In the next hour, the same client can perform requests up to an additional budget of `900`. As soon as this budget is exceeded, later requests will be blocked until the timeout expires.
413408

414409
### Limit any individual query’s complexity
415410

src/content/docs/waf/rate-limiting-rules/create-api.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,19 +128,19 @@ The new rule does not consider requests for cached assets when calculating the r
128128
### Example D - Complexity-based rate limiting rule
129129

130130
:::note
131-
[Complexity-based rate limiting](/waf/rate-limiting-rules/request-rate/#complexity-based-rate-limiting) is available in beta and can only be configured via API.
131+
[Complexity-based rate limiting](/waf/rate-limiting-rules/request-rate/#complexity-based-rate-limiting) is only available to Enterprise customers with Advanced Rate Limiting.
132132
:::
133133

134134
This example adds a rate limiting rule to the `http_ratelimit` phase entry point ruleset for the zone with ID `$ZONE_ID`. The phase entry point ruleset already exists, with ID `$RULESET_ID`.
135135

136-
The new rule is a complexity-based rate limiting rule that takes the `my-score` HTTP response header into account to calculate a total complexity score for the client. The counter with the total score is updated when there is a match for the rate limiting rule's counting expression (in this case, the same as the rule expression since `counting_expression` is an empty string). When this total score becomes larger than `400` during a period of `60` seconds, any later client requests will be blocked for a period of `600` seconds (10 minutes).
136+
The new rule is a complexity-based rate limiting rule that takes the `my-score` HTTP response header into account to calculate a total complexity score for the client. The counter with the total score is updated when there is a match for the rate limiting rule's counting expression (in this case, the same as the rule expression since `counting_expression` is an empty string). When this total score becomes larger than `400` during a period of `60` seconds (one minute), any later client requests will be blocked for a period of `600` seconds (10 minutes).
137137

138138
<APIRequest
139139
path="/zones/{zone_id}/rulesets/{ruleset_id}/rules"
140140
method="POST"
141141
json={{
142142
description: "My complexity-based rate limiting rule",
143-
expression: 'http.request.uri.path matches "^/graphql/"',
143+
expression: '(http.request.uri.path wildcard "/graphql/*")',
144144
action: "block",
145145
ratelimit: {
146146
characteristics: ["cf.colo.id", 'http.request.headers["x-api-key"]'],

src/content/docs/waf/rate-limiting-rules/parameters.mdx

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,21 @@ If you set a custom counting expression, it will not automatically extend the ru
8484
For example, you might want to perform rate limiting for clients sending more than five requests to `/api/` resulting in a `403` HTTP status code from the origin server. In this case, the matching expression would be `starts_with(http.request.uri.path, "/api/")` and the counting expression would be `http.response.code eq 403 and starts_with(http.request.uri.path, "/api/")`. If the counting expression did not include the matching expression (that is, if you had set the counting expression to `http.response.code eq 403`), any response with a `403` status code on any URL would increase the counter.
8585
:::
8686

87+
### When rate exceeds
88+
89+
- Field name in the API: _N/A_ (different API fields required according to the selected option)
90+
91+
The rate limiting counting can be:
92+
93+
- **Request based**: Performs rate limiting based on the number of incoming requests during a given period. This is the only counting method when complexity-based rate limiting is not available.
94+
- **Complexity based**: Performs rate limiting based on the [complexity](/waf/rate-limiting-rules/request-rate/#complexity-based-rate-limiting) or cost of handling requests during a given period. Only available to Enterprise customers with Advanced Rate Limiting.
95+
8796
### When rate exceeds > Requests
8897

8998
- Data type: <Type text="Integer" />
9099
- Field name in the API: `requests_per_period`
91100

92-
The number of requests over the period of time that will trigger the rule.
101+
The number of requests over the period of time that will trigger the rule. Applies to request-based rate limiting.
93102

94103
### When rate exceeds > Period
95104

@@ -100,6 +109,20 @@ The period of time to consider (in seconds) when evaluating the request rate. Th
100109

101110
The available API values are: `10`, `60` (one minute), `120` (two minutes), `300` (five minutes), `600` (10 minutes), or `3600` (one hour).
102111

112+
### When rate exceeds > Score per period
113+
114+
- Data type: <Type text="Integer" />
115+
- Field name in the API: `score_per_period`
116+
117+
Maximum score per period. When this value is exceeded, the rule action will execute. Applies to [complexity-based rate limiting](/waf/rate-limiting-rules/request-rate/#complexity-based-rate-limiting).
118+
119+
### When rate exceeds > Response header name
120+
121+
- Data type: <Type text="String" />
122+
- Field name in the API: `score_response_header_name`
123+
124+
Name of HTTP header in the response, set by the origin server, with the score for the current request. Applies to [complexity-based rate limiting](/waf/rate-limiting-rules/request-rate/#complexity-based-rate-limiting).
125+
103126
### Then take action
104127

105128
- Data type: <Type text="String" />
@@ -111,9 +134,9 @@ Use one of the following values in the API: `block`, `challenge`, `js_challenge`
111134

112135
If you select the _Block_ action, you can define a custom response using the following parameters:
113136

114-
- [**With response type**](#with-response-type-for-block-action)
115-
- [**With response code**](#with-response-code-for-block-action)
116-
- [**Response body**](#response-body-for-block-action)
137+
- [With response type](#with-response-type-for-block-action)
138+
- [With response code](#with-response-code-for-block-action)
139+
- [Response body](#response-body-for-block-action)
117140

118141
#### With response type (for _Block_ action)
119142

src/content/docs/waf/rate-limiting-rules/request-rate.mdx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,22 +116,23 @@ Request 4 matches the rule expression and therefore Cloudflare evaluates the rat
116116
## Complexity-based rate limiting
117117

118118
:::note
119-
Complexity-based rate limiting is available in beta to Enterprise customers with Advanced Rate Limiting, and can only be configured via API.
119+
Only available to Enterprise customers with Advanced Rate Limiting.
120120
:::
121121

122122
A complexity-based rate limiting rule performs rate limiting based on the complexity or cost of handling requests during a given period, instead of the number of requests in the same period.
123123

124124
A common use case is to score each request with an estimate of the cost (or complexity) required to serve that request. The rate limiting rule can then enforce a maximum limit on the total complexity that each client can put on the application over a given period, regardless of the total number of requests sent by that client.
125125

126-
When you configure a complexity-based rate limiting rule, the origin server must include an HTTP header in the response with its complexity score.
126+
When you configure a complexity-based rate limiting rule, the origin server must include an HTTP header in the response with its complexity score. This score corresponds to the complexity (or cost) of serving the current request. The score value must be between 1 and 1,000,000.
127127

128128
Complexity-based rate limiting rules must contain the following properties:
129129

130-
- **Score** (API field: `score_per_period`): Maximum score per period. When this value is exceeded, the rule action will execute.
131-
- **Score response header name** (API field: `score_response_header_name`): Name of HTTP header in the response, set by the origin server, with the score for the current request. The score corresponds to the complexity (or cost) of serving the current request. The score value must be between 1 and 1,000,000.
130+
- [Score per period](/waf/rate-limiting-rules/parameters/#when-rate-exceeds--score-per-period): Maximum score per period. When this value is exceeded, the rule action will execute.
131+
- [Period](/waf/rate-limiting-rules/parameters/#when-rate-exceeds--period): The period of time to consider when evaluating the request rate.
132+
- [Response header name](/waf/rate-limiting-rules/parameters/#when-rate-exceeds--response-header-name): Name of HTTP header in the response, set by the origin server, with the score for the current request.
132133

133134
Cloudflare keeps counters with the total score of all requests with the same values for the rule characteristics that match the rule expression. The score increases by the value provided by the origin in the response when there is a match for the counting expression (by default, it is the same as the rule expression). When the total score is larger than the configured maximum score per period, the rule action is applied.
134135

135136
If the origin server does not provide the HTTP response header with a score value or if the score value is outside of the allowed range, the corresponding rate limiting counter will not be updated.
136137

137-
For an example of a complexity-based rate limiting rule, refer to [Create rate limiting rules via API](/waf/rate-limiting-rules/create-api/#example-d---complexity-based-rate-limiting-rule).
138+
For an example of a complexity-based rate limiting rule, refer to [Rule examples](/waf/rate-limiting-rules/use-cases/#example-4).

src/content/docs/waf/rate-limiting-rules/use-cases.mdx

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Rule characteristics:
4141

4242
- _Data center ID_ (included by default when creating the rule in the dashboard)
4343
- _IP Address_
44-
- _HTTP Header_ > `x-api-key`
44+
- _Header value of_ > `x-api-key`
4545

4646
</Example>
4747

@@ -58,6 +58,44 @@ Rule characteristics:
5858

5959
- _Data center ID_ (included by default when creating the rule in the dashboard)
6060
- _IP Address_
61-
- _HTTP Header_ > `user-agent`
61+
- _Header value of_ > `user-agent`
6262

6363
</Example>
64+
65+
## Example 4
66+
67+
:::note
68+
[Complexity-based rate limiting](/waf/rate-limiting-rules/request-rate/#complexity-based-rate-limiting) is only available to Enterprise customers with Advanced Rate Limiting.
69+
:::
70+
71+
The following [rate limiting rule](/waf/rate-limiting-rules/create-zone-dashboard/) performs complexity-based rate limiting. The rule takes into account the `my-score` HTTP response header provided by the origin server to calculate a total complexity score for the client with the provided API key.
72+
73+
The counter with the total score is updated when there is a match for the rate limiting rule's [counting expression](/waf/rate-limiting-rules/parameters/#increment-counter-when) (in this case, the same as the rule expression since a counting expression was not provided). When this total score becomes larger than `400` during a period of one minute, any later client requests will be blocked for a period of 10 minutes.
74+
75+
<Example>
76+
77+
Expression:<br />
78+
`(http.request.uri.path wildcard "/graphql/*")`
79+
80+
Rule characteristics:
81+
82+
- _Data center ID_ (included by default when creating the rule in the dashboard)
83+
- _Header value of_ > `x-api-key`
84+
85+
When rate exceeds: **Complexity based**
86+
87+
- Score per period: `400`
88+
- Period: _1 minute_
89+
- Response header name: `my-score`
90+
91+
Then take action:
92+
93+
- Choose action: _Block_
94+
95+
With the following behavior: **Block for the selected duration**
96+
97+
- Duration: _10 minutes_
98+
99+
</Example>
100+
101+
For an API example with this rule configuration, refer to [Create a rate limiting rule via API](/waf/rate-limiting-rules/create-api/#example-d---complexity-based-rate-limiting-rule).

0 commit comments

Comments
 (0)