![Nginx 受信ヘッダー $http_q を使用した複数のレート制限](https://rvso.com/image/789301/Nginx%20%E5%8F%97%E4%BF%A1%E3%83%98%E3%83%83%E3%83%80%E3%83%BC%20%24http_q%20%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%9F%E8%A4%87%E6%95%B0%E3%81%AE%E3%83%AC%E3%83%BC%E3%83%88%E5%88%B6%E9%99%90.png)
http ブロックに次のようなレート制限設定があります。
# Rate limit config declaration
map $http_q $r_b001 {
b001 "1";
}
# Zone config
limit_req_zone $r_b001 zone=b001:100m rate=20r/s;
# Rate limit config declaration
map $http_q $r_c001 {
c001 "1";
}
# Zone config
limit_req_zone $r_c001 zone=c001:100m rate=25r/s;
そして、ロケーションブロック内には
location /c001{
limit_req zone=c001 burst=1 nodelay;
limit_req_status 429;
other config...
}
location /b001{
limit_req zone=b001 burst=1 nodelay;
limit_req_status 429;
other config...
}
現在、b001 キーと c001 を使用して負荷テストを実行すると、必要なレート制限制御が得られません。さらにキーと関連する構成を追加すると、偏差はさらに大きくなります。どこが間違っているのでしょうか。また、場所ごとにキーごとにこのようなレート制限をどのように実現するのでしょうか。
完全な構成は次のとおりです。
geoip2 /etc/nginx/geoip/geoLite-2Country/GeoLite2-Country.mmdb {
$geoip2_data_country_iso_code country iso_code;
}
include /etc/nginx/conf.d/geoip_config/*.conf;
include /etc/nginx/conf.d/blacklisted_config/*.conf;
##########################################################################################
# Whitelist config declaration
geo $whitelist_b001 {
default 1;
}
# Rate limit config declaration
map $http_q $r_b001 {
b001 "1";
default $request_id;
}
# Zone config
limit_req_zone $r_b001 zone=b001:100m rate=25r/s;
# Rate with White limit config
map $http_q $rw_b001 {
b001 $whitelist_b001;
default "0";
}
##########################################################################################
# Whitelist config declaration
geo $whitelist_c001 {
default 1;
}
# Rate limit config declaration
map $http_q $r_c001 {
c001 "1";
default $request_id;
}
# Zone config
limit_req_zone $r_c001 zone=c001:100m rate=15r/s;
# Rate with White limit config
map $http_q $rw_c001 {
c001 $whitelist_c001;
default "0";
}
# API Check, regex matches to 1 if one value corresponds to 1
map $r_b001$r_c001 $API_CHECK {
default 0;
~((1)) 1;
}
#Pass through check, regex matches to 1 if one value corresponds to 1
map $rw_b001$rw_c001 $PASS_THROUGH{
~((1)) 1;
}
server {
#*****************************
# LISTEN PORT AND SERVER NAME
#*****************************
listen 443 ssl http2;
server_name api.com;
client_body_buffer_size 16k;
client_max_body_size 16k;
access_log /var/log/nginx/app/access.log json_output;
#*****************************
# ROOT PATH
#*****************************
root /var/www/html;
#*****************************
# INDEX PAGE
#*****************************
location / {
try_files $uri$args $uri$args/ =404;
}
#***************************************
# Key and IP Validators
#**************************************
if ($API_CHECK = 0) {
return 401 '{"status": "failure","status_code": 401 ,"custom_status_code": "XXXX","request_id": "$request_id","date_time": "$date_gmt","detail": "API key is Invalid"}';
}
if ($allowed_country = no) {
return 403 '{"status": "failure","status_code": 403 ,"custom_status_code": "XXXX","request_id": "$request_id","date_time": "$date_gmt","detail": "Your request to this site is forbidden"}';
}
if ($blacklisted_ip = 1) {
return 403 '{"status": "failure","status_code": 403 ,"custom_status_code": "XXXX","request_id": "$request_id","date_time": "$date_gmt","detail": "Your request to this site is forbidden"}';
}
if ($PASS_THROUGH = 0) {
return 403 '{"status": "failure","status_code": 403 ,"custom_status_code": "XXXX","request_id": "$request_id","date_time": "$date_gmt","detail": "Your request to this site is forbidden"}';
}
#*****************************
# Application re-route
#*****************************
location ^~ /api {
rewrite ^/api/(.*)$ /proxyapi/$http_q/$1?$args last;
}
location ^~ /proxyapi/b001 {
# Limit req zone inside its own block
limit_req zone=b001 burst=1 nodelay;
limit_req_status 429;
alias /var/www/html/risk_app/public;
try_files $uri $uri/ @risk_laravel_b001;
index index.php;
# Deny .htaccess
location ~ /\.ht{
deny all;
return 404;
}
# FastCGI Configuration
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
include fastcgi_params;
fastcgi_read_timeout 600;
fastcgi_param SCRIPT_FILENAME /var/www/html/risk_app/public/index.php;
fastcgi_param SSL_CLIENT_VERIFY $ssl_client_verify;
fastcgi_param SSL_CLIENT_S_DN $ssl_client_s_dn;
fastcgi_param NGINX_REQUEST_ID $request_id;
}
}
location @risk_laravel_b001 {
rewrite /proxyapi/b001/(.*)$ /proxyapi/b001/index.php?/$1 last;
}
location ^~ /proxyapi/c001 {
# Limit req zone inside its own block
limit_req zone=default_zone burst=1 nodelay;
limit_req_status 429;
alias /var/www/html/risk_app/public;
try_files $uri $uri/ @risk_laravel_c001;
index index.php;
# Deny .htaccess
location ~ /\.ht{
deny all;
return 404;
}
# FastCGI Configuration
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
include fastcgi_params;
fastcgi_read_timeout 600;
fastcgi_param SCRIPT_FILENAME /var/www/html/risk_app/public/index.php;
fastcgi_param SSL_CLIENT_VERIFY $ssl_client_verify;
fastcgi_param SSL_CLIENT_S_DN $ssl_client_s_dn;
fastcgi_param NGINX_REQUEST_ID $request_id;
}
}
location @risk_laravel_c001 {
rewrite /proxyapi/c001/(.*)$ /proxyapi/c001/index.php?/$1 last;
}
location /ping {
access_log off;
return 200 '{"status":"succes","status_code": 200}';
}
}