2

I want Cloudflare WAF to restrict admin section of WordPress site/wp-admin/ and allow access to WP admin section from only two countries India & UAE.

For some reason it block traffic from all countries not only to admin section but also to main website such as www.example.com.

To me below setting should only block admin pages from all countries other than India & UAE and main site should not have any restriction.

Not sure if I am doing anything wrong here as its not working as intended.

enter image description here

Second image : enter image description here

Third Image: enter image description here Fourth Image enter image description here Fifth image enter image description here

3
  • The example URI shows it starting with a slash. Have you tried matching that? Commented Sep 30, 2022 at 9:09
  • The expression preview has parenthesis that indicate the wrong order of operations. No idea how you fix that, but you clearly need to get the parenthesis fixed. Commented Sep 30, 2022 at 9:11
  • I have tried multiple combination such as /wp-admin/ or full url even change the field type to Full URI but nothing seem to work.. updated my question as i had shared wrong screenshot
    – Learning
    Commented Sep 30, 2022 at 10:16

3 Answers 3

4
+100

This is the easy way, supported in all cases. Limit Hostname with equals example.com, URI Path with contains /wp-admin or /wp-admin/ (this is shown in the screenshot below), and Country with is not in { "IN", "AE" }.

A screenshot of Cloudflare's Dashboard showing the implementation of the solution, explained in the text surrounding this image.

If you have access to it (depending on plan type), using a matches regex could make the URI Path filter easier and more focused as it becomes ^/wp-admin, meaning it blocks all those that start with that path.

The full expression, which you can enter when you click "Edit expression" then becomes:

(http.host eq "example.com" and http.request.uri.path contains "/wp-admin/" and not ip.geoip.country in {"IN" "AE"})

The error you are encountering is because you are using OR after the AND group, meaning it's blocking all request to all hostnames and all paths not coming from the UAE or all the requests not coming from India limited to the specific filter you added to the URI in each screenshot.

This you can clearly see in the expression preview below each example.

In your case, if you really wanted to keep the OR in there (isn't required, as shown above, but to show all possible cases), you'd need to filter the URI in each section of Country filtering, before and after the OR.


More info on this can be found in:

3
  • Finally its working as intended with the setting as mentioned by you.. It should also work with. Logically it should also work with (http.request.full_uri contains "/wp-admin/" and not ip.geoip.country in {"IN" "AE"}) or full URI Full take full URL into consideration.. or should it be like this (http.request.full_uri contains example.com/wp-admin" and not ip.geoip.country in {"IN" "AE"})`
    – Learning
    Commented Oct 3, 2022 at 12:50
  • For some reason same setting are not working for other domain with only difference is the domain name and path /_admin/ as this is non WP website and admin section is contains /_admin/
    – Learning
    Commented Oct 3, 2022 at 13:15
  • In order, it would work yes, but it would be to all hostnames, mine was scoped to a single hostname per the original question. Try and avoid the _ in the contains. Maybe some issue with character escaping. You could also try and do a /\_admin/. Commented Oct 3, 2022 at 17:02
1

I see that you can "Edit expression." I'm not sure how to get their graphical expression builder to give you what you want, but it looks like can edit the code directly.

CloudFlare has documentation:

From that, I would recommend using the field http.request.uri.path which has little more than the part of the URI than you want to match. I also see several places when the in operator can take several space separated values.

You should be able to edit the expression to:

(http.request.uri.path contains "wp-admin" and not ip.geoip.country in {"IN" "AE"})

3
  • it doesnt allow me to add starts_with as it give some sort of error but below is changed to (http.request.uri.path contains "/wp-admin" and not ip.geoip.country in {"IN"}) or (not ip.geoip.country in {"AE"}) and still it blocks all links including home page?
    – Learning
    Commented Oct 3, 2022 at 12:22
  • Because the parenthesis are still not balanced. I updated it to remove the starts_with suggestion since you say that doesn't work Commented Oct 3, 2022 at 12:48
  • for my second problem your solution works i am not sure if CF caches WAF entries or what logically solution suggested by other also works but for WP and not for other website.. So i am not sure what is actually. Yes i agree with you Parenthesis is important
    – Learning
    Commented Oct 3, 2022 at 16:07
1

The problem with your setup, is that you can't combine AND and OR in the same expression, UNLESS you do it in advanced mode (Edit).

The solution is simple:

  1. Click on Edit Expression

  2. Copy and paste the following code:

    (http.request.uri.path contains "wp-login.php") and not ip.geoip.country in {"IN","AE"}

Want to go beyond? Cloudflare can help you mitigate your attack surface even further. For example, you can allow only users using a specific browser, or those coming from certain IP ranges.

If your team only uses Firefox to access the site, add the following:

and (http.user_agent contains "Firefox")

If you want to also block other common destinations prone to attacks:

((http.request.uri.path contains "wp-login.php") or (http.request.uri contains "xmlrpc.php") or (http.request.uri contains "admin-ajax.php") or (http.request.uri contains "wp-admin")) 

Only allow the IP if it comes from a particular ASIN :

and not ((ip.geoip.asnum eq 14618) or (ip.geoip.asnum eq 8075))

The full expression would look like this:

((http.request.uri.path contains "wp-login.php") or (http.request.uri contains "xmlrpc.php") or (http.request.uri contains "admin-ajax.php") or (http.request.uri contains "wp-admin")) and not ((ip.geoip.asnum eq 14618 or ip.geoip.asnum eq 8075) and (http.user_agent contains "Firefox"))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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