![Nginx 使用傳入標頭 $http_q 進行多重速率限制](https://rvso.com/image/789301/Nginx%20%E4%BD%BF%E7%94%A8%E5%82%B3%E5%85%A5%E6%A8%99%E9%A0%AD%20%24http_q%20%E9%80%B2%E8%A1%8C%E5%A4%9A%E9%87%8D%E9%80%9F%E7%8E%87%E9%99%90%E5%88%B6.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}';
}
}