WordPress login and XML-RPC endpoints at wp-login.php
and xmlrpc.php
respectively are the mostly widely abused targets for bots scanning the web for sites with weak passwords. Here is a simple Nginx configuration snippet that allows you to set the limit_req
depending on the request path and method.
First, define the limit_req_zone
at the http {}
level and conditionally enable it only for POST
requests to the desired request URIs by setting the limit request zone input to $binary_remote_addr
while keeping it undefined for all the un-mapped requests:
map "$request_method:$uri" $wp_post_limit_key {
POST:/wp-login.php $binary_remote_addr;
POST:/xmlrpc.php $binary_remote_addr;
}
limit_req_zone $wp_post_limit_key zone=wp_post_limit_zone:10m rate=5r/m;
where:
$wp_post_limit_key
is our custom variable name that is either unset by default or equal to$binary_remote_addr
when the current request should be rate-limited.wp_post_limit_zone
is our custom zone name that must be referenced inlimit_req
of eachserver {}
block.rate=5r/m
sets the allowed request rate from the same IP to 5 requests per minute. You can change it to2r/s
if you wanted to permit 2 request per second.
And then add it to the PHP location in each of your server {}
blocks:
location ~ \.php$ {
try_files $uri =404;
limit_req zone=wp_post_limit_zone;
// ...
}
You can define multiple limit_req_zone
configurations for different request mapping logic and apply them all to the same PHP location block.
Adjust the HTTP Response Code
By default Nginx responds with HTTP 503 Service Unavailable status code to all throttled requests. Use the limit_req_status
directive to change it to 429 Too Many Requests in either http {}
or server {}
block:
limit_req_status 429;
Oh! I like this use of the map with the method and URL.
Right!? I have been using it to also detect WebP support via
$http_accept
and then append any image requests with.webp
as they get generated on upload.Cool :) This made me make the same rule in Azure Front Door:
https://gist.github.com/soderlind/38ba10db6603db449c7f4a9333491c41