1

I want configure different rate limiting for php-fpm.

I want to:

  1. static files had no limits,
  2. PHP requests had limits,
  3. PHP requests to / admin /.+ had different limits.

I have problem with implementation point 3. Now I test:

limit_req_zone $binary_remote_addr zone=php:10m rate=2r/s;
limit_req_zone $binary_remote_addr zone=admin:10m rate=9r/s;

server {
    location / {
        try_files $uri $uri/ /index.php?$args;
    }
    limit_req_status 429;
# limitng works, server return 404
    location ~ /admin/ {limit_req zone=admin...}

    location ~ [^/]\.php(/|$) {
        limit_req zone=php burst=9 delay=4;
#limit_req not allowed here
        if($request_uri ~ /admin) {limit_req zone=admin...}
#not update limits (lower)
        location ~ ^/admin/ {limit_req zone=admin...}
#negative matching returns index.php content
        location location ~ ^/(?!(admin)) {limit_req zone=php...}
    }
}

Also is limit_req_zone $request_uri but if I understand, this create different pools for /admin/1 and /admin/2.

//update 1:

I need different pools for request like: /index.php?/.* and less strict for /index.php?/admin/.*

2 Answers 2

5

According to the limit_req_zone directive documentation:

Requests with an empty key value are not accounted.

So just use two limit_req directives in your PHP handler location and made one of the zone keys empty depending on the $request_uri (either first or second request limit rate won't be applied in this case):

map $request_uri $is_admin {
    ~^/admin/  1;
    default    0;
}
map $is_admin $php_key {
    0 $binary_remote_addr;
    # an empty value otherwise by default
}
map $is_admin $admin_key {
    1 $binary_remote_addr;
    # an empty value otherwise by default
}

limit_req_zone $php_key zone=php:10m rate=2r/s;
limit_req_zone $admin_key zone=admin:10m rate=9r/s;

server {
    ...
    location ~ [^/]\.php(/|$) {
        limit_req zone=php ...
        limit_req zone=admin ...
        ...
1
  • pure magic! works like a charm Sep 15, 2023 at 7:28
0

According to documetation limit_req is allowed only in http, server, location.

I would suggest to exclude 1 & 2 and have common location with same policy as for / and admin :

server {
listen 127.0.0.1:8088;
location / {
content_by_lua_block {
    ngx.say("root")
    ngx.exit(ngx.HTTP_OK)

}
}
location ~* .(jpg|jpeg|gif|png|ico|css|bmp|swf|js|html|txt)$ {
content_by_lua_block {
    ngx.say("static")
    ngx.exit(ngx.HTTP_OK)

}
}
location ~* "^\/admin($|\/(.*)$)" {
content_by_lua_block {
    ngx.say("processed by php with first ratelimit")
    ngx.exit(ngx.HTTP_OK)

}
}
location ~* "\.php$" {
content_by_lua_block {
    ngx.say("processed by php with second ratelimit")
    ngx.exit(ngx.HTTP_OK)

}
}
}

And tests:

# curl 127.0.0.1:8088/admin
processed by php with first ratelimit
# curl 127.0.0.1:8088/admin.php
processed by php with second ratelimit
# curl 127.0.0.1:8088/admin/
processed by php with first ratelimit
# curl 127.0.0.1:8088/admin/test.php
processed by php with first ratelimit
# curl 127.0.0.1:8088/test/php
root
7
  • We didn't understand each other. Route /admin/ must be processed by php, but should have a different rate-limiting.
    – bato3
    Sep 6, 2019 at 13:05
  • I updated my unswer with test codeblock Sep 6, 2019 at 13:14
  • Sorry, I can't find the solution into to your answer. I have the situation: /index.php?/some - rate-limiting-1 and /index.php?/admin - less-strict-rate-limiting
    – bato3
    Sep 6, 2019 at 13:34
  • I didn;t get properly from first time) Updated once more Sep 6, 2019 at 13:36
  • 1
    yes in such case you will need to duplicate your php configuration inside 2 locations or create a separate file and include it. Sep 6, 2019 at 13:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .