Home > Software design >  nginx location regular expression matching encountered problems
nginx location regular expression matching encountered problems

Time:06-11

This is the URL I need to match.

https://example.com/wp-login.php
https://example.com/wp-login.php?action=lostpassword
https://example.com/?s=
https://example.com/?s=xxxxxxx

This is the location matching rule I am using, it does not work, what is wrong please?

location ~* ^/(?:wp-login\.php|\?s\=) {
    deny all;
}

CodePudding user response:

This is the common nginx novices error. Neither location nor rewrite directives works with the whole request URI. Both of them works with the normalized request URI which does not include the query string part at all (description of what URI normalization is can be found in the location directive documentation). That means you can't check the query string using location directive at all.

Usually what you are asking for can be achieved checking the $arg_<name> nginx variable value, something like

if ($arg_s) {
    return 403;
}

Unfortunately there is no way to distinct an empty query argument value from the absence of such an argument (well, at least without using third party modules like lua-nginx-module, where that difference can be actually checked against an empty string or a nil value). Fortunately an original request URI is available to you via the $request_uri internal variable, so you can do something like

if ($request_uri ~ \?(.*&)?s=) {
    return 403;
}
location = /wp-login.php {
    deny all;
}

or even use a single $request_uri variable matching against a regex pattern like:

if ($request_uri ~ /wp-login\.php|\?(.*&)?s=) {
    return 403;
}

(this should be placed at the server configuration level)

CodePudding user response:

With your shown samples and attempts please try following regex.

(?:wp-login\.php(?:\?action=\S )?$|\?s=(?:\S )?)$

Here is the Online demo for regex.

Explanation: Adding detailed explanation for above.

(?:                   ##Starting 1st non-capturing group from here.
  wp-login\.php       ##matching wp-login.php here.
  (?:\?action=\S )?$  ##In a non-capturing group matching ?action= followed by non-spaces and keeping this as an optional match.
  |                   ##Putting OR condition either any of above OR following should match.
  \?s=                ##Matching literal ? followed by s=
  (?:\S )?            ##In a non-capturing group matching 1 or more non-spaces and keeping this match as an optional one.
)$                    ##closing very first non-capturing group here.
  • Related