Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 10 additions & 15 deletions src/content/docs/waf/rate-limiting-rules/best-practices.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -392,24 +392,19 @@ This type of rate limiting requires that the server scores every served request

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

| Setting | Value |
| --------------------------- | ------------------------------------- |
| Matching criteria | URI Path contains `/graphql` |
| Expression | `http.request.uri.path eq "/graphql"` |
| Counting characteristics | Cookie (`session_id`) |
| Score rate (score / period) | 1,000 / 1 hour |
| Score location | Response header (`score`) |
| Action | Block |
| Setting | Value |
| ------------------------ | ------------------------------------- |
| Matching criteria | URI Path contains `/graphql` |
| Expression | `http.request.uri.path eq "/graphql"` |
| Counting characteristics | Cookie (`session_id`) |
| Score per period | 1,000 |
| Period | 1 hour |
| Response header name | `score` |
| Action | Block |

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

:::note

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).

:::

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.
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.

### Limit any individual query’s complexity

Expand Down
6 changes: 3 additions & 3 deletions src/content/docs/waf/rate-limiting-rules/create-api.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -128,19 +128,19 @@ The new rule does not consider requests for cached assets when calculating the r
### Example D - Complexity-based rate limiting rule

:::note
[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.
[Complexity-based rate limiting](/waf/rate-limiting-rules/request-rate/#complexity-based-rate-limiting) is only available to Enterprise customers with Advanced Rate Limiting.
:::

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`.

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).
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).

<APIRequest
path="/zones/{zone_id}/rulesets/{ruleset_id}/rules"
method="POST"
json={{
description: "My complexity-based rate limiting rule",
expression: 'http.request.uri.path matches "^/graphql/"',
expression: '(http.request.uri.path wildcard "/graphql/*")',
action: "block",
ratelimit: {
characteristics: ["cf.colo.id", 'http.request.headers["x-api-key"]'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,32 @@ import { Render, Tabs, TabItem } from "~/components";

8. (Optional) To define an expression that specifies the conditions for incrementing the rate counter, enable **Use custom counting expression** and set the expression. By default, the counting expression is the same as the rule expression. The counting expression can include [response fields](/ruleset-engine/rules-language/fields/reference/?field-category=Response).

9. Under **When rate exceeds**, define the maximum number of requests and the time period to consider when determining the rate.
9. (Optional) In **When rate exceeds**, select between:
- **Request based**: Rate limiting based on the number of incoming requests during a given period.
- **Complexity based**: Rate limiting based on the complexity or cost of handling requests during a given period.

10. Under **Then take action**, select the rule action from the **Choose action** drop-down list. For example, selecting _Block_ tells Cloudflare to refuse requests in the conditions you specified when the request limit is reached.
:::note
[Complexity-based rate limiting](/waf/rate-limiting-rules/request-rate/#complexity-based-rate-limiting) is only available to Enterprise customers with Advanced Rate Limiting. Other users will always use request-based rate limiting.
:::

11. (Optional) If you selected the _Block_ action, you can [configure a custom response](#configure-a-custom-response-for-blocked-requests) for requests exceeding the configured rate limit.
10. If you selected **Request based** in the previous step (or if you could not select the rate limiting method), enter a value for:
- **Requests**: Maximum number of requests.
- **Period**: Time period to consider when determining the rate.

12. Select the mitigation timeout in the **Duration** dropdown. This is the time period during which Cloudflare applies the select action once the rate is reached.
If you selected **Complexity based**, enter a value for:
- **Score per period**: Maximum score per period. When this value is exceeded, the rule action will execute.
- **Period**: Time period to consider when determining the rate.
- **Response header name**: Name of HTTP header in the response, set by the origin server, with the score for the current request.

11. Under **Then take action**, select the rule action from the **Choose action** drop-down list. For example, selecting _Block_ tells Cloudflare to refuse requests in the conditions you specified when the request limit is reached.

12. (Optional) If you selected the _Block_ action, you can [configure a custom response](#configure-a-custom-response-for-blocked-requests) for requests exceeding the configured rate limit.

13. Select the mitigation timeout in the **Duration** dropdown. This is the time period during which Cloudflare applies the select action once the rate is reached.

Enterprise customers with a paid add-on can [throttle requests](/waf/rate-limiting-rules/parameters/#with-the-following-behavior) instead of applying the configured action for a selected duration. To throttle requests, under **With the following behavior** select _Throttle requests over the maximum configured rate_.

13. To save and deploy your rule, select **Deploy**. If you are not ready to deploy your rule, select **Save as Draft**.
14. To save and deploy your rule, select **Deploy**. If you are not ready to deploy your rule, select **Save as Draft**.

</TabItem> <TabItem label="New dashboard" icon="rocket">

Expand Down
31 changes: 27 additions & 4 deletions src/content/docs/waf/rate-limiting-rules/parameters.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,21 @@ If you set a custom counting expression, it will not automatically extend the ru
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.
:::

### When rate exceeds

- Field name in the API: _N/A_ (different API fields required according to the selected option)

The rate limiting counting can be:

- **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.
- **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.

### When rate exceeds > Requests

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

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

### When rate exceeds > Period

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

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

### When rate exceeds > Score per period

- Data type: <Type text="Integer" />
- Field name in the API: `score_per_period`

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).

### When rate exceeds > Response header name

- Data type: <Type text="String" />
- Field name in the API: `score_response_header_name`

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).

### Then take action

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

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

- [**With response type**](#with-response-type-for-block-action)
- [**With response code**](#with-response-code-for-block-action)
- [**Response body**](#response-body-for-block-action)
- [With response type](#with-response-type-for-block-action)
- [With response code](#with-response-code-for-block-action)
- [Response body](#response-body-for-block-action)

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

Expand Down
11 changes: 6 additions & 5 deletions src/content/docs/waf/rate-limiting-rules/request-rate.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -116,22 +116,23 @@ Request 4 matches the rule expression and therefore Cloudflare evaluates the rat
## Complexity-based rate limiting

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

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.

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.

When you configure a complexity-based rate limiting rule, the origin server must include an HTTP header in the response with its complexity score.
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.

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

- **Score** (API field: `score_per_period`): Maximum score per period. When this value is exceeded, the rule action will execute.
- **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.
- [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.
- [Period](/waf/rate-limiting-rules/parameters/#when-rate-exceeds--period): The period of time to consider when evaluating the request rate.
- [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.

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.

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.

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).
For an example of a complexity-based rate limiting rule, refer to [Rule examples](/waf/rate-limiting-rules/use-cases/#example-4).
42 changes: 40 additions & 2 deletions src/content/docs/waf/rate-limiting-rules/use-cases.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Rule characteristics:

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

</Example>

Expand All @@ -58,6 +58,44 @@ Rule characteristics:

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

</Example>

## Example 4

:::note
[Complexity-based rate limiting](/waf/rate-limiting-rules/request-rate/#complexity-based-rate-limiting) is only available to Enterprise customers with Advanced Rate Limiting.
:::

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.

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.

<Example>

Expression:<br />
`(http.request.uri.path wildcard "/graphql/*")`

Rule characteristics:

- _Data center ID_ (included by default when creating the rule in the dashboard)
- _Header value of_ > `x-api-key`

When rate exceeds: **Complexity based**

- Score per period: `400`
- Period: _1 minute_
- Response header name: `my-score`

Then take action:

- Choose action: _Block_

With the following behavior: **Block for the selected duration**

- Duration: _10 minutes_

</Example>

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).
Loading