You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/hypernode-platform/nginx/how-to-resolve-rate-limited-requests-429-too-many-requests.md
+89-41Lines changed: 89 additions & 41 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,7 +12,7 @@ redirect_from:
12
12
13
13
# How to Resolve Rate Limited Requests (429 Too Many Requests)
14
14
15
-
To protect your Hypernode from all kinds of attacks, bots, brute forces, and scriptkiddies causing downtime, we've implemented several layers of rate limiting.
15
+
To protect your Hypernode from all kinds of attacks, bots, brute forces, and script kiddies causing downtime, we've implemented several layers of rate limiting.
16
16
17
17
Most of these rate-limit methods only apply to bots. Still, to avoid FPM worker depletion, we [implemented a rate-limiting mechanism per IP](https://changelog.hypernode.com/release-4735-upper-limit-active-php-requests-per-ip/) to prevent one single IP from exhausting the available FPM workers.
18
18
@@ -25,16 +25,16 @@ On Hypernode we currently differentiate between two rate limiting methods and th
25
25
- Rate limiting based on User Agents and requests per second (zone `bots`)
26
26
- Rate limiting based on requests per IP address (zone `zoneperip`)
27
27
28
-
Both methods are implemented using [NginX's limit_req module](http://nginx.org/en/docs/http/ngx_http_limit_req_module.html)
28
+
Both methods are implemented using [Nginx's limit_req module](https://nginx.org/en/docs/http/ngx_http_limit_req_module.html)
29
29
30
30
### Determining the Applied Rate Limiting Method
31
31
32
-
You can quickly determine which method of Rate Limiting was the cause of the request being 429'd since each time any of the rate-limiting methods are hit, a message with be logged in the Nginx error log.
32
+
You can quickly determine which method of rate limiting was the cause of the request being 429'd since each time any of the rate-limiting methods are hit, a message will be logged in the Nginx error log.
33
33
34
34
To look for rate limiting messages in the error log, you can run the following command:
2020/06/07 13:33:37 [error] limiting requests, excess: 0.072 by zone "bots", client: 203.0.113.104, server: example.hypernode.io, request: "GET /api/ HTTP/2.0", host: "example.hypernode.io"
39
39
2020/06/07 13:33:37 [error] limiting connections by zone "zoneperip", client: 198.51.100.69, server: example.hypernode.io, request: "POST /admin/ HTTP/2.0", host: "example.hypernode.io"
40
40
```
@@ -51,7 +51,7 @@ A log entry where the rate limit is applied per IP address (based on the `zonepe
51
51
2020/06/07 13:33:37 [error] limiting connections by zone "zoneperip", client: 198.51.100.69, server: example.hypernode.io, request: "POST /admin/ HTTP/2.0", host: "example.hypernode.io"
52
52
```
53
53
54
-
**Note: PerIP rate limiting only applies to requests handled by PHP and not to the static content.**
54
+
**Note: Per‑IP rate limiting only applies to requests handled by PHP and not to static content.**
55
55
56
56
## Rate Limiting for Bots and Crawlers
57
57
@@ -63,7 +63,7 @@ Since our goal is not to block bots but to rate limit them nicely, we must be ca
63
63
64
64
### How to Configure the Bot Rate Limiter
65
65
66
-
Some bots are default exempt from rate limitings, like Google, Bing, and several monitoring systems. These bots never get rate limited since they usually abide by the robots.txt. However, some bots don't follow the instructions given in robots.txt or are used by abusive crawlers. These bots will be rate limited at one request per second. Any requests over this limit will then return a 429 error. If you want, you can override the system-wide configuration on who gets blocked and who does not. To get started, place the following in a config file called `/data/web/nginx/http.ratelimit`:
66
+
Some bots are exempt from rate limiting by default, like Google, Bing, and several monitoring systems. These bots never get rate limited since they usually abide by the robots.txt. However, some bots don't follow the instructions given in robots.txt or are used by abusive crawlers. These bots will be rate limited at one request per second. Any requests over this limit will then return a 429 error. If you want, you can override the system-wide configuration on who gets blocked and who does not. To get started, place the following in a config file called `/data/web/nginx/http.ratelimit`:
As you can see, this sorts all visitors into two groups:
79
79
80
-
- On the first line, the allowlist, you find the keywords that are exempt from the rate liming, like: `google`, `bing`, `heartbeat`, or `magereport.com`.
81
-
- The second line, contains keywords for generic and abusive bots and crawlers, which can trigger the ratelimiter, like `crawler`, `spider`, or `bot`
80
+
- On the first line, the allowlist, you find the keywords that are exempt from rate limiting, like: `google`, `bing`, `heartbeat`, or `magereport.com`.
81
+
- The second line contains keywords for generic and abusive bots and crawlers, which can trigger the rate limiter, like `crawler`, `spider`, or `bot`.
82
82
83
83
The keywords are separated by `|` characters since it is a regular expression.
84
84
@@ -97,14 +97,14 @@ In the example above you can see that a bot with the User Agent `SpecialSnowflak
Instead of adding the complete User Agent to the regex, it’s often better to limit it to just an identifying keyword, as shown above. The reason behind this is that the string is evaluated as a Regular Expression, which means that extra care needs to be taken when adding anything other than alphanumeric characters. Also as user agents might change slightly over time, this may this bot will no longer be allowlisted over time.
105
+
Instead of adding the complete User Agent to the regex, it’s often better to limit it to just an identifying keyword, as shown above. The reason behind this is that the string is evaluated as a Regular Expression, which means that extra care needs to be taken when adding anything other than alphanumeric characters. Also, as user agents might change slightly over time, an overly specific string may stop matching and the bot will no longer be allowlisted.
106
106
107
-
### Known Rate Limited Plugins and Service Provider
107
+
### Known Rate Limited Plugins and Service Providers
108
108
109
109
There are a couple of plugins and service providers that tend to hit the blacklisted keyword in the `http.ratelimit` snippet and, therefore, may need to be excluded individually. Below we have listed them and their User Agents for your convenience
110
110
@@ -115,74 +115,122 @@ There are a couple of plugins and service providers that tend to hit the blackli
115
115
- Mollie - `Mollie.nl HTTP client/1.0`
116
116
- Screaming - `Screaming Frog SEO Spider`
117
117
118
-
Besides the above-known plugins that will hit the blacklisted keyword, `http.ratelimit` we know that Picqer will also hit the rate limiter because of being blocked by "**zoneperip**". Please find [here](https://picqer.com/files/ip-addresses.txt) the IP addresses of Picqer. You can exclude those IP addressess from hitting the rate limiter if you follow the [instructions](#known-rate-limited-plugins-and-service-provider).
118
+
Besides the above-known plugins that will hit the blacklisted keyword, `http.ratelimit` we know that Picqer will also hit the rate limiter because of being blocked by "**zoneperip**". Please find [here](https://picqer.com/files/ip-addresses.txt) the IP addresses of Picqer. You can exclude those IP addresses from hitting the rate limiter if you follow the [instructions](#known-rate-limited-plugins-and-service-providers).
119
119
120
120
## Rate Limiting per IP Address
121
121
122
122
To prevent a single IP from using all the FPM workers available simultaneously, leaving no workers available for other visitors, we implemented a per IP rate limit mechanism. This mechanism sets a maximum amount of PHP-FPM workers that can be used by one IP to 20. This way, one single IP address cannot deplete all the available FPM workers, leaving other visitors with an error page or a non-responding site.
123
123
124
124
**Please note:** if [Hypernode Managed Vhosts](hypernode-managed-vhosts.md) is enabled, only add the `http.ratelimit` file in the Nginx root. Don't add it to the specific vhost as well, as this may cause conflicts.
125
125
126
-
### Exclude IP Addresses from the per IP Rate Limiting
126
+
### How per‑IP limiting works (what you can influence)
127
127
128
-
In some cases, it might be necessary to exclude specific IP addresses from the per IP rate limiting. If you wish to exclude an IP address, you can do so by creating a config file called `/data/web/nginx/http.ratelimit` with the following content:
128
+
The platform manages the global per‑IP limiter (zone and limits). You control only the key variable used for counting connections: `$limit_conn_per_ip`. If this variable is an empty string, the per‑IP limiter is effectively disabled for that request; if it contains the client IP, that request is counted towards that IP.
129
+
130
+
### Exclude IP addresses from the per‑IP rate limiting
131
+
132
+
In some cases, it might be necessary to exclude specific IP addresses from the per‑IP rate limiting. Define an allowlist and compose the effective key using a geo→map chain in `/data/web/nginx/http.ratelimit`:
129
133
130
134
```nginx
131
-
geo $limit_conn_per_ip {
132
-
default $remote_addr;
133
-
198.51.100.69 '';
135
+
# 1) Mark IPs/CIDRs that should be exempt from per‑IP limiting
136
+
geo $limit_conn_ip_allow {
137
+
default 1; # 1 = enforce limit
138
+
1.2.3.4 0; # 0 = exempt
139
+
}
140
+
141
+
# 2) Build the base key used for per‑IP limiting. If exempt → empty key disables per‑IP limiting for this request
In this example, we have excluded the IP address **198.51.100.69** by setting an empty value in the form of `''`.
156
+
In this example, we have excluded the IP address **1.2.3.4** by emitting an empty key, no URL whitelists are active in the above example.
138
157
139
-
In addition to excluding a single IP address, it is also possible to allow a whole range of IP addresses. You can do this by using the so-called CIDR notation (e.g., 198.51.100.0/24 to whitelist all IP addresses within the range 198.51.100.0 to 198.51.100.255). In that case, you can use the following snippet in `/data/web/nginx/http.ratelimit` instead:
158
+
In addition to excluding a single IP address, it is also possible to allow a whole range of IP addresses. You can do this by using the so-called CIDR notation (e.g., 198.51.100.0/24 to allowlist all IP addresses within the range 198.51.100.0 to 198.51.100.255). Extend the `geo` block accordingly:
140
159
141
160
```nginx
142
-
geo $limit_conn_per_ip {
143
-
default $remote_addr;
144
-
198.51.100.0/24 '';
161
+
geo $limit_conn_ip_allow {
162
+
default 1;
163
+
1.2.3.1 0;
164
+
1.2.3.0/24 0;
145
165
}
146
166
```
147
167
148
-
### Disable perIP Rate Limiting
168
+
### Disable per‑IP rate limiting
149
169
150
170
When your shop performance is very poor, it’s possible all your FPM workers are busy just serving regular traffic. Handling a request takes so much time that all workers are continuously depleted by a small number of visitors. We highly recommend optimizing your shop for speed and a temporary upgrade to a bigger plan if this situation arises. Disabling the rate limit will not fix this problem but only change the error message from a `Too many requests` error to a timeout error.
151
171
152
-
For debugging purposes, however, it could be helpful to disable the per-IP connection limit for all IP’s. With the following snippet in `/data/web/nginx/http.ratelimit`, it is possible to altogether disable IP based rate limiting:
172
+
For debugging purposes, however, it could be helpful to disable the per‑IP connection limit for all IPs. With the following snippet in `/data/web/nginx/http.ratelimit`, it is possible to disable per‑IP rate limiting entirely by emitting an empty key for all requests:
153
173
154
174
```nginx
155
-
geo $limit_conn_per_ip {
175
+
map $request_uri $limit_conn_per_ip {
156
176
default '';
157
177
}
158
178
```
159
179
160
-
**Warning: Only use this setting for debugging purposed! Using this setting on production Hypernodes is highly discouraged, as your shop can be easily taken offline by a single IP using slow and/or flood attacks.**
180
+
**Warning: Only use this setting for debugging purposes! Using this setting on production Hypernodes is highly discouraged, as your shop can be easily taken offline by a single IP using slow and/or flood attacks.**
161
181
162
-
### Exclude Specific URLs from the perIP Rate Limiting Mechanism
182
+
### Exclude specific URLs from the per‑IP rate limiting mechanism
163
183
164
-
To exclude specific URLs from being rate-limited you can create a file `/data/web/nginx/server.ratelimit`with the following content:
184
+
To exclude specific URLs from being rate‑limited, use the `map $request_uri $limit_conn_per_ip` you added above in `/data/web/nginx/http.ratelimit`and add/uncomment entries like:
165
185
166
186
```nginx
167
-
set $ratelimit_request_url "$remote_addr";
168
-
if ($request_uri ~ ^\/(.*)\/rest\/V1\/example-call\/(.*) ) {
169
-
set $ratelimit_request_url '';
170
-
}
171
-
172
-
if ($request_uri ~ ^\/elasticsearch.php$ ) {
173
-
set $ratelimit_request_url '';
187
+
map $request_uri $limit_conn_per_ip {
188
+
default $limit_conn_per_ip_base;
189
+
~^/rest/V1/example-call/ '';
190
+
~^/elasticsearch\.php$ '';
191
+
~^/graphql$ '';
174
192
}
175
193
```
176
194
177
-
In the example above, the URLs `*/rest/V1/example-call/*` and `/elasticsearch.php` are the ones that have to be excluded. You now have to use the `$ratelimit_request` variable as a default value in the file `/data/web/nginx/http.ratelimit` (see below) to exclude these URLs from the rate limiter and make sure that bots and crawlers will still be rate limited based on their User Agent.
195
+
With these entries, the URLs `*/rest/V1/example-call/*`, `/elasticsearch.php`, and `/graphql` are excluded from per‑IP limiting. The platform’s global limiter will use `$limit_conn_per_ip` implicitly. You can also combine this with a regular allowlist, as described above.
178
196
179
-
```nginx
180
-
geo $limit_conn_per_ip {
181
-
default $ratelimit_request_url;
182
-
}
197
+
### Debugging per‑IP rate limiting
198
+
199
+
Define a custom JSON log format that records the effective per‑IP key and enable it. Add the JSON log format in `/data/web/nginx/http.ratelimit`:
200
+
201
+
Ensure the log directory exists:
202
+
203
+
```bash
204
+
mkdir -p /data/web/log
205
+
```
206
+
207
+
Then configure the JSON log format and enable the access log:
208
+
209
+
```text
210
+
log_format custom escape=json '{'
211
+
'"time":"$time_iso8601", '
212
+
'"remote_addr":"$remote_addr", '
213
+
'"host":"$http_host", '
214
+
'"request":"$request", '
215
+
'"status":"$status", '
216
+
'"request_time":"$request_time", '
217
+
'"user_agent":"$http_user_agent", '
218
+
'"limit_conn_per_ip":"$limit_conn_per_ip"'
219
+
'}';
220
+
access_log /data/web/log/nginx-custom custom;
183
221
```
184
222
185
-
You can also combine this with a regular allowlist, and exclude IP Addresses as described above.
Copy file name to clipboardExpand all lines: docs/hypernode-platform/php/what-limits-apply-to-active-php-requests-per-ip.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -20,4 +20,4 @@ When one IP uses up most or all of the available workers, this causes a processi
20
20
21
21
Previously we configured a limit of `vCPUs * 5 - 2`. For our largest Hypernode plans, this could theoretically mean one IP using up to 99% of the available workers. This is undesired behaviour, but it can happen when a lot of people are accessing the admin pages from one office IP. This is why we have chosen to set the limit at 30 workers per IP.
22
22
23
-
Users that overstep this limit will be served a [429 too many requests status code](../nginx/how-to-resolve-rate-limited-requests-429-too-many-requests.md). You can always circumvent this per IP rate-limiting by [whitelisting IP's in the NGINX config](../nginx/how-to-resolve-rate-limited-requests-429-too-many-requests.md#exclude-ip-addresses-from-the-per-ip-rate-limiting).
23
+
Users that overstep this limit will be served a [429 too many requests status code](../nginx/how-to-resolve-rate-limited-requests-429-too-many-requests.md). You can always circumvent this per IP rate-limiting by [whitelisting IP's in the NGINX config](../nginx/how-to-resolve-rate-limited-requests-429-too-many-requests.md#rate-limiting-per-ip-address).
0 commit comments