Я могу использовать limit_req
чтобы ограничить скорость всех запросов к моему серверу.
Однако я хотел бы снять ограничение скорости для определенных IP-адресов (например, белый список) и использовать другое ограничение скорости для некоторых других (то есть определенных IP-адресов, которые я хотел бы получить на уровне 1 р / с).
Я пробовал использовать условные выражения (например, if ( $remote_addr = "1.2.3.4" ) {}
), но похоже, что это работает только с правилами перезаписи, а не с правилами ограничения скорости.
Действительно, лучше избегать использования директивы «if». Когда ключ в limit_req_zone (и limit_conn_zone) пуст, ограничения не применяются. Вы можете использовать это вместе с модулями map и geo, чтобы создать белый список IP-адресов, для которых не применяются ограничения ограничения.
В этом примере показано, как настроить ограничение как для одновременных запросов, так и для скорости запросов с одного IP-адреса.
http {
geo $whitelist {
default 0;
# CIDR in the list below are not limited
1.2.3.0/24 1;
9.10.11.12/32 1;
127.0.0.1/32 1;
}
map $whitelist $limit {
0 $binary_remote_addr;
1 "";
}
# The directives below limit concurrent connections from a
# non-whitelisted IP address to five
limit_conn_zone $limit zone=connlimit:10m;
limit_conn connlimit 5;
limit_conn_log_level warn; # logging level when threshold exceeded
limit_conn_status 503; # the error code to return
# The code below limits the number requests from a non-whitelisted IP
# to one every two seconds with up to 3 requests per IP delayed
# until the average time between responses reaches the threshold.
# Further requests over and above this limit will result
# in an immediate 503 error.
limit_req_zone $limit zone=one:10m rate=30r/m;
limit_req zone=one burst=3;
limit_req_log_level warn;
limit_req_status 503;
Директивы зоны должны быть размещены на уровне http, однако другие директивы могут быть размещены ниже, например на сервере или на уровне местоположения, чтобы ограничить их область действия или дополнительно настроить ограничения.
Для получения дополнительной информации обратитесь к документации Nginx. ngx_http_limit_req_module и ngx_http_limit_conn_module
Вы можете безопасно использовать именованные местоположения, такие как «@location» в блоке if ().
Видеть: http://wiki.nginx.org/IfIsEvil
Примерно так должно работать:
http {
limit_req_zone $binary_remote_addr zone=delay:10m rate=1r/m;
server {
...
error_page 410 = @slowdown;
if( $remote_addr != "1.2.3.4" ) {
return 410;
}
location @slowdown {
limit_req zone=delay burst 5;
...
}
location / {
...
}
}
Заполните "location @slowdown {}" той же информацией, что и "location / {}", например proxy_pass, если вы используете nginx в качестве обратного прокси.