Releases: TecharoHQ/anubis
v1.21.0: Minfilia Warde
Please, be at ease. You are among friends here.
In this release, Anubis becomes internationalized, gains the ability to use system load as input to issuing challenges, finally fixes the "invalid response" after "success" bug, and more! Please read these notes before upgrading as the changes are big enough that administrators should take action to ensure that the upgrade goes smoothly.
Big ticket changes
The biggest change is that the "invalid response" after "success" bug is now finally fixed for good by totally rewriting how Anubis' challenge issuance flow works. Instead of generating challenge strings from request metadata (under the assumption that the values being compared against are stable), Anubis now generates random data for each challenge. This data is stored in the active storage backend for up to 30 minutes. This also fixes #746 and other similar instances of this issue.
In order to reduce confusion, the "Success" interstitial that shows up when you pass a proof of work challenge has been removed.
Storage
Anubis now is able to store things persistently in memory, on the disk, or in Valkey (this includes other compatible software). By default Anubis uses the in-memory backend. If you have an environment with mutable storage (even if it is temporary), be sure to configure the bbolt
storage backend.
Localization
Anubis now supports localized responses. Locales can be added in lib/localization/locales/. This release includes support for the following languages:
- Brazilian Portugese
- Chinese (Simplified)
- Chinese (Traditional)
- English
- Estonian
- Filipino
- French
- German
- Icelandic
- Italian
- Japanese
- Spanish
- Turkish
If facts or local regulations demand, you can set Anubis default language with the FORCED_LANGUAGE
environment variable or the --forced-language
command line argument:
FORCED_LANGUAGE=de
Load average
Anubis can dynamically take action based on the system load average, allowing you to write rules like this:
## System load based checks.
# If the system is under high load for the last minute, add weight.
- name: high-load-average
action: WEIGH
expression: load_1m >= 10.0 # make sure to end the load comparison in a .0
weight:
adjust: 20
# If it is not for the last 15 minutes, remove weight.
- name: low-load-average
action: WEIGH
expression: load_15m <= 4.0 # make sure to end the load comparison in a .0
weight:
adjust: -10
Something to keep in mind about system load average is that it is not aware of the number of cores the system has. If you have a 16 core system that has 16 processes running but none of them is hogging the CPU, then you will get a load average below 16. If you are in doubt, make your "high load" metric at least two times the number of CPU cores and your "low load" metric at least half of the number of CPU cores. For example:
Kind | Core count | Load threshold |
---|---|---|
high load | 4 | 8.0 |
low load | 4 | 2.0 |
high load | 16 | 32.0 |
low load | 16 | 8 |
Also keep in mind that this does not account for other kinds of latency like I/O latency. A system can have its web applications unresponsive due to high latency from a MySQL server but still have that web application server report a load near or at zero.
Other features and fixes
There are a bunch of other assorted features and fixes too:
- Add
COOKIE_SECURE
option to set the cookie Secure flag - Sets cookie defaults to use SameSite: None
- Determine the
BIND_NETWORK
/--bind-network
value from the bind address (#677). - Implement a development container manifest to make contributions easier.
- Fix dynamic cookie domains functionality (#731)
- Add option for custom cookie prefix (#732)
- Make the Open Graph subsystem and DNSBL subsystem use storage backends instead of storing everything in memory by default.
- Allow Common Crawl by default so scrapers have less incentive to scrape
- The bbolt storage backend now runs its cleanup every hour instead of every five minutes.
- Don't block Anubis starting up if Thoth health checks fail.
- A race condition involving opening two challenge pages at once in different tabs causing one of them to fail has been fixed.
- The "Try again" button on the error page has been fixed. Previously it meant "try the solution again" instead of "try the challenge again".
- In certain cases, a user could be stuck with a test cookie that is invalid, locking them out of the service for up to half an hour. This has been fixed with better validation of this case and clearing the cookie.
- Start exposing JA4H fingerprints for later use in CEL expressions.
- Add
/healthz
route for use in platform-based health checks.
Potentially breaking changes
We try to introduce breaking changes as much as possible, but these are the changes that may be relevant for you as an administrator:
Challenge format change
Previously Anubis did no accounting for challenges that it issued. This means that if Anubis restarted during a client, the client would be able to proceed once Anubis came back online.
During the upgrade to v1.21.0 and when v1.21.0 (or later) restarts with the in-memory storage backend, you may see a higher rate of failed challenges than normal. If this persists beyond a few minutes, open an issue.
If you are using the in-memory storage backend, please consider using a different storage backend.
Systemd service changes
The following potentially breaking change applies to native installs with systemd only:
Each instance of systemd service template now has a unique RuntimeDirectory
, as opposed to each instance of the service sharing a RuntimeDirectory
. This change was made to avoid the RuntimeDirectory
getting nuked any time one of the Anubis instances restarts.
If you configured Anubis' unix sockets to listen on /run/anubis/foo.sock
for instance anubis@foo
, you will need to configure Anubis to listen on /run/anubis/foo/foo.sock
and additionally configure your HTTP load balancer as appropriate.
If you need the legacy behaviour, install this systemd unit dropin:
# /etc/systemd/system/[email protected]/50-runtimedir.conf
[Service]
RuntimeDirectory=anubis
Just keep in mind that this will cause problems when Anubis restarts.
What's Changed
- feat: implement localization system by @lolgzs in #716
- fix: determine bind network from bind address by @littlecxm in #714
- Add Brazilian Portuguese translation by @rffontenelle in #726
- fix: Dynamic cookie domain not working by @Earl0fPudding in #731
- feat(cmd): Add custom cookie prefix by @Earl0fPudding in #732
- build(deps): bump the github-actions group with 2 updates by @dependabot[bot] in #735
- build(deps): bump the gomod group with 2 updates by @dependabot[bot] in #736
- feat: dev container support by @Xe in #734
- Fix translations in pt-BR.json by @rffontenelle in #729
- Set cookies to have the Secure flag default to true by @victorvalenca in #739
- fix(web/main): remove the success interstitial by @Xe in #745
- feat(localization): Add option for forcing a language by @Earl0fPudding in #742
- fix(run/[email protected]): unique runtimedir per instance by @Xe in #750
- feat(localization): Add German language translation by @Earl0fPudding in #741
- docs: add BotStopper docs from the git repo by @Xe in #752
- chore(default-co...
v1.21.0-pre3: Minfilia Warde
A small fix to amend broken RPM signatures.
v1.21.0-pre2: Minfila Warde
Please report any issues with this prerelease so the full release can be the best it can possibly be.
What's Changed
- build(deps): bump the github-actions group with 2 updates by @dependabot[bot] in #770
- build(deps): bump github.com/shirou/gopsutil/v4 from 4.25.1 to 4.25.6 in the gomod group by @dependabot[bot] in #771
- minor typo fix: Update apache.mdx replace nginx with Apache in place by @mihugo in #779
- docs(known-instances): update list of known instances by @lotharsm in #776
- feat(localization): add Simplified Chinese by @littlecxm in #774
- docs(installation): Clarify information about private keys and multile instances by @StandingPadAnimations in #788
- fix(localization): HTML language header and forced-language by @SlyEcho in #787
- Update apache.mdx by @jzb in #784
- feat(localization): add Japanese language translation by @dai in #772
- feat(i18n): add Estonian locale by @SlyEcho in #783
- Create is.json by @sveinki in #780
- feat(localization): Add Italian language translation by @giomba in #778
- feat(localization): Add Filipino language by @searinminecraft in #775
- fix(internal/thoth): don't block Anubis starting if healthcheck fails by @Xe in #794
- feat(blog): incident report for TI-20250709-0001 by @Xe in #795
- chore: use nginx-micro to make the docs image 13 MB by @Xe in #796
- docs: update CHANGELOG for language changes by @Xe in #793
- docs(known-instances): update list of known instances by @lotharsm in #801
- correct gitea.botPolicies extension to be yaml, not json by @evgeni in #800
- docs(known-instances): add rpmfusion.org and wiki.freepascal.org to known instances by @lotharsm in #807
- chore(docs): fix typo in configuration/expressions by @maximelouet in #811
- fix(index.templ) centered-div class usage typo by @ciencia in #812
- chore(docs): add link to status page in the footer by @Xe in #814
- chore: release v1.21.0-pre2 by @Xe in #816
New Contributors
- @mihugo made their first contribution in #779
- @StandingPadAnimations made their first contribution in #788
- @jzb made their first contribution in #784
- @dai made their first contribution in #772
- @sveinki made their first contribution in #780
- @giomba made their first contribution in #778
- @searinminecraft made their first contribution in #775
- @evgeni made their first contribution in #800
- @maximelouet made their first contribution in #811
- @ciencia made their first contribution in #812
Full Changelog: v1.21.0-pre1...v1.21.0-pre2
v1.21.0-pre1: Minfilia Warde
Minfilia Warde
Please, be at ease. You are among friends here.
In this release, Anubis becomes internationalized, gains the ability to use system load as input to issuing challenges,
This release is brought to you by FreeCAD, an open-source computer aided design tool that lets you design things for the real world.
Big ticket changes
The biggest change is that the "invalid response" after "success" bug is now finally fixed for good by totally rewriting how Anubis' challenge issuance flow works. Instead of generating challenge strings from request metadata (under the assumption that the values being compared against are stable), Anubis now generates random data for each challenge. This data is stored in the active storage backend for up to 30 minutes. This also fixes #746 and other similar instances of this issue.
In order to reduce confusion, the "Success" interstitial that shows up when you pass a proof of work challenge has been removed.
Storage
Anubis now is able to store things persistently in memory, on the disk, or in Valkey (this includes other compatible software). By default Anubis uses the in-memory backend. If you have an environment with mutable storage (even if it is temporary), be sure to configure the bbolt
storage backend.
Localization
Anubis now supports localized responses. Locales can be added in lib/localization/locales/. This release includes support for the following languages:
If facts or local regulations demand, you can set Anubis default language with the FORCE_LANGUAGE
environment variable:
FORCE_LANGUAGE=de
Load-based checks
Anubis can dynamically take action based on the system load average, allowing you to write rules like this:
## System load based checks.
# If the system is under high load for the last minute, add weight.
- name: high-load-average
action: WEIGH
expression: load_1m >= 10.0 # make sure to end the load comparison in a .0
weight:
adjust: 20
# If it is not for the last 15 minutes, remove weight.
- name: low-load-average
action: WEIGH
expression: load_15m <= 4.0 # make sure to end the load comparison in a .0
weight:
adjust: -10
Something to keep in mind about system load average is that it is not aware of the number of cores the system has. If you have a 16 core system that has 16 processes running but none of them is hogging the CPU, then you will get a load average below 16. If you are in doubt, make your "high load" metric at least two times the number of CPU cores and your "low load" metric at least half of the number of CPU cores. For example:
Kind | Core count | Load threshold |
---|---|---|
high load | 4 | 8.0 |
low load | 4 | 2.0 |
high load | 16 | 32.0 |
low load | 16 | 8 |
Also keep in mind that this does not account for other kinds of latency like I/O latency. A system can have its web applications unresponsive due to high latency from a MySQL server but still have that web application server report a load near or at zero.
Other features and fixes
There are a bunch of other assorted features and fixes too:
- Add
COOKIE_SECURE
option to set the cookie Secure flag - Sets cookie defaults to use SameSite: None
- Determine the
BIND_NETWORK
/--bind-network
value from the bind address (#677). - Implement a development container manifest to make contributions easier.
- Fix dynamic cookie domains functionality (#731)
- Add option for custom cookie prefix (#732)
- Make the Open Graph subsystem and DNSBL subsystem use storage backends instead of storing everything in memory by default.
- Allow Common Crawl by default so scrapers have less incentive to scrape
- The bbolt storage backend now runs its cleanup every hour instead of every five minutes.
Potentially breaking changes
The following potentially breaking change applies to native installs with systemd only:
Each instance of systemd service template now has a unique RuntimeDirectory
, as opposed to each instance of the service sharing a RuntimeDirectory
. This change was made to avoid the RuntimeDirectory
getting nuked any time one of the Anubis instances restarts.
If you configured Anubis' unix sockets to listen on /run/anubis/foo.sock
for instance anubis@foo
, you will need to configure Anubis to listen on /run/anubis/foo/foo.sock
and additionally configure your HTTP load balancer as appropriate.
If you need the legacy behaviour, install this systemd unit dropin:
# /etc/systemd/system/[email protected]/50-runtimedir.conf
[Service]
RuntimeDirectory=anubis
Just keep in mind that this will cause problems when Anubis restarts.
What's Changed
- feat: implement localization system by @lolgzs in #716
- fix: determine bind network from bind address by @littlecxm in #714
- Add Brazilian Portuguese translation by @rffontenelle in #726
- fix: Dynamic cookie domain not working by @Earl0fPudding in #731
- feat(cmd): Add custom cookie prefix by @Earl0fPudding in #732
- build(deps): bump the github-actions group with 2 updates by @dependabot in #735
- build(deps): bump the gomod group with 2 updates by @dependabot in #736
- feat: dev container support by @Xe in #734
- Fix translations in pt-BR.json by @rffontenelle in #729
- Set cookies to have the Secure flag default to true by @victorvalenca in #739
- fix(web/main): remove the success interstitial by @Xe in #745
- feat(localization): Add option for forcing a language by @Earl0fPudding in #742
- fix(run/[email protected]): unique runtimedir per instance by @Xe in #750
- feat(localization): Add German language translation by @Earl0fPudding in #741
- docs: add BotStopper docs from the git repo by @Xe in #752
- chore(default-config): allowlist common crawl by @Xe in #753
- feat(localization): Add Turkish language translation by @dcelasun in #751
- docs(known-instances): add ebird.org by @SGHFan in #755
- feat(lib): use new challenge creation flow by @Xe in #749
- chore(devcontainer): move playwright to its own devcontainer service by @Xe in #756
- docs(known-instances): Add Duke University, coinhoards.org (and myself) to known instances by @lotharsm in #757
- fix: make ogtags and dnsbl use the Store instead of memory by @Xe in #760
- fix(lib/store/bbolt): use a multi-bucket flow instead of a single bucket flow by @Xe in #761
- fix(lib/store/bbolt): run cleanup every hour instead of every 5 minutes by @Xe in #762
- docs: remove proof of work branding by @Xe in #763
- feat(localization): Update German language translation by @lotharsm in #764
- docs(known-instances): update list of known instances by @lotharsm in #767
- feat(localization): Add Traditional Chinese language translation by @xlionjuan in #759
- feat(lib/policy/expressions): add system load average to bot expression inputs by @Xe in #766
New Contributors
- @lolgzs made their first contribution in #716
- @littlecxm made their first contribution in ht...
v1.20.0: Thancred Waters
Anubis now has support for weighing the soul of incoming requests with custom rules and thresholds. Anubis also can function without the use of client-side JavaScript using the metarefresh
challenge.
The big ticket items are as follows:
- Implement a no-JS challenge method:
metarefresh
(#95) - Implement request "weight", allowing administrators to customize the behaviour of Anubis based on specific criteria
- Implement GeoIP and ASN based checks via Thoth (#206)
- Add custom weight thresholds via CEL (#688)
- Move Open Graph configuration to the policy file
- Enable support for Open Graph metadata to be returned by default instead of doing lookups against the target
- Add
robots2policy
CLI utility to convert robots.txt files to Anubis challenge policies using CEL expressions (#409) - Refactor challenge presentation logic to use a challenge registry
- Allow challenge implementations to register HTTP routes
- Imprint/Impressum support (#362)
- Fix "invalid response" after "Success!" in Chromium (#564)
A lot of performance improvements have been made:
- Replace internal SHA256 hashing with xxhash for 4-6x performance improvement in policy evaluation and cache operations
- Optimized the OGTags subsystem with reduced allocations and runtime per request by up to 66%
- Replace cidranger with bart for IP range checking, improving IP matching performance by 3-20x with zero heap
allocations
And some cleanups/refactors were added:
- Fix OpenGraph passthrough (#717)
- Remove the unused
/test-error
endpoint and update the testing endpoint/make-challenge
to only be enabled in
development - Add
--xff-strip-private
flag/envvar to toggle skipping X-Forwarded-For private addresses or not - Bump AI-robots.txt to version 1.37
- Make progress bar styling more compatible (UXP, etc)
- Add
--strip-base-prefix
flag/envvar to strip the base prefix from request paths when forwarding to target servers - Fix an off-by-one in the default threshold config
- Add functionality for HS512 JWT algorithm
- Add support for dynamic cookie domains with the
--cookie-dynamic-domain
/COOKIE_DYNAMIC_DOMAIN
flag/envvar
Request weight is one of the biggest ticket features in Anubis. This enables Anubis to be much closer to a Web Application Firewall and when combined with custom thresholds allows administrators to have Anubis take advanced reactions. For more information about request weight, see the request weight section of the policy file documentation.
TL;DR when you have one or more WEIGHT rules like this:
bots:
- name: gitea-session-token
action: WEIGH
expression:
all:
- '"Cookie" in headers'
- headers["Cookie"].contains("i_love_gitea=")
# Remove 5 weight points
weight:
adjust: -5
You can configure custom thresholds like this:
thresholds:
- name: minimal-suspicion # This client is likely fine, its soul is lighter than a feather
expression: weight < 0 # a feather weighs zero units
action: ALLOW # Allow the traffic through
# For clients that had some weight reduced through custom rules, give them a
# lightweight challenge.
- name: mild-suspicion
expression:
all:
- weight >= 0
- weight < 10
action: CHALLENGE
challenge:
# https://anubis.techaro.lol/docs/admin/configuration/challenges/metarefresh
algorithm: metarefresh
difficulty: 1
report_as: 1
# For clients that are browser-like but have either gained points from custom
# rules or report as a standard browser.
- name: moderate-suspicion
expression:
all:
- weight >= 10
- weight < 20
action: CHALLENGE
challenge:
# https://anubis.techaro.lol/docs/admin/configuration/challenges/proof-of-work
algorithm: fast
difficulty: 2 # two leading zeros, very fast for most clients
report_as: 2
# For clients that are browser like and have gained many points from custom
# rules
- name: extreme-suspicion
expression: weight >= 20
action: CHALLENGE
challenge:
# https://anubis.techaro.lol/docs/admin/configuration/challenges/proof-of-work
algorithm: fast
difficulty: 4
report_as: 4
These thresholds apply when no other ALLOW
, DENY
, or CHALLENGE
rule matches the request. WEIGHT
rules add and remove request weight as needed:
bots:
- name: gitea-session-token
action: WEIGH
expression:
all:
- '"Cookie" in headers'
- headers["Cookie"].contains("i_love_gitea=")
# Remove 5 weight points
weight:
adjust: -5
- name: bot-like-user-agent
action: WEIGH
expression: '"Bot" in userAgent'
# Add 5 weight points
weight:
adjust: 5
Of note: the default "generic browser" rule assigns 10 weight points:
# Generic catchall rule
- name: generic-browser
user_agent_regex: >-
Mozilla|Opera
action: WEIGH
weight:
adjust: 10
Adjust this as you see fit.
What's Changed
- build(deps-dev): bump esbuild from 0.25.4 to 0.25.5 in the npm group by @dependabot in #600
- build(deps): bump docker/build-push-action from 6.17.0 to 6.18.0 in the github-actions group by @dependabot in #602
- build(deps): bump github.com/a-h/templ from 0.3.865 to 0.3.887 in the gomod group by @dependabot in #601
- docs(faq): anubis does not mine bitcoin by @Xe in #609
- feat: implement challenge registry by @Xe in #607
- docs(known-instances): add Alliance of Hessian Libraries by @CryptoCopter in #611
- docs(subrequest-auth): document required policy changes by @foosinn in #613
- docs: Adjust the name of the cookie to the current "techaro.lol-anubis-auth" by @jieter in #615
- fix(lib/challenge): allow challenges to register HTTP routes by @Xe in #620
- docs(known-instances): add wiki.dolphin-emu.org to known instances by @lotharsm in #626
- feat(lib/challenge): HTTP meta refresh challenge method by @Xe in #623
- style: Some minor fixes by @JasonLovesDoggo in #548
- Bump ai.robots.txt to v1.34 by @Dryusdan in #632
- build(deps): bump the gomod group with 2 updates by @dependabot in #634
- docs(admin/environments): Prefer IPv6 over IPv4 for apache2 listener directive by @lotharsm in #628
- build(deps): bump github/codeql-action from 3.28.18 to 3.28.19 in the github-actions group by @dependabot in #635
- Adds ability to toggle off stripping of private addrs from XFF by @dchandekstark in #619
- Make progress bar styling more compatible (UXP, etc) by @Fierelier in #636
- feat(lib): implement request weight by @Xe in #621
- Update known-instances.md to include SquirrelJME by @XerTheSquirrel in #643
- fix(anubis): nil check policy loading by @JasonLovesDoggo in #645
- test: introduce SSH based CI for non-native test hosts by @Xe in #644
- build(deps): bump github.com/cloudflare/circl from 1.6.0 to 1.6.1 by @dependabot in #650
- test(ssh-ci): re-enable GOARCH=ppc64le by @Xe in #651
- fix(gitattributes): update pattern for generated files by @JasonLovesDoggo in #652
- fix(ci): conditionally run SSH jobs for TecharoHQ/anubis by @JasonLovesDoggo in #654
- feat: add a strip-base-prefix option by @JasonLovesDoggo in #655
- refactor(ogtags): optimize URL construction and memory allocations by @JasonLovesDoggo in #647
- docs(known-instances): add bugs.scummvm.org and gitlab.postmarketos.org by @lotharsm in #661
- feat: add robots2policy CLI to convert robots.txt to Anubis CEL by @JasonLovesDoggo in #657
- Add ReactOS to known-instances.md by @ColinFinck in #664
- build(deps): bump the github-actions group with 3 updates by @dependabot in #666
- Add the blog section back by @Xe in #670
- feat: implement a client for Thoth, the IP reputation database for Anubis by @Xe in #637
- chore(sponsors): update canine.tools logo by @hyper...
v1.20.0-pre2
v1.20.0 prerelease 2: Thancred Waters
What's Changed
- Makefile: Build robots2policy by @heftig in #699
- fix(default-config): off-by-one error in the default thresholds by @Xe in #701
- feat: implement imprint/impressum support by @Xe in #706
- fix(web/js): broken progress bar with slow algo by @yut23 in #673
- build(deps): bump the github-actions group with 3 updates by @dependabot in #708
- fix(lib): fix invalid response after success in Chrome by @Xe in #711
New Contributors
Full Changelog: v1.20.0-pre1...v1.20.0-pre2
v1.20.0-pre1
v1.20.0 prerelease 1: Thancred Waters
The big ticket items are as follows:
- Implement a no-JS challenge method:
metarefresh
(#95) - Implement request "weight", allowing administrators to customize the behaviour of Anubis based on specific criteria
- Implement GeoIP and ASN based checks via Thoth (#206)
- Add custom weight thresholds via CEL (#688)
- Move Open Graph configuration to the policy file
- Enable support for Open Graph metadata to be returned by default instead of doing lookups against the target
- Add
robots2policy
CLI utility to convert robots.txt files to Anubis challenge policies using CEL expressions (#409) - Refactor challenge presentation logic to use a challenge registry
- Allow challenge implementations to register HTTP routes
A lot of performance improvements have been made:
- Replace internal SHA256 hashing with xxhash for 4-6x performance improvement in policy evaluation and cache operations
- Optimized the OGTags subsystem with reduced allocations and runtime per request by up to 66%
- Replace cidranger with bart for IP range checking, improving IP matching performance by 3-20x with zero heap
allocations
And some cleanups/refactors were added:
- Remove the unused
/test-error
endpoint and update the testing endpoint/make-challenge
to only be enabled in
development - Add
--xff-strip-private
flag/envvar to toggle skipping X-Forwarded-For private addresses or not - Bump AI-robots.txt to version 1.37
- Make progress bar styling more compatible (UXP, etc)
- Add
--strip-base-prefix
flag/envvar to strip the base prefix from request paths when forwarding to target servers
Request weight is one of the biggest ticket features in Anubis. This enables Anubis to be much closer to a Web Application Firewall and when combined with custom thresholds allows administrators to have Anubis take advanced reactions. For more information about request weight, see the request weight section of the policy file documentation.
TL;DR when you have one or more WEIGHT rules like this:
bots:
- name: gitea-session-token
action: WEIGH
expression:
all:
- '"Cookie" in headers'
- headers["Cookie"].contains("i_love_gitea=")
# Remove 5 weight points
weight:
adjust: -5
You can configure custom thresholds like this:
thresholds:
- name: minimal-suspicion # This client is likely fine, its soul is lighter than a feather
expression: weight < 0 # a feather weighs zero units
action: ALLOW # Allow the traffic through
# For clients that had some weight reduced through custom rules, give them a
# lightweight challenge.
- name: mild-suspicion
expression:
all:
- weight >= 0
- weight < 10
action: CHALLENGE
challenge:
# https://anubis.techaro.lol/docs/admin/configuration/challenges/metarefresh
algorithm: metarefresh
difficulty: 1
report_as: 1
# For clients that are browser-like but have either gained points from custom
# rules or report as a standard browser.
- name: moderate-suspicion
expression:
all:
- weight >= 10
- weight < 20
action: CHALLENGE
challenge:
# https://anubis.techaro.lol/docs/admin/configuration/challenges/proof-of-work
algorithm: fast
difficulty: 2 # two leading zeros, very fast for most clients
report_as: 2
# For clients that are browser like and have gained many points from custom
# rules
- name: extreme-suspicion
expression: weight >= 20
action: CHALLENGE
challenge:
# https://anubis.techaro.lol/docs/admin/configuration/challenges/proof-of-work
algorithm: fast
difficulty: 4
report_as: 4
These thresholds apply when no other ALLOW
, DENY
, or CHALLENGE
rule matches the request. WEIGHT
rules add and remove request weight as needed:
bots:
- name: gitea-session-token
action: WEIGH
expression:
all:
- '"Cookie" in headers'
- headers["Cookie"].contains("i_love_gitea=")
# Remove 5 weight points
weight:
adjust: -5
- name: bot-like-user-agent
action: WEIGH
expression: '"Bot" in userAgent'
# Add 5 weight points
weight:
adjust: 5
Of note: the default "generic browser" rule assigns 10 weight points:
# Generic catchall rule
- name: generic-browser
user_agent_regex: >-
Mozilla|Opera
action: WEIGH
weight:
adjust: 10
Adjust this as you see fit.
What's Changed
- build(deps-dev): bump esbuild from 0.25.4 to 0.25.5 in the npm group by @dependabot in #600
- build(deps): bump docker/build-push-action from 6.17.0 to 6.18.0 in the github-actions group by @dependabot in #602
- build(deps): bump github.com/a-h/templ from 0.3.865 to 0.3.887 in the gomod group by @dependabot in #601
- docs(faq): anubis does not mine bitcoin by @Xe in #609
- feat: implement challenge registry by @Xe in #607
- docs(known-instances): add Alliance of Hessian Libraries by @CryptoCopter in #611
- docs(subrequest-auth): document required policy changes by @foosinn in #613
- docs: Adjust the name of the cookie to the current "techaro.lol-anubis-auth" by @jieter in #615
- fix(lib/challenge): allow challenges to register HTTP routes by @Xe in #620
- docs(known-instances): add wiki.dolphin-emu.org to known instances by @lotharsm in #626
- feat(lib/challenge): HTTP meta refresh challenge method by @Xe in #623
- style: Some minor fixes by @JasonLovesDoggo in #548
- Bump ai.robots.txt to v1.34 by @Dryusdan in #632
- build(deps): bump the gomod group with 2 updates by @dependabot in #634
- docs(admin/environments): Prefer IPv6 over IPv4 for apache2 listener directive by @lotharsm in #628
- build(deps): bump github/codeql-action from 3.28.18 to 3.28.19 in the github-actions group by @dependabot in #635
- Adds ability to toggle off stripping of private addrs from XFF by @dchandekstark in #619
- Make progress bar styling more compatible (UXP, etc) by @Fierelier in #636
- feat(lib): implement request weight by @Xe in #621
- Update known-instances.md to include SquirrelJME by @XerTheSquirrel in #643
- fix(anubis): nil check policy loading by @JasonLovesDoggo in #645
- test: introduce SSH based CI for non-native test hosts by @Xe in #644
- build(deps): bump github.com/cloudflare/circl from 1.6.0 to 1.6.1 by @dependabot in #650
- test(ssh-ci): re-enable GOARCH=ppc64le by @Xe in #651
- fix(gitattributes): update pattern for generated files by @JasonLovesDoggo in #652
- fix(ci): conditionally run SSH jobs for TecharoHQ/anubis by @JasonLovesDoggo in #654
- feat: add a strip-base-prefix option by @JasonLovesDoggo in #655
- refactor(ogtags): optimize URL construction and memory allocations by @JasonLovesDoggo in #647
- docs(known-instances): add bugs.scummvm.org and gitlab.postmarketos.org by @lotharsm in #661
- feat: add robots2policy CLI to convert robots.txt to Anubis CEL by @JasonLovesDoggo in #657
- Add ReactOS to known-instances.md by @ColinFinck in #664
- build(deps): bump the github-actions group with 3 updates by @dependabot in #666
- Add the blog section back by @Xe in #670
- feat: implement a client for Thoth, the IP reputation database for Anubis by @Xe in #637
- chore(sponsors): update canine.tools logo by @hyperdefined in #672
- perf: Replace internal SHA256 hashing with xxhash for 4-6x performance improvement by @JasonLovesDoggo in #676
- perf: replace cidranger with bart for significant performance improvements by @JasonLovesDoggo in #675
- docs(known-instances): add wiki.koha-community.org by @prettysunflower in #683
- chore: remove duplicate CHANGELOG entry by @JasonLovesDoggo in #684
- fix(geo): correct typo "counties" to "countries" by @hydrargyrum in #678
- docs(known-instances): add extensions.ty...
v1.19.1: Jenomis cen Lexentale - Echo 1
Return data/bots/ai-robots-txt.yaml
to avoid breaking configs #599
This is a smaller release, mostly focused on improving compatibility and fixes a few major issues with cookies.
Users should upgrade to this release as soon as possible.
What's Changed
- style: apply structpack & goimport by @JasonLovesDoggo in #469
- feat: add TARGET_INSECURE_SKIP_VERIFY setting to allow self-signed HTTPS backends by @Xe in #426
- Add check-spelling v0.0.24 by @jsoref in #462
- Overhaul anubis.freebsd by @pswilde in #427
- ci(check-spelling): allow release names in spelling allowlists by @Xe in #483
- test(playwright): Add Docker and Podman support by @SlyEcho in #433
- chore(go.mod): move yeet to be a go tool by @Xe in #485
- fix(jwt): update nonce value in challenge JWT cookie to be a string by @JasonLovesDoggo in #486
- feat(ci): use dynamic repository owner and name in Docker actions by @JasonLovesDoggo in #487
- fix(bots/phrik): add IPv6 address for phrik by @Xe in #494
- build(deps-dev): bump the npm group with 3 updates by @dependabot in #496
- fix(lib): use a new cookie per domain when COOKIE_DOMAIN is set by @Xe in #490
- docs(known-instances): add some entries to the list by @Xe in #497
- fix(lib): make ClearCookie respect the dynamic cookie name by @Xe in #500
- fix(systemd): add RuntimeDirectory by @Xe in #510
- docs: add HTMX workaround by @Xe in #511
- Bump AI-robots.txt rules to version 1.30 by @Dryusdan in #509
- feat: add TARGET_HOST to allow overriding the Host header when forwarding requests by @OatmealDome in #507
- feat(apps): add SearXNG instance tracker policy and Qualys Labs SSL testing rules by @Xe in #512
- feat(apps): Make SASL login work on bookstack with Anubis by @Dryusdan in #502
- feat(lib): ensure that clients store cookies by @Xe in #501
- chore(docs/deploy): move to new cluster by @Xe in #519
- Add reddit.nerdvpn.de to known instances by @Lenni-builder in #518
- fix(lib): properly clear out test cookie by @Xe in #522
- build(deps): bump the github-actions group with 4 updates by @dependabot in #523
- docs:
REDIRECT_DOMAINS
must include port numbers by @gucci-on-fleek in #521 - docs: correct the path for the default configuration file by @gravityfargo in #535
- Bump AI-robots.txt rules to version 1.31 by @Dryusdan in #538
- feat: add TARGET_SNI to allow overriding the TLS handshake hostname when forwarding requests by @jprenken in #529
- fix(lib): record challenges issused over embedded HTML by @Xe in #543
- docs(native-install): vague gesturing at distribution package managers by @Xe in #544
- fix(expression): add validation for empty expression list in CEL by @JasonLovesDoggo in #545
- docs(admin): add wordpress docs by @Xe in #552
- Create Anubis OpenRC init.d script by @CyberTailor in #561
- build(deps): bump astral-sh/setup-uv from 6.0.1 to 6.1.0 in the github-actions group by @dependabot in #558
- add Weblate to known-instances.md by @jordigh in #571
- feat(cli): Add --version flag by @kdkasad in #572
- build(deps): bump k8s.io/apimachinery from 0.33.0 to 0.33.1 in the gomod group by @dependabot in #524
- fix(internal): register mime type for .mjs files by @Xe in #577
- feat(expressions): add randInt function to allow making rules nondeterministic by @Xe in #578
- feat(data): add x-firefox-ai default challenge rule by @Xe in #580
- fix(internal/test): skip integration tests if SKIP_INTEGRATION is set by @Xe in #586
- feat(yeetfile): build GOARCH=ppc64le packages by @Xe in #583
- feat(lib): Add proxied requests counter metric by @kdkasad in #570
- fix(web): show Anubis version number on challenge pages by @Xe in #587
- fix(lib): only use the first five characters of Accept-Language header values by @Xe in #588
- style(bench): small cleanup by @JasonLovesDoggo in #546
- feat(lib): annotate cookies with what rule was passed by @Xe in #576
- Add Applebot definition by @tabletcorry in #589
- docs(known-instances): Add Gitea by @jesentz in #591
- Opt-in policies for OpenAI and MistralAI bots by @tabletcorry in #590
- docs(known-instances): add openwrt.org by @Aloki in #594
- docs(known-instances): add catgirl.click by @Zohiu in #597
- add my site to known-instances.md by @minihoot in #595
- Split up AI filtering files by @tabletcorry in #592
New Contributors
- @OatmealDome made their first contribution in #507
- @Lenni-builder made their first contribution in #518
- @gucci-on-fleek made their first contribution in #521
- @gravityfargo made their first contribution in #535
- @jprenken made their first contribution in #529
- @CyberTailor made their first contribution in #561
- @jordigh made their first contribution in #571
- @kdkasad made their first contribution in #572
- @tabletcorry made their first contribution in #589
- @jesentz made their first contribution in #591
- @Aloki made their first contribution in #594
- @Zohiu made their first contribution in #597
- @minihoot made their first contribution in #595
Full Changelog: v1.18.0...v1.19.1
v1.19.0: Jenomis cen Lexentale
NOTE:
Prefer v1.19.1. This has a config bug that was fixed in v1.19.1.
This is a smaller release, mostly focused on improving compatibility and fixes a few major issues with cookies.
Users should upgrade to this release as soon as possible.
What's Changed
- style: apply structpack & goimport by @JasonLovesDoggo in #469
- feat: add TARGET_INSECURE_SKIP_VERIFY setting to allow self-signed HTTPS backends by @Xe in #426
- Add check-spelling v0.0.24 by @jsoref in #462
- Overhaul anubis.freebsd by @pswilde in #427
- ci(check-spelling): allow release names in spelling allowlists by @Xe in #483
- test(playwright): Add Docker and Podman support by @SlyEcho in #433
- chore(go.mod): move yeet to be a go tool by @Xe in #485
- fix(jwt): update nonce value in challenge JWT cookie to be a string by @JasonLovesDoggo in #486
- feat(ci): use dynamic repository owner and name in Docker actions by @JasonLovesDoggo in #487
- fix(bots/phrik): add IPv6 address for phrik by @Xe in #494
- build(deps-dev): bump the npm group with 3 updates by @dependabot in #496
- fix(lib): use a new cookie per domain when COOKIE_DOMAIN is set by @Xe in #490
- docs(known-instances): add some entries to the list by @Xe in #497
- fix(lib): make ClearCookie respect the dynamic cookie name by @Xe in #500
- fix(systemd): add RuntimeDirectory by @Xe in #510
- docs: add HTMX workaround by @Xe in #511
- Bump AI-robots.txt rules to version 1.30 by @Dryusdan in #509
- feat: add TARGET_HOST to allow overriding the Host header when forwarding requests by @OatmealDome in #507
- feat(apps): add SearXNG instance tracker policy and Qualys Labs SSL testing rules by @Xe in #512
- feat(apps): Make SASL login work on bookstack with Anubis by @Dryusdan in #502
- feat(lib): ensure that clients store cookies by @Xe in #501
- chore(docs/deploy): move to new cluster by @Xe in #519
- Add reddit.nerdvpn.de to known instances by @Lenni-builder in #518
- fix(lib): properly clear out test cookie by @Xe in #522
- build(deps): bump the github-actions group with 4 updates by @dependabot in #523
- docs:
REDIRECT_DOMAINS
must include port numbers by @gucci-on-fleek in #521 - docs: correct the path for the default configuration file by @gravityfargo in #535
- Bump AI-robots.txt rules to version 1.31 by @Dryusdan in #538
- feat: add TARGET_SNI to allow overriding the TLS handshake hostname when forwarding requests by @jprenken in #529
- fix(lib): record challenges issused over embedded HTML by @Xe in #543
- docs(native-install): vague gesturing at distribution package managers by @Xe in #544
- fix(expression): add validation for empty expression list in CEL by @JasonLovesDoggo in #545
- docs(admin): add wordpress docs by @Xe in #552
- Create Anubis OpenRC init.d script by @CyberTailor in #561
- build(deps): bump astral-sh/setup-uv from 6.0.1 to 6.1.0 in the github-actions group by @dependabot in #558
- add Weblate to known-instances.md by @jordigh in #571
- feat(cli): Add --version flag by @kdkasad in #572
- build(deps): bump k8s.io/apimachinery from 0.33.0 to 0.33.1 in the gomod group by @dependabot in #524
- fix(internal): register mime type for .mjs files by @Xe in #577
- feat(expressions): add randInt function to allow making rules nondeterministic by @Xe in #578
- feat(data): add x-firefox-ai default challenge rule by @Xe in #580
- fix(internal/test): skip integration tests if SKIP_INTEGRATION is set by @Xe in #586
- feat(yeetfile): build GOARCH=ppc64le packages by @Xe in #583
- feat(lib): Add proxied requests counter metric by @kdkasad in #570
- fix(web): show Anubis version number on challenge pages by @Xe in #587
- fix(lib): only use the first five characters of Accept-Language header values by @Xe in #588
- style(bench): small cleanup by @JasonLovesDoggo in #546
- feat(lib): annotate cookies with what rule was passed by @Xe in #576
- Add Applebot definition by @tabletcorry in #589
- docs(known-instances): Add Gitea by @jesentz in #591
- Opt-in policies for OpenAI and MistralAI bots by @tabletcorry in #590
- docs(known-instances): add openwrt.org by @Aloki in #594
- docs(known-instances): add catgirl.click by @Zohiu in #597
- add my site to known-instances.md by @minihoot in #595
- Split up AI filtering files by @tabletcorry in #592
New Contributors
- @OatmealDome made their first contribution in #507
- @Lenni-builder made their first contribution in #518
- @gucci-on-fleek made their first contribution in #521
- @gravityfargo made their first contribution in #535
- @jprenken made their first contribution in #529
- @CyberTailor made their first contribution in #561
- @jordigh made their first contribution in #571
- @kdkasad made their first contribution in #572
- @tabletcorry made their first contribution in #589
- @jesentz made their first contribution in #591
- @Aloki made their first contribution in #594
- @Zohiu made their first contribution in #597
- @minihoot made their first contribution in #595
Full Changelog: v1.18.0...v1.19.0
v1.19.0-pre1: Jenomis cen Lexentale
What's Changed
- style: apply structpack & goimport by @JasonLovesDoggo in #469
- feat: add TARGET_INSECURE_SKIP_VERIFY setting to allow self-signed HTTPS backends by @Xe in #426
- Add check-spelling v0.0.24 by @jsoref in #462
- Overhaul anubis.freebsd by @pswilde in #427
- ci(check-spelling): allow release names in spelling allowlists by @Xe in #483
- test(playwright): Add Docker and Podman support by @SlyEcho in #433
- chore(go.mod): move yeet to be a go tool by @Xe in #485
- fix(jwt): update nonce value in challenge JWT cookie to be a string by @JasonLovesDoggo in #486
- feat(ci): use dynamic repository owner and name in Docker actions by @JasonLovesDoggo in #487
- fix(bots/phrik): add IPv6 address for phrik by @Xe in #494
- build(deps-dev): bump the npm group with 3 updates by @dependabot in #496
- fix(lib): use a new cookie per domain when COOKIE_DOMAIN is set by @Xe in #490
- docs(known-instances): add some entries to the list by @Xe in #497
- fix(lib): make ClearCookie respect the dynamic cookie name by @Xe in #500
- fix(systemd): add RuntimeDirectory by @Xe in #510
- docs: add HTMX workaround by @Xe in #511
- Bump AI-robots.txt rules to version 1.30 by @Dryusdan in #509
- feat: add TARGET_HOST to allow overriding the Host header when forwarding requests by @OatmealDome in #507
- feat(apps): add SearXNG instance tracker policy and Qualys Labs SSL testing rules by @Xe in #512
- feat(apps): Make SASL login work on bookstack with Anubis by @Dryusdan in #502
- feat(lib): ensure that clients store cookies by @Xe in #501
- chore(docs/deploy): move to new cluster by @Xe in #519
- Add reddit.nerdvpn.de to known instances by @Lenni-builder in #518
- fix(lib): properly clear out test cookie by @Xe in #522
- build(deps): bump the github-actions group with 4 updates by @dependabot in #523
- docs:
REDIRECT_DOMAINS
must include port numbers by @gucci-on-fleek in #521 - docs: correct the path for the default configuration file by @gravityfargo in #535
- Bump AI-robots.txt rules to version 1.31 by @Dryusdan in #538
- feat: add TARGET_SNI to allow overriding the TLS handshake hostname when forwarding requests by @jprenken in #529
- fix(lib): record challenges issused over embedded HTML by @Xe in #543
- docs(native-install): vague gesturing at distribution package managers by @Xe in #544
- fix(expression): add validation for empty expression list in CEL by @JasonLovesDoggo in #545
- docs(admin): add wordpress docs by @Xe in #552
New Contributors
- @OatmealDome made their first contribution in #507
- @Lenni-builder made their first contribution in #518
- @gucci-on-fleek made their first contribution in #521
- @gravityfargo made their first contribution in #535
- @jprenken made their first contribution in #529
Full Changelog: v1.18.0...v1.19.0-pre1