Crazy amount of guests

Thanks. I'm curious then - how do they solve a Cloudflare interactive challenge if they don't metaphorically "click" the button to say they are human? Presumably code to make it look clicked?

Anyway they are stopped again for now. The ones pretending to be multiple browsers and mobiles and faking referers can't solve cloudflare challenges, so they're being stopped by a challenge rule now. The rest that can solve cloudflare challenges are trapped in the honeypot. No doubt they will try something else.

I believe the bots running real browsers with playwright or puppeteer can click things, using javascript, which I assume is how they solve an interactive, tick box, cloudflare challenge.
There are clients that exist to mimic legitimate clients. Check out various topics with tagged repos on Github that exist for this very purpose:


Many, if not nearly all of the listed repos, are using Chromium in some form or fashion to do their dealings. Think of 'clicking' in this terminology as a phantom-click. The bots aren't actually clicking, they're deciphering the payload to solve, solves it, sends it back to CF for validation.

In the world of HTTP, it's either a GET or a POST - there isn't much else. Yes, yes, I know, OPTIONS and HEAD also exists, but that's aside this subject matter. :)
 
There are clients that exist to mimic legitimate clients. Check out various topics with tagged repos on Github that exist for this very purpose:


Many, if not nearly all of the listed repos, are using Chromium in some form or fashion to do their dealings. Think of 'clicking' in this terminology as a phantom-click. The bots aren't actually clicking, they're deciphering the payload to solve, solves it, sends it back to CF for validation.

In the world of HTTP, it's either a GET or a POST - there isn't much else. Yes, yes, I know, OPTIONS and HEAD also exists, but that's aside this subject matter. :)
Thank you for explaining that :-) Can't believe cloudflare solver solutions are actually out there publicly (those links)!
 
In case this is useful to anyone else. Just blocked ASN 211590 - Bucklog SARL (France) scanner. One of it's IP's was the highest number of requests in the past day. It was probing for .git and .github files. Presumably didn't get anything on a Xenforo site? But it has a bad reputation after googling. The IP was 185.177.72.49. ASN as above.
 
"The standout deserves its own paragraph

BUCKLOG isn't just a number on our chart — GreyNoise did the deep forensic work on it and we're standing on their shoulders here. Their researchers documented AS211590 as a purpose-built, Kubernetes-orchestrated scanning fleet operating out of a single Paris range, generating on the order of 13 million sessions across 90 days, and in one tracked week throwing more than 33,000 HTTP requests at webhook endpoints — hunting file-upload paths, document-processing endpoints, and n8n workflow-automation instances via CVE-2026-21858. That is not a hosting company that happens to have a few bad tenants. The abuse is the product. The entire ASN is the weapon."


Edit - It's been mentioned in this thread before on page 10 - apparently going direct to server IP in this case?

 
From nearly all of my findings, the most common Chinese AI Scrapers are polling Google, Bing, among other search engines, then slams those indexed URLs over and over.

More recently, I have noticed that the AI scrapers are acting more... spider-like. Hits a previously scraped or indexed URL, then ingests the other visible URLs on the page to spider out.

In both instances, it's all distributed without any sort of rate limiting.
That is what I'm seeing... they aren't clicking links, well, not the bad ones anyway.
 
It's been mentioned in this thread before on page 10 - apparently going direct to server IP in this case?
The problem though, is a lot, and I mean, a LOT, of corporations use AWS as their corporate VPN, so every employee is going out via an AWS VPN. If you block AWS you are going to block a huge legitimate set of real people.
 
The problem though, is a lot, and I mean, a LOT, of corporations use AWS as their corporate VPN, so every employee is going out via an AWS VPN. If you block AWS you are going to block a huge legitimate set of real people.
Yes I haven't blocked AWS. I just blocked Bucklog SARL
 
The problem though, is a lot, and I mean, a LOT, of corporations use AWS as their corporate VPN, so every employee is going out via an AWS VPN. If you block AWS you are going to block a huge legitimate set of real people.
No doubt there are some. However: How do you know that these are a lot companies and how much exactly is "a LOT"?

Fact is: AWS is a major source of bad bots and dangerous traffic. A good reason to block AWS altogether as Amazon does not seem to care. If corporations decide to use a filthy area of the internet with more than dubious neighbors they should not be surprised about the consequences for their internet connection.

Same principle as with mail rbis in earlier years: Blocking gets extended until either customers leave or the ignorant hosting company finally throws the baddies out.
 
A whole bunch of the internet uses AWS infrastructure.
Sure. For their server infrastructure. But not necessarily as thier company exit to the internet. What should company servers want from my (or your) forum?

I think Stripe uses AWS.
I guess when you use stripe your would whitelist their IPs. If you don't use stripe - why should they have access to your forum then?
 
My current version of browser impersonator for cloudflare expression, now factoring in a new discovery that was sailing past all rules, using residential IP's, 1 IP per page, within one week it jumped from 1200 visits to 45k daily. The last part of the rule is what targets it, I'm currently assessing whether it is also captcha solving. Initial assessment against a week of logs, says NO, but you never know.

I've shared this, up-to date, because it is probably the single most effective rule I have ever run, with an ongoing less than 1% solve on managed challenge, some of which is likely captcha solving.

Code:
(
  (
    http.user_agent contains "Chrome/1"
    and not any(lower(http.request.headers.names[*])[*] == "sec-ch-ua")
  )
  or
  (
    http.user_agent contains "Mozilla/5.0"
    and (http.user_agent contains "Chrome/1" or http.user_agent contains "Firefox/1")
    and not any(lower(http.request.headers.names[*])[*] == "sec-fetch-mode")
  )
  or
  (
    http.user_agent contains "Mozilla/5.0"
    and (http.user_agent contains "Chrome/1" or http.user_agent contains "Firefox/1")
    and not any(lower(http.request.headers.names[*])[*] == "accept-language")
  )
  or
  (
    http.user_agent contains "Mozilla/5.0"
    and http.user_agent contains "Version/"
    and http.user_agent contains "Safari/"
    and not (http.user_agent contains "Chrome/")
    and not (http.user_agent contains "Chromium/")
    and (
      not any(lower(http.request.headers.names[*])[*] == "sec-fetch-mode")
      or not any(lower(http.request.headers.names[*])[*] == "accept-language")
    )
  )
  or lower(http.user_agent) contains "elevenlabscrawler"
  or lower(http.user_agent) contains "academicbot"
)
and not (
  http.cookie contains "xf_user="
  or http.cookie contains "xf_session="
)

For those on shared hosting, where resources are slim, you probably do want to block the Tencent and related China / Hong Kong ASN's, because they're the ones using captcha solving, and I doubt its paid, and highly probable their own system.

One update, I moved the following into a block, because this is all 1 ip 1 page, same user agent, same header information, all identified as automated, and it all skirted managed challenge, so its paid solving.

Code:
(http.user_agent eq "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/156.0.0.0 Safari/537.36" and not http.cookie contains "xf_user=" and not http.cookie contains "xf_session=")
 
Last edited:
That's really helpful - especially for someone just starting out with this issue.

My guest list has stayed at between 6 and 12 visitors for a few days now :-) Mainly just real guests! Yes it's not a busy forum 😂 Some real guests get a cloudflare challenge arriving on the site but hardly any get challenged in the Uk or Europe. However I have a challenge for all desktop computers which has stopped most of the bots and the ones that solve it get caught in the honeypot. As nearly all my users are on mobiles, not many of them get challenged.

The desktop challenge is where nearly all the bots go and get caught. Now it makes no difference if they keep swapping browsers. I have another rule to catch fake mobiles. It's highly unlikely to catch a real user, but if it does they just get a challenge on arrival.

Very happy with the honeypot now though, having tweaked it a bit. I don't think the bots have anywhere else to go.
 
One update, I moved the following into a block, because this is all 1 ip 1 page, same user agent, same header information, all identified as automated, and it all skirted managed challenge, so its paid solving.

Code:
(http.user_agent eq "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/156.0.0.0 Safari/537.36" and not http.cookie contains "xf_user=" and not http.cookie contains "xf_session=")
Isn't this the latest version of Chrome on Linux? I wish I could block it but we actually do have staff who use it, so it's not an option for us. Even with the cookie excluded, people still need to be able to actually log in to bypass the block.

We're also experiencing attacks from Linux lately. I've also had to put Chrome/146 and Chrome/152 on a full-on block since they were also bypassing challenges. :(
 
If it helps, on my site this was the state of play with Linux browsers.
Linux Chrome 156 - solved challenges
Linux Chrome 146 (mainly digital ocean) - solved challenges.

Other Linux browsers couldn't solve challenges but all carried a fake referer.

So my honeypot stops Linux Chrome after they solve the challenges, if you're interested. It has an html page - the bots get there and stop. A real user, using linux and not a logged in member, just gets a button saying "click to continue". So they just go straight to whatever page they were requesting. But also real guests aren't likely to go direct to the pathways unless they've bookmarked the page - and I think they're unlikely to bookmark things like goto (but they might bookmark whats new).

This is my honeypot rule if it helps. So it blocks the solvers but not the real people (although does add a step "click to continue" for some real people).

The first line is the bit that works with the html page. In snippets there is already a prepopulated html page but you can add your own to say whatever you want. The bots get there and just stop. Nowhere else to go.

The top part contains a referer so real guests and users bypass it - because those browsers could solve challenges but didn't carry referers.
The bottom part doesn't carry a referer because less Linux users and Linux bots do sometimes carry a referer (if they had a referer they would bypass the first part of the rule).

Top line makes it work with the html and "click to continue" button name so that's what the zn is.

It's a SNIPPET rule not a custom rule btw. It only works with the snippet html

starts_with(http.request.uri.path, "/zn/")
or (
http.request.method eq "GET"
and (starts_with(http.request.uri.path, "/threads/")
or starts_with(http.request.uri.path, "/posts/")
or starts_with(http.request.uri.path, "/goto/")
or starts_with(http.request.uri.path, "/ams/")
or starts_with(http.request.uri.path, "/whats-new"))
and (http.user_agent contains "Windows NT"
or http.user_agent contains "Macintosh"
or http.user_agent contains "X11"
or (http.user_agent contains "Linux" and not http.user_agent contains "Android"))
and not cf.client.bot
and not http.cookie contains "xf_user"
and http.referer eq ""
)
or (
http.request.method eq "GET"
and (starts_with(http.request.uri.path, "/threads/")
or starts_with(http.request.uri.path, "/posts/")
or starts_with(http.request.uri.path, "/goto/")
or starts_with(http.request.uri.path, "/attachments/")
or starts_with(http.request.uri.path, "/ams/")
or starts_with(http.request.uri.path, "/whats-new"))
and http.user_agent contains "Linux"
and not http.user_agent contains "Android"
and not cf.client.bot
and not http.cookie contains "xf_user"
)

The snippet html is on a previous page on here, which can be changed to whatever - but it creates the "click to continue" button, and contains a trap for any bots who selected any buttons - but the bots have just ignored all three coded buttons and just stopped there.

The snippet rule fires after the custom rules.
 
Last edited:
Isn't this the latest version of Chrome on Linux?
It is, yes, and in my logs, over 99% of it is fake, 1 ip, 1 page scrape, no human elements, activates specific bot knowns, is 100% certainty bot. You could also add it to a block, something like this, which now ensures sec-ua is captured:

Code:
or (
  (
    (
      http.user_agent eq "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/156.0.0.0 Safari/537.36"
      and any(http.request.headers["sec-fetch-site"][*] == "none")
      and http.referer ne ""
      and not http.referer contains "myptsd.com"
    )
    or (
      http.user_agent contains "X11; Linux x86_64"
      and http.user_agent contains "Chrome/1"
      and not any(lower(http.request.headers.names[*])[*] == "sec-ch-ua")
    )
  )
  and not http.cookie contains "xf_user="
  and not http.cookie contains "xf_session="
)

Outcome

Screenshot 2026-11-02 075755.webp

This will ensure a real person using a browser is not affected. I'm personally doing some quirky things specific to my traffic, that I'm not fully sharing here, so sorry if some of it becomes disjointed.

My actual browser impersonator has some other stuff added into it, specific to the rubbish in my logs. Still not complete what I am using.

Code:
(
  (
    http.user_agent contains "Chrome/1"
    and not any(lower(http.request.headers.names[*])[*] == "sec-ch-ua")
  )
  or
  (
    http.user_agent contains "Mozilla/5.0"
    and (http.user_agent contains "Chrome/1" or http.user_agent contains "Firefox/1")
    and not any(lower(http.request.headers.names[*])[*] == "sec-fetch-mode")
  )
  or
  (
    http.user_agent contains "Mozilla/5.0"
    and (http.user_agent contains "Chrome/1" or http.user_agent contains "Firefox/1")
    and not any(lower(http.request.headers.names[*])[*] == "accept-language")
  )
  or
  (
    http.user_agent contains "Mozilla/5.0"
    and http.user_agent contains "Version/"
    and http.user_agent contains "Safari/"
    and not (http.user_agent contains "Chrome/")
    and not (http.user_agent contains "Chromium/")
    and (
      not any(lower(http.request.headers.names[*])[*] == "sec-fetch-mode")
      or not any(lower(http.request.headers.names[*])[*] == "accept-language")
    )
  )
  or (
    (
      lower(http.user_agent) contains "bot"
      or lower(http.user_agent) contains "crawl"
      or lower(http.user_agent) contains "spider"
      or lower(http.user_agent) contains "scrap"
      or lower(http.user_agent) contains "python"
      or lower(http.user_agent) contains "curl/"
      or lower(http.user_agent) contains "wget"
      or lower(http.user_agent) contains "go-http"
      or lower(http.user_agent) contains "libwww"
      or lower(http.user_agent) contains "httpclient"
      or lower(http.user_agent) contains "axios"
      or lower(http.user_agent) contains "node-fetch"
      or lower(http.user_agent) contains "headlesschrome"
    )
    and not lower(http.user_agent) contains "perplexitybot"
  )
)
and not (
  http.cookie contains "xf_user="
  or http.cookie contains "xf_session="
)
)
 
Last edited:
Basically, I look at this once a week / fortnight to check what's new in my logs, and the scrapers have really changed things up since my last peak. The biggest shift is from multiple pages per IP to now a single page per IP, basically they're throwing a 100k+ of IP's at me, all trying to grab a single page. Tracking that down to isolate and block it has been interesting.
 
Back
Top Bottom