From b22ffdacb6bcf8920e3550d43e41a54bb3d24ac0 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Tue, 13 Jan 2026 02:34:27 +0100 Subject: [PATCH] Infrastructure: evaluate Anubis -- document setup --- doc/technical/infra/Webserver/Webserver.txt | 51 + wiki/thinkPad.ichthyo.mm | 1424 ++++++++++++++++++- 2 files changed, 1445 insertions(+), 30 deletions(-) diff --git a/doc/technical/infra/Webserver/Webserver.txt b/doc/technical/infra/Webserver/Webserver.txt index da7fe237b..4c356c2dc 100644 --- a/doc/technical/infra/Webserver/Webserver.txt +++ b/doc/technical/infra/Webserver/Webserver.txt @@ -169,4 +169,55 @@ every two minutes (via SystemD timer). The resulting data trail can be found in The parameters of the Apache MPM and the WSGI daemon are then tuned such as to make good use of the available memory, while avoiding excess idle workers. +Anubis +~~~~~~ +https://anubis.techaro.lol/[Anubis] is a service that was discussed controversially +in the community this year. It was created by a +https://github.com/Xe[Canadian Open-Source programmer] as an immediate stopgap +to help protect the _»small internet«_ from the endless storm of requests that +flood in from AI companies. It is configured as a gateway proxy, which classifies +incoming requests based on request properties and sends suspicious clients first +to a JavaScript proof-of-work challenge. After passing Anubis, the client gets +a Cookie to prevent further challenges for some limited time. +Anubis was reported to be very effective for keeping aggressive scraper bots away, +yet the bots have adapted already to some degree. So this remains a game of +cat and mouse. Our first evaluations however indicate very promising numbers, +by keeping out 92% of PageImpressions and UniqueUsers, thereby reducing +the traffic deliverey by the Lumiera issue tracker by more than 80%. + +Introducing such an entrance gateway may be seen as an extreme measure; +the rationale is that we have reached such a level of threat that generic rate limits +would have to be so severe that they practically render those resources useless. +Without these protective measures, we would no longer be able to provide Lumiera.org +as a free resource to everyone. + +[underline]#Legal stance#: I consider this usage covered by the provisions of GDPR. +Setting this cookie is justified by our legitimate interest of keeping the service operational; +we evaluate IP data patterns for the sole purpose of detecting abuse of our website, +and we state that fact clearly on our GDPR page. + +Setup +^^^^^ +Anubis runs as single-instance SystemD service unit `anubis@lumiera`, with transient +storage backend only. It is integrated into the Website as a _gateway_ (reverse proxy). +Anubis is configured by a set of rules in https://cel.dev/[Common Excpression Language]. +The active rule set is configured in '/etc/anubis' and also checked into the +xref:_var_local_trac[Trac-Git]. Rules are evaluated according to the _commited-choice_ +pattern, i.e. the first rule where the guard condition matches will terminate the +evaluation and yield a decision. Anubis was installed from a custom DEB package +and ships with +https://github.com/TecharoHQ/anubis/tree/main/data[a set of rule building blocks], +that can be imported from the `(data)` prefix -- which translates into the path +'/usr/share/doc/anubis/data' + +TIP: https://anubis.techaro.lol/[Homepage] + · https://anubis.techaro.lol/docs/admin/native-install[Installation] + · https://anubis.techaro.lol/docs/admin/environments/apache[Apache-setup] + · https://github.com/TecharoHQ/anubis[Github] + +As of 1/2026, Anubis protects our +https://issues.lumiera.org/timeline[Issue tracker], +the https://git.lumiera.org/[Git repository browser] and the +https://lumiera.org/doxy/[API-doc] -- which together constitute +the majority of pages accessible on the website. diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index dc27fd750..7009a0a12 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -162564,7 +162564,7 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo - + @@ -167655,7 +167655,8 @@ that situation will improve in forseeable future. - + + @@ -167763,9 +167764,10 @@ that situation will improve in forseeable future. - + + - + @@ -167795,9 +167797,9 @@ that situation will improve in forseeable future. - - - + + + @@ -167853,8 +167855,12 @@ that situation will improve in forseeable future. + + + + - + @@ -167864,10 +167870,23 @@ that situation will improve in forseeable future. - - + + + + + +

+ tatsächlich verwenden wir WSGI +

+ +
+
- + + + + + @@ -167881,6 +167900,1038 @@ that situation will improve in forseeable future. + + + + +

+ Das erscheint mir adäquat; das event-MPM ist vor allem von Vorteil bei Web-Applikationen, die viele Socket-Verbindungen offen halten. Zwar haben wir auch einiges an keep-Alive, und das blockiert dann jeweils einen Thread. In den konkreten Last-Messwerten sehe ich jedoch nie einen Engpaß, und wir verwenden jetzt (gegenüber früher) oft nur noch ein viertel des vorhandenen Arbeitsspeichers. +

+ +
+ +
+ + + + + + + + + + + + + + + + + + +

+ ...basierend auf der %cpu, allerdings gefiltert auf die Threads, die überhaupt schon aktiv gelaufen sind (da Apache stets einen Pool an idle-Workern vorhält); angegeben als Verhältniszahl, 1.0 ≙ 100%, mißt den durchschnittlichen Anteil an der gesamten Prozeßzeit, welchen die Prozesse im "runnable"-State verbringen. Typische Werte sind 10% unter Last und <5% wenn weitgehend Idle +

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ also /etc/anubis/<service>.env +

+ +
+
+ + + + + + + + + + + + + +

+ Aggressively block AI/LLM related bots/agents by default +

+ +
+
+ + + + +

+ +

+

+   # Search engine crawlers to allow, defaults to: +

+

+   #   - Google (so they don't try to bypass Anubis) +

+

+   #   - Apple +

+

+   #   - Bing +

+

+   #   - DuckDuckGo +

+

+   #   - Qwant +

+

+   #   - The Internet Archive +

+

+   #   - Kagi +

+

+   #   - Marginalia +

+

+   #   - Mojeek +

+ +
+ + + + + + +

+ Allow common "keeping the internet working" routes (well-known, favicon, robots.txt) +

+ +
+ + +
+ + + + + + + + + + + + + + + + + + + + +

+ Das ist ein Überbleibsel aus der Anfangszeit; Xena meinte erst, das das was bringt; Reviewer haben sie dann darauf aufmerksam gemacht, daß das IP-Daten leaken kann. Seither ist es deaktiviert +

+ +
+
+ + + + +

+ Das erlaubt gewisse "OG"-Urls ohne Challenge durch +

+ +
+
+ + + + +

+ # By default, send HTTP 200 back to clients that either get issued a challenge +

+

+ # or a denial. This seems weird, but this is load-bearing due to the fact that +

+

+ # the most aggressive scraper bots seem to really, really, want an HTTP 200 and +

+

+ # will stop sending requests once they get it. +

+ +
+ + + + + + + + +

+ # Anubis can store temporary data in one of a few backends. See the storage +

+

+ # backends section of the docs for more information: +

+

+ # +

+

+ # https://anubis.techaro.lol/docs/admin/policies#storage-backends +

+ +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ - import: (data)/crawlers/alibaba-cloud.yaml +

+

+ - import: (data)/crawlers/huawei-cloud.yaml +

+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ das heißt, alles was mit User-Agent "Mozilla|Opera" daherkommt, aber keine andere Regel matcht, bekommt einen Gewichts-Malus von +10 +

+ +
+ +
+
+ + + + + + + + +

+ derzeit eine Regel: überhaupt kein UserAgent ⟶ DENY +

+ +
+
+
+ + + + + + + +

+ +

+

+   # Search engine crawlers to allow, defaults to: +

+

+   #   - Google (so they don't try to bypass Anubis) +

+

+   #   - Apple +

+

+   #   - Bing +

+

+   #   - DuckDuckGo +

+

+   #   - Qwant +

+

+   #   - The Internet Archive +

+

+   #   - Kagi +

+

+   #   - Marginalia +

+

+   #   - Mojeek +

+ +
+
+
+ + + + + +
+

+ meta policies +

+ + +
+

+ Contains policies that exclusively reference policies in multiple  other data folders. +

+

+ Akin to "stances" that the administrator can take, with reference to various topics, such as AI/LLM systems. +

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +

+ S   RSS     VSZ %MEM  %CUC  CMD +

+

+ S 29948 1265196  0.7  1.506 /usr/bin/anubis +

+ +
+ + + +

+ ps -A  -o s,rss,vsz,%mem,cuc,cmd +

+ +
+
+
+
+ + + + + + + + + + + + + +

+ siehe Notiz in hauZu.mm +

+ +
+
+ + + + + +

+ # /usr/lib/systemd/system/anubis@.service +

+

+ [Unit] +

+

+ Description="Anubis HTTP defense proxy (instance %i)" +

+

+ +

+

+ [Service] +

+

+ ExecStart=/usr/bin/anubis +

+

+ Restart=always +

+

+ RestartSec=30s +

+

+ EnvironmentFile=/etc/anubis/%i.env +

+

+ LimitNOFILE=infinity +

+

+ DynamicUser=yes +

+

+ CacheDirectory=anubis/%i +

+

+ CacheDirectoryMode=0755 +

+

+ StateDirectory=anubis/%i +

+

+ StateDirectoryMode=0755 +

+

+ RuntimeDirectory=anubis/%i +

+

+ RuntimeDirectoryMode=0755 +

+

+ ReadWritePaths=/run +

+

+ +

+

+ [Install] +

+

+ WantedBy=multi-user.target +

+ +
+ + + + + +

+ d.h. der Service erstellt einen transienten Unix User-Account, so lange er läuft, und entfernt diesen automatisch wenn er stoppt; das aktiviert automatisch zusätzliche Sandboxing-Optionen: der Service darf fast nirgends schreiben, er bekommt ein privates /temp-Dir (das nacher wieder verschwindet), und IPC-Files / Pipes werden automatisch wieder gelöscht. Insofern verbleiben keine Resourcen im System, die diesem pseudo-user gehören, nachdem der Service stoppt +

+ +
+ +
+
+ + + + + + + +

+ Wir brauchen das, weil wir ein normales Logfile am gewohnten Ort haben wollen. +

+

+ SystemD betreibt Service-Units aber normalerweise unter Sandboxing; und automatisch (wie hier), wenn wir einen "automatic user" verwenden +

+

+ Hinweis: dieser Override aggregiert sich mit dem Default, der ReadWritePath=/run +

+ +
+
+
+
+ + + + + + + + +

+ DEB.control definiert keinerlei dependencies +

+ +
+ + + +

+ Entweder das ist tatsächlich ein AppImage, oder »man« nimmt es mit den Pakten nicht so sonderlich genau (oder verwendet irgend eine Wrapper-Software) +

+ +
+ +
+
+
+ + + + + + + +
    +
  • + erkenntlich an dem '@' im Servicenamen: anubis@.service +
  • +
  • + als Solcher gibt es den nicht, aber man startet dann z.B. anubis@lumiera +
  • +
+ +
+ +
+ + + + +

+ Instanzname: lumiera +

+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ logging: +

+

+   sink: file +

+

+   parameters: +

+

+     file: "/var/log/apache2/anubis.log" +

+

+     maxBackups: 0                # disable log-rotation by Golang: fahedouch/go-logrotate +

+

+     maxBytes:  -1                # unlimited size +

+

+     maxAge:     0                # no clean-up (leave this to Linux logrotate) +

+ +
+
+ + + + + + + + + + + + + + +

+ # Anubis JSON log 1/2026 +

+

+ /var/log/apache2/anubis.log { +

+

+ daily +

+

+ rotate 28 +

+

+ extension log +

+

+ dateext +

+

+ dateyesterday +

+

+ dateformat %Y-%m-%d. +

+

+ compress +

+

+ delaycompress +

+

+ missingok +

+

+ notifempty +

+

+ ignoreduplicates +

+

+ create 640 anubis staff +

+

+ postrotate +

+

+     if pgrep -f ^/usr/bin/anubis > /dev/null; then +

+

+         /usr/bin/systemctl stop  anubis@lumiera 2>&1 | logger -t anubis.logrotate +

+

+         /usr/bin/systemctl start anubis@lumiera 2>&1 | logger -t anubis.logrotate +

+

+     fi +

+

+ endscript +

+

+ } +

+ +
+ +
+
+
+ + + + + + +

+ Noch vor wenigen Monaten war sie skeptisch, aber dann hat sie wohl den Research von Antropic gesehen, dem zufolge bereits eine kleine Anzahl an vergifteten Trainingsdaten genügt, ein Modell zu korrumpieren, egal wie groß das Modell und die Trainingsdaten insgesamt sind +

+ +
+
+ + + + + + + + + + + + + + +

+ Direkt nach dem Restart... +

+

+ WARN: REDIRECT_DOMAINS is not set, Anubis will only redirect to the same domain a request is coming from, see https://anubis.techaro.lol/docs/admin/configuration/redirect-domains +

+ +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + +

+     # Retrieve origin IP of the request for logging +

+

+     RemoteIPHeader X-Real-Ip +

+

+     RemoteIPInternalProxy 127.0.0.1 +

+ +
+ + + + + +
+ + + + +

+ damit Apache beim Rückübersetzen den Namen verwendet, der als ServerName im eingehenden VirtualHost steht +

+ +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ sed -nre '\_\[12/Jan/2026:03:_, \_\[12/Jan/2026:14:_ p' \ +

+

+    trac-access.2026-01-12.log >trac.12.log +

+ +
+ +
+ + + + + + + + + +

+ jq --arg start "2026-01-12T15:00" --arg end "2026-01-12T17:00" \ +

+

+ -s 'map(select(.time[0:16] >= $start and .time[0:16]<= $end))' \ anubis.2026-01-12.log|less +

+ +
+ + +
+ + + + +

+ liest eine Folge von JSON-Werten und packt sie in ein Array, das dann in die Pipeline geschickt wird +

+ +
+
+ + + + +
+ + + + + + +

+ jq -r \ +

+

+ 'map([.time[0:19] \ +

+

+      , ."x-real-ip" \ +

+

+      , if .check_result == null \ +

+

+          then ["CHALLENGE","default"] \ +

+

+          else [.check_result.rule, .check_result.name] \ +

+

+        end \ +

+

+      , .path \ +

+

+      ]|flatten|@csv) \ +

+

+  |.[]' \ +

+

+ anub.12.json > anub.12.csv +

+ +
+ + + +

+ jq -r 'map([.time[0:19] , ."x-real-ip" , if .check_result == null then ["CHALLENGE","default"] else [.check_result.rule, .check_result.name] end , .path ]|flatten|@csv) |.[]' anub.12.json > anub.12.csv +

+ +
+ + + + + + + + +

+ bei mir ist ein Element ein nested Array ⟹ flatten vor dem CSV-Filter +

+ +
+
+ + + + + +
@@ -167892,7 +168943,7 @@ that situation will improve in forseeable future. - + @@ -179873,7 +180924,7 @@ runner.run(test_suite())
- + @@ -179892,7 +180943,8 @@ runner.run(test_suite())
- + + @@ -179904,8 +180956,9 @@ runner.run(test_suite())
- - + + + @@ -179916,7 +180969,7 @@ runner.run(test_suite())
- + @@ -179936,7 +180989,10 @@ runner.run(test_suite())
- + + + + @@ -180021,8 +181077,8 @@ runner.run(test_suite())
- - + + @@ -180094,9 +181150,11 @@ runner.run(test_suite()) - - - + + + + + @@ -180233,17 +181291,83 @@ runner.run(test_suite()) + + + + + + +

+ von vorher 1.5 - 2 GiB auf nun 400 - 800 MiB +

+ +
+ + + + +
    +
  • + Ich messe die %CPU, aber nur in den Threads, die überhaupt etwas gearbeitet haben. Dieser Wert liegt selten über 10% +
  • +
  • + Bisher habe ich den Apache für maximal 4 Prozesse à 20 Threads konfiguriert; er läuft die meiste Zeit nur mit 2 Prozessen und mehr als 10 Idle workers +
  • +
+ +
+ + + + +

+ Es wollte sich halt Niemand(TM)  mit dem lästigen Thema beschäftigen, solange bis die Hütte brennt... +

+ +
+
-
- - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ Also »Open Core« +

+ +
+
+
+ + + @@ -180266,10 +181390,250 @@ runner.run(test_suite()) + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + +

+ Ergebnis: drastische Reduktion aller Lasten +

+ +
+ + + + +

+ Vergleichsmessung mit Anubis/Trac +

+

+ Vergleichszeitraum:  9.1.26 13:00-24:00 +

+

+ Meßzeitraum-Anubis: 12.1.26 03:00-14:00 +

+

+ (jeweils 11 Stunden) +

+

+ +

+

+ Heute (Anubis-Messung) war weniger Last auf dem System: +

+
    +
  • +  nur 34% der UniqueVisitors in Lumiera +
  • +
  • +  nur 68% des Traffic in Lumiera +
  • +
+

+ +

+

+ Deshalb setze ich die Zahlen jeweils ins Verhältnis +

+

+ zu der Meßgröße in www.lumiera.org (ohne Anubis). +

+

+ +

+ + + + + + + + + + + + + + + + + + + + + +
+ Größe + + Vergleich + + mit Anubis +
+ Volumen + + 61% + + 0.6% +
+ PageImpressions + + 117% + + 4% +
+ UniqueVisitors + + 26% + + 1.6% +
+

+ +

+

+ UniqueVisitors am Gateway: 17% +

+

+ +

+

+ Weitere Beobachtungen heute +

+

+ +

+

+ Am Gateway werden gefiltert (jeweils ohne mich selber) +

+

+  - 92% der PageImpressions +

+

+  - 92% der UniqueVisitors +

+

+  - 87% des Datenvolumens +

+

+ +

+

+ Anubis hat 2094 Transaktionen registriert +

+
    +
  • + 1473 DENY +
  • +
  • +  621 CHALLENGE +
  • +
  • +  571 davon sind am Challenge gescheitert +
  • +
+

+ +

+

+ Häufigkeit der Regeln: +

+

+   1099 "bot/alibaba-cloud" +

+

+    614 "default" +

+

+    291 "bot/ai-catchall" +

+

+     80 "bot/no-user-agent-string" +

+

+      7 "threshold/mild-suspicion" +

+

+      3 "bot/huawei-cloud" +

+

+ +

+

+ +

+

+ Anmerkung zum Datenvolumen vor dem Gateway: +

+

+ Viele Bots versuchen es immer wieder. Einer hat es 80 mal versucht. +

+

+ Im Schnitt versuchen die Bots 10 mal, reinzukommen. +

+ +
+ +
+ + + + +

+ Das ist abhängig von der Feinabstimmung der Regeln, und wird nur solange gelten, bis die aggresiveren Bots auch die erweiterten Browser-Eigenschaften zuverlässig nachahmen +

+ +
+ +
+ + +
+
+ +