Bugzilla – Attachment 183590 Details for
Bug 39906
Add bot challenge (in Apache layer)
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 39906: [FOR DISCUSSION] Add a worker to waste some CPU cycles if likely bot
Bug-39906-FOR-DISCUSSION-Add-a-worker-to-waste-som.patch (text/plain), 7.40 KB, created by
Paul Derscheid
on 2025-06-27 08:14:02 UTC
(
hide
)
Description:
Bug 39906: [FOR DISCUSSION] Add a worker to waste some CPU cycles if likely bot
Filename:
MIME Type:
Creator:
Paul Derscheid
Created:
2025-06-27 08:14:02 UTC
Size:
7.40 KB
patch
obsolete
>From 5ccb8faaf94de44a807e56b736c781f0c3ed44f1 Mon Sep 17 00:00:00 2001 >From: Paul Derscheid <paul.derscheid@lmscloud.de> >Date: Fri, 27 Jun 2025 10:05:47 +0200 >Subject: [PATCH] Bug 39906: [FOR DISCUSSION] Add a worker to waste some CPU > cycles if likely bot > >- The only change to the antibot config is the addition of > opac-search.pl (just noticed that the root path should be included as > well). >- Added a config object to adjust and experiment with the settings. >- Added a worker script to calculate the number of primes in a given > number of iterations set by index.js. >--- > .../templates/apache-shared-opac-antibot.conf | 2 +- > .../lib/koha_fast_challenge/index.js | 134 ++++++++++++++---- > .../lib/koha_fast_challenge/worker.js | 19 +++ > 3 files changed, 130 insertions(+), 25 deletions(-) > create mode 100644 koha-tmpl/opac-tmpl/lib/koha_fast_challenge/worker.js > >diff --git a/debian/templates/apache-shared-opac-antibot.conf b/debian/templates/apache-shared-opac-antibot.conf >index d69832b2264..0b6ca9d0bd0 100644 >--- a/debian/templates/apache-shared-opac-antibot.conf >+++ b/debian/templates/apache-shared-opac-antibot.conf >@@ -3,7 +3,7 @@ RewriteEngine on > #NOTE: To override this setting of ANTIBOT_DO, in the parent VirtualHost add the following: SetEnvIf Request_URI ^ ANTIBOT_OVERRIDE=true > #You can then provide your own conditions for setting the ANTIBOT_DO environmental variable > RewriteCond %{ENV:ANTIBOT_OVERRIDE} ^$ >-RewriteCond expr "%{REQUEST_URI} =~ m#^/cgi-bin/koha/(opac-detail.pl|opac-export.pl|opac-suggestions.pl|opac-search.pl|opac-authoritiesdetail.pl|opac-ISBDdetail.pl|opac-MARCdetail.pl|opac-shelves.pl)$#" >+RewriteCond expr "%{REQUEST_URI} =~ m#^/cgi-bin/koha/(opac-main.pl|opac-detail.pl|opac-export.pl|opac-suggestions.pl|opac-search.pl|opac-authoritiesdetail.pl|opac-ISBDdetail.pl|opac-MARCdetail.pl|opac-shelves.pl)$#" > RewriteCond %{HTTP:Cookie} !(^|;\s*)CGISESSID= [NC] > #NOTE: The KOHA_INIT is set by Javascript by the fast challenge webpage > RewriteCond %{HTTP:Cookie} !(^|;\s*)KOHA_INIT= [NC] >diff --git a/koha-tmpl/opac-tmpl/lib/koha_fast_challenge/index.js b/koha-tmpl/opac-tmpl/lib/koha_fast_challenge/index.js >index 974e57024bb..a9474cedeb6 100644 >--- a/koha-tmpl/opac-tmpl/lib/koha_fast_challenge/index.js >+++ b/koha-tmpl/opac-tmpl/lib/koha_fast_challenge/index.js >@@ -1,34 +1,120 @@ >-document.addEventListener("DOMContentLoaded", event => { >- const timeout_base = 0; >- let timeout_incr = 250; >+document.addEventListener("DOMContentLoaded", (event) => { >+ // --- Configuration --- >+ const config = { >+ baseTimeout: 250, >+ penalties: { >+ webdriver: 20, >+ spoofedWebdriver: 50, >+ noPlugins: 10, >+ noMimeTypes: 10, >+ noLanguages: 10, >+ noUserAgent: 50, >+ fastRFA: 5, >+ noInteraction: 25, >+ }, >+ workerBaseIterations: 750000, >+ interactionCheckDelay: 3000, >+ botScoreThreshold: 15, >+ }; > >- if (navigator.webdriver){ >- timeout_incr += 10000 >- } >- if (navigator.plugins.length === 0){ >- timeout_incr += 5000; >- } >- if (navigator.mimeTypes.length === 0){ >- timeout_incr += 5000; >- } >- if (!navigator.languages || navigator.languages.length === 0){ >- timeout_incr += 5000; >+ let checksHaveRun = false; >+ >+ function runAntiBotChecks() { >+ if (checksHaveRun) return; >+ checksHaveRun = true; >+ >+ let botScore = 0; >+ let userInteracted = false; >+ >+ // --- Detection Phase --- >+ if (navigator.webdriver) botScore += config.penalties.webdriver; >+ if (navigator.plugins.length === 0) botScore += config.penalties.noPlugins; >+ if (navigator.mimeTypes.length === 0) >+ botScore += config.penalties.noMimeTypes; >+ if (!navigator.languages || navigator.languages.length === 0) >+ botScore += config.penalties.noLanguages; >+ if (!navigator.userAgent) botScore += config.penalties.noUserAgent; >+ >+ try { >+ const descriptor = Object.getOwnPropertyDescriptor( >+ Navigator.prototype, >+ "webdriver" >+ ); >+ if (descriptor && !descriptor.get.toString().includes("native code")) { >+ botScore += config.penalties.spoofedWebdriver; >+ } >+ } catch (e) { >+ botScore += config.penalties.spoofedWebdriver; > } >+ > const timestamp1 = performance.now(); > requestAnimationFrame(() => { >- const delay = performance.now() - timestamp1; >- if (delay < 20){ >- timeout_incr += 1000; >- } >+ if (performance.now() - timestamp1 < 20) { >+ botScore += config.penalties.fastRFA; >+ } > }); > >- let final_timeout = timeout_base + timeout_incr; >+ const interactionEvents = ["mousemove", "keydown", "scroll"]; >+ const recordInteraction = () => { >+ userInteracted = true; >+ interactionEvents.forEach((name) => >+ document.removeEventListener(name, recordInteraction) >+ ); >+ }; >+ interactionEvents.forEach((name) => >+ document.addEventListener(name, recordInteraction, { passive: true }) >+ ); >+ >+ // --- Action Phase --- > setTimeout(() => { >- let koha_init_cookie = "KOHA_INIT=1; path=/; SameSite=Lax"; >- if (location.protocol === 'https:'){ >- koha_init_cookie += "; Secure"; >+ if (!userInteracted) { >+ botScore += config.penalties.noInteraction; >+ } >+ >+ console.log(`Final bot score: ${botScore}`); >+ >+ if (botScore >= config.botScoreThreshold) { >+ console.log("High bot score. Engaging parallel CPU trap."); >+ try { >+ const worker = new Worker("worker.js"); >+ const taskIterations = >+ config.workerBaseIterations * (1 + botScore / 20); >+ worker.postMessage({ iterations: taskIterations }); >+ } catch (e) { >+ console.error("Could not create Web Worker.", e); > } >- document.cookie = koha_init_cookie; >- location.reload(); >+ } >+ >+ const finalTimeout = config.baseTimeout + botScore * 150; >+ setCookieAndReload(finalTimeout); >+ }, config.interactionCheckDelay); >+ } >+ >+ function setCookieAndReload(final_timeout) { >+ console.log(`Final timeout: ${final_timeout}ms`); >+ setTimeout(() => { >+ let koha_init_cookie = "KOHA_INIT=1; path=/; SameSite=Lax"; >+ if (location.protocol === "https:") { >+ koha_init_cookie += "; Secure"; >+ } >+ document.cookie = koha_init_cookie; >+ location.reload(); > }, final_timeout); >+ } >+ >+ // --- Visibility API Implementation --- >+ if (document.visibilityState === "visible") { >+ runAntiBotChecks(); >+ } else { >+ document.addEventListener( >+ "visibilitychange", >+ function onVisible() { >+ if (document.visibilityState === "visible") { >+ document.removeEventListener("visibilitychange", onVisible); >+ runAntiBotChecks(); >+ } >+ }, >+ { once: true } >+ ); >+ } > }); >diff --git a/koha-tmpl/opac-tmpl/lib/koha_fast_challenge/worker.js b/koha-tmpl/opac-tmpl/lib/koha_fast_challenge/worker.js >new file mode 100644 >index 00000000000..936cb4159a6 >--- /dev/null >+++ b/koha-tmpl/opac-tmpl/lib/koha_fast_challenge/worker.js >@@ -0,0 +1,19 @@ >+self.onmessage = function (e) { >+ const iterations = e.data.iterations || 100000; >+ let primes = 0; >+ >+ function isPrime(num) { >+ for (let i = 2, s = Math.sqrt(num); i <= s; i++) { >+ if (num % i === 0) return false; >+ } >+ return num > 1; >+ } >+ >+ for (let i = 0; i < iterations; i++) { >+ if (isPrime(i)) { >+ primes++; >+ } >+ } >+ >+ self.postMessage({ done: true, primes: primes }); >+}; >-- >2.50.0
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 39906
:
182474
|
182506
|
182507
|
182906
|
183590
|
184784
|
184886
|
184887
|
184890