Tutorial: Advanced Rate Limiting with Zones¶
This tutorial provides practical, step-by-step examples for implementing advanced rate limiting scenarios using Peakhour's Rate Limit Zones.
Duration: 25 minutes Prerequisites: An understanding of how to create and use Rate Limit Zones. See the How to Configure Rate Limit Zones guide. Learning Goals: Learn how to create multi-stage rate limiting policies, key on different request attributes, and combine rule phases for sophisticated protection.
What You'll Build: Three advanced rate limiting policies to protect an API by user, apply stricter limits for failed logins, and challenge clients that trigger WAF rules.
Scenario 1: Per-User API Rate Limiting¶
In this scenario, we will rate limit an API based on an API key sent in a header, rather than by IP address. This ensures that different users behind the same IP (like in an office) have their own rate limits.
Create the Rate Limit Zone¶
- Navigate to Rules & Scripting > Rate Limiting.
- Create a new zone with the following settings:
- Name:
api_per_key
- Requests:
1000
- Interval (seconds):
3600
(1 hour) - Block Duration (seconds):
60
- Name:
- Click Add Zone.
Create the Firewall Rule¶
- Navigate to Rules Engine > All Rules.
- Click Add New Rule and select the Rate Limit Request phase.
- Configure the rule:
- Rule Name:
API Rate Limit by Key
- Filter:
starts_with(http.request.uri.path, "/api/")
- Rule Name:
- Configure the Actions:
- Add a Rate Limit action group.
- Select the Add to zone action and choose the
api_per_key
zone. - Select the Check zone action and choose the
api_per_key
zone. - For the Zone Key, select
Header
. In the text box that appears, enterAuthorization
. This tells Peakhour to track requests based on the value of theAuthorization
header. Other key types like IP address, cookie, and network fingerprints are also available. See the Rate Limit Zones guide for a full list. - For the Action on exceeding the limit, choose
block
with a status code of429
.
- Save and Commit your changes.
Your API is now protected with a rate limit of 1000 requests per hour for each unique Authorization
header value.
Scenario 2: Stricter Limits for Failed Logins¶
This scenario uses two zones and two rule phases to apply a lenient rate limit to all login attempts, but a much stricter limit to clients who have recently failed to log in.
Create the Zones¶
Create two new zones:
1. Zone 1 (Lenient):
- Name: login_attempts
- Requests: 20
- Interval (seconds): 300
(5 minutes)
- Block Duration (seconds): 300
2. Zone 2 (Strict):
- Name: failed_logins
- Requests: 5
- Interval (seconds): 3600
(1 hour)
- Block Duration (seconds): 3600
Create the Rules¶
Rule 1: Track all login attempts (Request Phase)
- Create a new rule in the Rate Limit Request phase.
- Rule Name:
Track All Login Attempts
- Filter:
http.request.uri.path == "/login" and http.request.method == "POST"
- Actions:
- Add to zone:
login_attempts
- Check zone:
login_attempts
, Action:block
- Zone Key:
IP address
- Add to zone:
- Save the rule.
Rule 2: Track failed logins (Response Phase)
- Create a new rule in the Rate Limit Response phase.
- Rule Name:
Track Failed Logins
- Filter:
http.response.code == 401
(Assuming your app returns 401 for failed logins). - Actions:
- Add to zone:
failed_logins
- Zone Key:
IP address
- Add to zone:
- Save the rule.
Rule 3: Block clients with failed logins (Request Phase)
- Create another new rule in the Rate Limit Request phase.
- Rule Name:
Block Failed Login Offenders
- Filter:
http.request.uri.path == "/login" and http.request.method == "POST"
- Actions:
- Check zone:
failed_logins
, Action:block
- Zone Key:
IP address
- Check zone:
- Save the rule.
-
Important: Drag this rule to be above the "Track All Login Attempts" rule. This ensures the stricter check happens first.
-
Commit your changes.
Now, all login attempts are tracked. If a client gets a 401
response, they are added to the failed_logins
zone. On their next login attempt, the stricter failed_logins
limit is checked first, quickly blocking brute-force attempts.
Scenario 3: Rate Limiting Based on WAF Events¶
This scenario uses the rate_limit_request_late
phase, which runs after the WAF, to challenge clients who trigger WAF rules.
Create the Zone¶
- Create a new zone:
- Name:
waf_offenders
- Requests:
10
- Interval (seconds):
60
- Block Duration (seconds):
900
(15 minutes)
- Name:
Create the Rule¶
- Create a new rule in the Rate Limit Request Late phase.
- Rule Name:
Challenge WAF Offenders
- Filter:
any(peakhour.waf.matched_rule.tags[*] == "sql-injection")
(This targets requests that triggered a WAF rule tagged with "sql-injection"). - Actions:
- Add to zone:
waf_offenders
- Check zone:
waf_offenders
, Action:challenge
- Zone Key:
IP address
- Add to zone:
- Save and Commit your changes.
Now, if a client triggers a SQL injection WAF rule, they will be added to the waf_offenders
zone. If they make more than 10 such attempts in a minute, they will be presented with a JavaScript challenge instead of being able to probe your application further.