Trying to undestand WAF

I’m trying to use the WAF and it’s not working as expected. Here are the rules:

IP Source - is not in list - my_list
Country - is not in - Canada, United States
URI Path - contains - /admin
URI Path - contains - /provider

When i visit from an IP in the list and from inside the United States, i’m blocked. When i check the ray-id log it shows the request was from my IP and from USA. Am i interpreting one of these rules backwards?

It looks like the issue might be “Block by country is only available on Enterprise plans.”. We are on paid (entry level) plan. I don’t think that’s the problem because i deleted the county rule and still had the problem.

If the red line was suppose to be my hint, maybe make it bigger than this tiny red line that has no hover text and clicking just opens a box that gives options to add contact info.
pic of original rule to show the red line:

AND is taking higher precedence than OR, so your rule as specified in your screenshot is blocking all access to /admin.

1 Like

Is there a way to add multiple URI paths in a single statement so i don’t have to use OR? For example:
contains - /provider, /admin
I tried the above but it just allows everyone.

i’m trying to block /provider* and /admin* from anybody not (in the ip list and in the US)

Click “edit expression” and use parenthesis to change the order of operations. Something like:

(not ip.src in {} and not in {"US" "CA"} and (http.request.uri.path contains "/foo" or http.request.uri.path contains "/bar"))

(Not tested but the dashboard accepted it as valid.)


Makes sense to me and seems like it should have worked but it didn’t work. Used like example. Blocked all request.

I’ve tested the rule as suggested by @i40west and it worked. Make sure you to double check the parenthesis and to purge Cloudflare cache for the relevant paths.

Also, since you’re on a paid plan, you can benefit from the function starts_with(), which makes the rule more precise than contains.

… and starts_with(http.request.uri.path, "/foo") or …

This limitation only applies to IP Access Rules, not to WAF Custom Rules.


nice…i think cache might have been the problem.


I’m not sure why the rule is no longer working. all traffic is getting through even though it is enabled. Here is the updated rule for reference. I’ve opened a ticket with cloudflare.

(not ip.src in $admins and not in {“US” “CA”} and (starts_with(http.request.uri.path, “/provider”) or starts_with(http.request.uri.path, “/admin”)))

Tested again, it should work as is.

  1. Check your other rules for any with action set to Skip or Allow.
  2. Check any IP Access Rules that might have Allow.
  3. Check your list to see if it properly reflects what you intend to not block.
1 Like

I checked 1 (only have 1 other rule…blocking a specific IP), 2 (there are none) and 3 (the 2 IP addresses I tested from are not in that list). I sent support my HAR file with proof. They responded they saw the 403 in the file and asked me to reconfirm. I replied reminding them to notice the 403 didn’t come from their server. The contents of the HAR reveal the text on the 403 page is not from the cloudflare block page. It’s from my server. I have a .htaccess file in the app directory blocking traffic as best it can until cloudflare block is working properly. I sent them another follow up test from a different IP since they asked me to send the IP i ran the last test from but by the time i got that message, i wasn’t at that location anymore.

The other rule in WAF is this: (ip.src eq <a_ip_address>)

You can install the Opera browser in a sandbox and use its built-in VPN to test different IPs.

1 Like

I’m going to test the opera browser built in vpn option when i get on regular network. I’m using cell phone network right now so download speed is limited.

1 Like

Cloudflare support isn’t sure why it’s not working either. They suggested the following change (first “and” to “or”) that proved fatal (blocked ALL traffic to the website beyond specified uri.paths):

(not ip.src in $admins or not in {“US” “CA”} and (starts_with(http.request.uri.path, “/provider”) or starts_with(http.request.uri.path, “/admin”)))

I was worried that change wouldn’t work because it’s the opposite of what seems intuitive. I “think” my problem might be a redundant rule that doesn’t work as expected. My goal was “block /provider* and /admin* from anybody not (in the ip list AND in the US)”

That last “AND” above looks to be the problem. My concern was if an attacker could be in Russia for example, spoof a specific IP that’s in the allow list. The “AND” would make sure that even though the request is coming from an approved USA IP, if cloudflare can detect it’s true origin is not USA or Canada, it would block it.

For an attacker to pull off that stunt would take above average skills considering most would just use a VPN and rely on the true origin IP not leaking. But I think what I’m asking is beyond what the WAF is capable of. I’m not sure, I’m still waiting to hear back from support since the last error.

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.