My web server is currently flooded with content spammers.

I don't want to completely block the IPs using iptables because they are from dynamic IPs and if I block one IP then after a few minutes the spam comes from another IP so I assume it uses a bot net of infected PCs which probably do reconnects and I don't want to end up in completely blocking an whole ISP or to permanently block tor exit nodes. So I want to use soft blocking similar to what cloud-flare and google do. They display a webpage for those bad scored IPs containing a information why they are blocked and a possibility to unblock.

I also have a solution how I could achieve that, but I'm wondering if there is a better way to solve that.

I have a catch all rule that will pass the request to my application that scores the IP, if the IP is has a bad score the info page will be displayed with a 502 error. If the IP is fine then a 418 is returned and the request is passed to @final-pass

location ~ {
  error_page 500 418 = @final-pass;

  proxy_set_header X-Real-IP  $remote_addr;
  proxy_set_header X-Forwarded-For $remote_addr;
  proxy_set_header Host $host;
  proxy_intercept_errors on;
  proxy_pass http://unix:/tmp/ip-check.sock;


Then I have the @final-pass this one will forward the request to a second nginx instance which has a regular setup will all virtual hosts:

location @final-pass {
  proxy_read_timeout      300;
  proxy_connect_timeout   300;
  proxy_redirect          off;
  proxy_buffering off;

  proxy_set_header    Host                $http_host;
  proxy_set_header    X-Real-IP           $remote_addr;
  proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
  proxy_set_header    X-Forwarded-Proto   $scheme;


  proxy_request_buffering off;
  proxy_http_version 1.1;

Is there a better or correct way how to solve that. The 418 error seems to be a bit ugly.

EDIT Is there a better/correct way to achieve that I can pass the request to one upstream first, and if the request is not handled by that upstream pass it to another one, without abusing the 418 error?

EDIT2 444 might be a better error code, but the question is still the same, is there a better way then using an error for that kind of forwarding.

  • You question (or rather its lack thereof) is unclear. If it is 'Is there a better way?', I would use location / instead of the ugly location ~. As for the 418 HTTP status code, the standard for your case would be 403, but 418 is a nice joke. :oD Mar 27, 2017 at 10:15
  • @BernardRosset Why should the standard for that case be 403? In my setup nginx will send the request to ip-check.sock. If this upstream responds with a status code that is different to 418 then it will be delivered to the client. I choose 418 because it has no meaning, but is still reserved. If 418 is returned then the request is forwared to the actual application. The 418 status code will never be send to the client, it is just used to as hack so that the request can be send to the actual upstream.
    – t.niese
    Mar 27, 2017 at 13:59
  • You are right about 403: you are not systematically forbidding access on the first lookup. For your HTTP status code 'problem', the list of assigned status codes does not say a thing about 418 or 444, which are both officially unassigned. That means there is no standard status code for the message you want to emit, you are thus free to choose any unassigned one. Some use 418 as a reference to the HTCPCP-TEA joke. Mar 27, 2017 at 15:22


You must log in to answer this question.

Browse other questions tagged .