nginxnginx-location

Block URLs with query strings in Nginx


I'm trying to use Nginx Location to block requests similar to this, which are causing load issues with WordPress (and the multilingual WPML plugin):

GET /foo/bar/?s=/?s=/?s=/?s=/?s=/?s=/?s=/?s=/?s=/?s=/ HTTP/1.1

However simplifying it to the following doesn't match:

location ~* \?s= {
  return 404;
}

even though I've:

(I can confirm that location foobar will correctly match "foobar" anywhere in the URL.)


Solution

  • The PCRE regex is correct. A test against Perl (the source of the Perl Compatible Regular Expressions) which are used by nginx according to the sources:

     perl -e 'print "yes\n" if "/foo/bar/?s=/?s=/?s=/?s=/?s=/?s=/?s=/?s=/?s=/?s=/" =~ m|\?s=/|'
      yes
    

    The reason why it does not match is, that the location { } match only matches against the URL, not the URI (which includes the params).

    So anything that follows after the ? will be ignored in the location match block.

    The way to fix this is by useing the complete uri to match, not just the URL:

        if ( $request_uri ~ s=/ ) {
                return 404;
        }
    

    Or if you want to include /foo/bar:

    location /foo/bar { 
        if ( $request_uri ~ s=/ ) {
                return 404;
        }
    }