Why do I want to do that?
Different reasons. One time, because I wanted a certain user not to access the dynamic WordPress site. Another time, I wanted to provide a bot that has been crawling the site with a “legitimate” page, without actually allowing it to go through the site. The main thing I was looking for is a way to do an internal redirect, so no 3xx code returned. I know there are probably better ways to achieve these goals (are there?). But hey, I learned some stuff about Nginx while doing this.
So here it goes, the first attempt:
location ~* /some/path/with_numbers/\d+ { if ($remote_addr = 11.11.111.1) { return 200 "sample reply - should be empty"; } # the next line is reached only when the above is not executed try_files $uri $uri/ /index.php$is_args$args; }
One problem with the above is that replacing the IP or adding more IPs is a bit problematic. So, we replace it with the following that relies on the Geo module:
geo $bad_ip { default 0; 1.2.3.4/32 1; 4.3.2.1/32 1; } server { [...] location ~* /some/path/with_numbers/\d+ { if ($bad_ip) { return 200 "sample reply - should be empty"; } # the next line is reached only when the above is not executed try_files $uri $uri/ /index.php$is_args$args; }
The other problem is that the text returned with the 200 code is a bit simplistic and I really wanted to send an HTML static page, not a stupid line. The fix uses error_page
[...] location ~* /some/path/with_numbers/\d+ { if ($bad_ip) { return 410; } error_page 410 =200 /my_static_page.html; # the next line is reached only when the above is not executed try_files $uri $uri/ /index.php$is_args$args; }
The result is a 200 (OK) code sent to the browser with a static HTML page that should load much faster than a PHP/RoR/etc alternative.
Of course, more can be done to identify the blocked entity, for example using UserAgent string, etc.
Leaving that for another day.