25

In order to prevent referrer spam, my nginx.conf contains a section like this:

if ($http_referer ~* spamdomain1\.com) {
    return 444;
}
if ($http_referer ~* spamdomain2\.com) {
    return 444;
}
if ($http_referer ~* spamdomain3\.com) {
    return 444;
}

These rules tell nginx just to close the connection if the user has one of these referrers set. Is there a more elegant way to do this? Can I define a list of these domains and then say something like, “If the referrer is in this list then return 444”?

1
  • create one big file quite like the one from sample and use it as include file where needed. Nov 22, 2014 at 17:49

3 Answers 3

36

I would try a map:

map $http_referer $bad_referer {
    default                  0;
    "~spamdomain1.com"       1;
    "~spamdomain2.com"       1;
    "~spamdomain3.com"       1;
}

Then use it like so:

if ($bad_referer) {
    return 444;
}
7
  • 1
    Since map uses a hash tables this approach will perform better than a series of individual checks. Read the docs for options that could be used, like hostnames and possiblely include of a separate file where they are listed could make it easier to maintain.
    – Brian
    Nov 22, 2014 at 22:57
  • Reading the docs related to map I was interested to see if one could use regex to match certain referrers since OP is doing regex matching using ~* operator, and indeed simply specifying map rule like "~*spamdomain4.com" 1; will do the trick. Neat! Nov 22, 2014 at 23:01
  • You're right, and this needs to use it anyway. Nov 22, 2014 at 23:07
  • Using the hostnames option it would be simply .spamdomain4.com 1;
    – Brian
    Nov 23, 2014 at 0:04
  • 6
    @Brian The referer field is a complete URL, not simply a hostname. So that doesn't work. Nov 23, 2014 at 0:20
14

You could use logical OR to craft one multi match statement e.g.

if ($http_referer ~ "spamdomain1\.com|spamdomain2\.com|spamdomain3\.com")  { 
  return 444;
}

EDIT per comment; removing break; from the block

1
  • 2
    The break directive will never be reached as return stops the processing of the current request. Nov 22, 2014 at 19:50
3

ngx_http_referer_module is another way to do it. Example from Referer Spam Blocking:

location / {
  valid_referers none blocked *.badreferer1.com badreferer2.com *.badreferer3.com badreferer4.net;

  if ($invalid_referer) {
    return   403;
  }
}
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .