Nginx: Allow All But Block Certain POST Request URLS For Selected Spammer IP Address/CIDR

by on December 2, 2013 · 1 comment· LAST UPDATED December 2, 2013

in , , ,

I am a small business and ecom site owner. I also run a WordPress based blog to connect with my customers. However, I get too much spam from certain IPs and net-blocks. How do I block access to certain url(s) such as example.com/blog/wp-comments-post.php for selected IP address and CIDRs? How do I allow everyone including IP address 1.2.3.4 to access my blog but block IP address 1.2.3.4 accessing only example.com/blog/wp-comments-post.php? How do I block POST requests for selected IPs/CIDR on nginx?

Tutorial details
DifficultyIntermediate (rss)
Root privilegesYes
Requirementsnginx
ngx_http_geo_module
Estimated completion time10m
Nginx comes with a simple module called ngx_http_access_module to allow or deny access to IP address. You can also create a config file and block certain urls using the following method.

Step #1: Create spammers.conf file

Create a file called /etc/nginx/spammers.conf, enter:
# vi /etc/nginx/spammers.conf
You need to use the ngx_http_geo_module. This modile creates variables with values depending on the client IP address or CIDR. The syntax is:

geo $var_name {
    default value1;
    ip value2;
    cidr value2;
}

In this example, block IPs/CIDRs - 101.0.71.27, 101.0.79.181, 101.0.79.27, 100.42.192.0/20, 101.192.0.0/14, and 148.248.0.0/16:

# spammers.conf #
geo $spammers_ip_cidrs {
      ## allow all ##
      default no;
      ## block these bad ips/cidrs/spammers ##
      101.0.71.27 yes; 
      101.0.79.181 yes;
      101.0.79.27 yes; 
      100.42.192.0/20 yes; 
      101.192.0.0/14 yes;
      148.248.0.0/16 yes;
}

Step #2: Update nginx.conf

Edit nginx.conf, enter:
# vi /etc/nginx/nginx.conf
Add the following in http section:

include /etc/nginx/spammers.conf;

Find your server section and add the following to match your POST request url:

 
 location ~* /blog/wp-comments-post\.php$ {
    if ( $spammers_ip_cidrs = yes ) {
       ## show default or custom forbidden page. To create black-hole use 444 code
       return 403;
   }
 

Here is a sample config directive for reverse proxy server:

  server {
    listen      75.126.153.206:80;
    server_name www.cyberciti.biz;
    access_log  /var/log/nginx/access.log main;
    error_log   /var/log/nginx/error.log;
    root        /nfs/ha/root/nginx;
    index       index.html;
 
## custom error pages put them at /nfs/ha/root/nginx location ##
    error_page 404 /error-page-404.html;
    location  /error-page-404.html {
          internal;
        }
 
    error_page 403 /error-page-403.html;
        location = /error-page-403.html {
          internal;
    }
 
## location section ##
      location / {
        proxy_pass  http://backendapache;
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
 
        proxy_set_header        Host            www.cyberciti.biz;
        proxy_set_header        X-Real-IP       $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        location ~* /blog/wp-comments-post\.php$ {
                if ( $spammers_ip_cidrs = yes ) {
                        return 403;
                }
        ## add rest of config for matching url here ##
        }
      }
  }
 

Save and close the file. Restart / reload nginx server, enter:
# service nginx reload
A visitor with an IP address 75.126.153.206 can browser your entire blog but will not able to post any comments. He/she (most likely a bot) will get an error code forbidden 403. A sample 403 error page:

Fig. 01: Custom nginx 403 page for www.cyberciti.biz

Fig. 01: Custom nginx 403 page for www.cyberciti.biz


See how to create a custom 403/404 page using nginx for more information.

How do I find out spammers IP address?

Use the grep command as follows:

 
grep '/blog/wp-comments-post.php' access_1.log
## Find all  url /blog/wp-comments-post.php  accessed on 30/Nov/2013 ##
## last sort is bad ##
grep '30/Nov/2013 | grep '/blog/wp-comments-post.php' /path/to/archives/access_1.log | awk '{ print $1}' | sort  | uniq -c | sort -nr > spam.txt

Sample outputs:

 $ cat spam.txt
    22304 221.234.211.192
    22133 221.235.67.111
    11174 142.4.113.57
    11110 192.184.37.126
     4235 37.0.122.237
...

No sane person will try to submit comment 22304 times. So you can block all those IPs. You can automate the entire procedure by writing a shell/python/perl script. The writing of such script is left as an exercise to the readers.

TwitterFacebookGoogle+PDF versionFound an error/typo on this page? Help us!

{ 1 comment… read it below or add one }

1 Basza December 6, 2013 at 1:12 pm

Nice, but I think, better block spammer IP on firewall – not only in nginx.

Reply

Leave a Comment

Tagged as: , , , ,

Previous Faq:

Next Faq: