Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

So I have a spammer on my site. I could block his IP using 'deny', but then he'll just change his IP and I'll have to keep playing cat and mouse with him.

Instead, I am curious if there is a way to configure nginx to respond to his IP more slowly.

That way maybe he'll just decide the site is not functioning correctly and leave me alone.

Thanks

share|improve this question

3 Answers 3

up vote 4 down vote accepted

Nginx directive limit_rate lets you specify the speed you'd like to rate limit responses, e.g.

location / {
  if ($slow) {
    limit_rate 4k;
  }
}

Nginx documentation is here. (from the documentation you'll see that your backend may make the decision and request Nginx to rate limit the client)

How you get this $slow variable set depends on your configuration. The easiest would be to set it via geo mapping:

geo $slow {
  default    0;

  1.2.3.0/24 1;
}

"Geo" mapping is a dependency of $slow based on the client IP address. It's 0 by default and 1 if a client IP address is in 1.2.3.0/24 subnet. See Nginx documentation on "geo" here

Using "fail2ban" is a reasonable evolution of this whole solution. You may use "fail2ban" to automatically detect unusual activity and collect IPs for Nginx and then reload Nginx so that it re-reads lists of IP addresses that need to be slowed down and/or blocked.

share|improve this answer

If you want to trick the offending user into thinking that he is still going unnoticed by you, you can use nginx's request limit module (http://wiki.nginx.org/HttpLimitReqModule).

First define a request limit zone:

http {
    limit_req_zone  $binary_remote_addr  zone=spammers:1m   rate=30r/m;
}

This zone will use the offender's IP address in order to identify and limit requests into 30 per minute (1 / 2 sec). Please note that the zone's memory size is set to 1 MiB, which means it can handle 1 MiB / 64 bytes per request bucket = 16384 spammer addresses (which is maybe an overkill for our case). Adjust respectively, if you must.

Next, we define the directive that will actually route the offender through the limiter using an (evil, unfortunately) if case:

location / {
    if ($remote_addr = 1.2.3.4) {
        limit_req   zone=spammer  burst=5;
    }
}

You can watch the fruits of your labor in the server's access log.

Note that this hack does not scale well, since you'll have to update the configuration file each time the offender changes IP (let alone include more IPs in there which means more if cases), but it works.

share|improve this answer
1  
You can also combine my answer with Alexander Azarov's geo block and make it more scalable! –  Panagiotis PJ Papadomitsos Nov 24 '12 at 16:52

Best way to deal with this spammer is to proper install and configure fail2ban. Fail2ban will search patterns in log files and block all ips that spam your site. Ofcourse you must configure it to search proper pattern.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.