Blocking POST requests for abusive ips with nginx

In the past we received abuse, especially from a certain ISP in Brazil. This was stopped by putting all IP ranges from this ISP in the iptables. This method was not preferable because it blocked complete access to the site. We now implemented a way to read from a plain text list of ips or ip ranges into nginx format with CentOS as OS.

This script is for converting ips into nginx format, its executed by using php on CLI:

echo "geo \$postbanned {\n";
echo "default 0;\n";
while($f = fgets(STDIN)){
$ip = rtrim($f, "\r\n");
if (substr_count($ip, ".") == 2) {
$sp = explode("/", $ip);
$ip = $sp[0] . ".0" . "/" . $sp[1];
if (substr_count($ip, ".") == 1) {
$sp = explode("/", $ip);
$ip = $sp[0] . ".0.0" . "/" . $sp[1];
echo $ip . " 1;\n";
echo "}\n";

For example, our list of ips.txt holds 3 ips.

We would use the following command to convert them and directly drop them into the nginx.d folder (Location of nginx on centos)

cat ips.txt | php convert.php > /etc/nginx/conf.d/banned.conf

This file would look something like this:

geo $postbanned {
default 0; 1; 1; 1;

After this we drop some lines in our nginx config, between the server {} on what site we would like to apply this config on.

set $ban 1;
if ($postbanned != 1) {
set $ban 0;
if ($request_method = GET) {
set $ban 0;
if ($request_method = HEAD) {
set $ban 0;
if ($ban = 1) {
return 403;

And that should do it, all POST requests are now banned for all ips you have in the banned list. This will prevent these ips from doing any harm to the site by uploading/commenting/etc.

All credits go to sinni800 for making the scripts.

Categorized: Technical

4 comments on “Blocking POST requests for abusive ips with nginx

  1. If a request is blacklisted or throttled, the response is a very simple Rack response. A single typical ruby web server thread can block several hundred requests per second.

Leave a Reply

Your email address will not be published. Required fields are marked *