Token-based лимитирование количества подключений Все знают про лимиты количества подключений с одного IP (IP-based), но что делать, если мы хотим ограничить количество подключений к некому API на один токен авторизации? И не важно, сколько разных IP будет использовано.
Часть конфига nginx:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
map $request_uri $client_token {
"~*(?i)(token=)([a-f0-9]{32})" $2; # regex return <32str>
default ""; # Fallback to limit_req_zone:global
}
limit_req_zone $binary_remote_addr zone=global:32m rate=100r/s; # Rule_1
limit_req_zone $client_token zone=tokenlimit:32m rate=5r/s; # Rule_2
limit_req zone=global burst=25;
server {
location / {
index index.html;
root /var/www/html;
}
location = /api {
index index.html;
root /var/www/api/html;
limit_req zone=tokenlimit burst=5 nodelay; # api location
limit_req zone=global; # Fallback
limit_req_status 429; # 503
Пример смешанной блокировки Имитируем множество подключений с хоста A без токена.
ab -n 999 -c 5 "http://api.tld/api?id=letmein"
Проверяем и получаем блокировку IP A Не зависимо от наличия токена, он превысил правило Rule_1 .
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
curl -v "http://api.tld/api?token=00000000000000000000000000000000"
< HTTP/1.1 429 Too Many Requests
< Server: nginx
< Date: Sun, 22 Jun 2024 20:03:37 GMT
< Content-Type: text/html
< Content-Length: 162
< Connection: keep-alive
<
<html>
<head><title>429 Too Many Requests</title></head>
<body>
<center><h1>429 Too Many Requests</h1></center>
<hr><center>nginx</center>
</body>
</html>
IP B при этом подключается без проблем Он не превысил ни общее число подключений с одного IP Rule_1 , ни количество подключений на один токен Rule_2 .
1
2
3
4
5
6
7
8
9
10
curl -v "http://api.tld/api?token=00000000000000000000000000000000"
< HTTP/1.1 200 OK
< Server: nginx
< Date: Sun, 22 Jun 2024 20:04:18 GMT
< Content-Type: text/plain; charset=utf-8
< Content-Length: 801
< Connection: keep-alive
< X-App-TOKEN: 00000000000000000000000000000000
Пример превышения лимита на один токен Хост A Имитируем множество подключений с хоста A используя токен (111).
1
ab -n 999 -c 5 "http://api.tld/api?token=11111111111111111111111111111111"
Получаем блокировку токена 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
curl -v "http://api.tld/api?token=11111111111111111111111111111111"
< HTTP/1.1 429 Too Many Requests
< Server: nginx
< Date: Sun, 22 Jun 2024 20:10:48 GMT
< Content-Type: text/html
< Content-Length: 162
< Connection: keep-alive
<
<html>
<head><title>429 Too Many Requests</title></head>
<body>
<center><h1>429 Too Many Requests</h1></center>
<hr><center>nginx</center>
</body>
</html>
Хост B Пробуем использовать этот же токен (111) с хоста B.
Получаем такую же блокировку токена 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
curl -v "http://api.tld/api?token=11111111111111111111111111111111"
< HTTP/1.1 429 Too Many Requests
< Server: nginx
< Date: Sun, 22 Jun 2024 20:12:42 GMT
< Content-Type: text/html
< Content-Length: 162
< Connection: keep-alive
<
<html>
<head><title>429 Too Many Requests</title></head>
<body>
<center><h1>429 Too Many Requests</h1></center>
<hr><center>nginx</center>
</body>
</html>
Пробуем использовать другой токен (000) с хоста B.
Успешное подключение 1
2
3
4
5
6
7
8
9
10
curl -v "http://api.tld/api?token=00000000000000000000000000000000"
< HTTP/1.1 200 OK
< Server: nginx
< Date: Sun, 22 Jun 2024 20:09:07 GMT
< Content-Type: text/plain; charset=utf-8
< Content-Length: 805
< Connection: keep-alive
< X-App-TOKEN: 00000000000000000000000000000000
Таким образом можно комбинировать разные лимиты, основываясь не только на IP, но и на параметрах запроса или location.
2024-06-22 23:25 +0000