bomba + ai = bombai. it bombs ai based purely on behavior
Find a file
2026-04-09 16:39:48 +02:00
src hmm lets not 2026-03-21 10:24:39 +01:00
.envrc Initial commit 2025-12-17 19:49:48 +01:00
.gitignore add more checks 2026-03-19 11:27:14 +01:00
Caddyfile Initial commit 2025-12-17 19:49:48 +01:00
Cargo.lock lockfile update 2026-01-18 02:36:26 +01:00
Cargo.toml better logging & config reloading 2026-01-03 09:44:57 +01:00
LICENSE fix license 2025-12-18 01:12:47 +01:00
README.md Update README.md 2026-04-09 16:39:48 +02:00
shell.nix Initial commit 2025-12-17 19:49:48 +01:00

bombai: bomba + ai

instead of letting the ai boom bomb our websites, lets bomb the ai in return.

install via rust with cargo install --git https://git.tudbut.de/tudbut/bombai. https://rustup.rs

update policy: releases after around 2 weeks of no changes to main. config changes can be made whenever and must be documented in the release text. config changes made on main do not need to be marked; expect breakage resulting in crashes if you track main.

features

  • not dependent on user agents
    • metric is only what is requested, though extra checks can be used for the last 1% that behave more gently
  • configurable, allowing e.g. setting lower limits for rarely visited pages
  • specifically designed to guard forgejo (and similar) things
  • zip bombs
  • traps (like iocaine, with or without bullshit generation)
  • redirecting to iocaine :)
  • metrics

more detail

detection

detection works by request counting for designated areas of the page ([[paths]])

  • each paths entry has its own counter
    • with separate max value after which requests get denied and the requester timeouted
    • with a decay per hour, that is calculated at much finer resolution than hourly of course
  • fail = timeout
  • entries can be set to always fail to create "trap paths" (max = 0)
  • subnets can be blobbed together into one entity, e.g. to catch alibaba's entire /24 subnet of bots

extra checks

there are a few extra checks that can be used to increase the accuracy from around 98% to 99.5% or more:

  • ie: denies internet explorer from visiting (many bots vary their user agents in such a way that they sometimes visit as internet explorer)
  • sec-fetch-mode: denies most bots masquerading as firefox or chrome-derivatives, catches pretty much everything that isnt caught by ie
  • priority: denies most bots masquerading as firefox or chrome-derivatives that pass through sec-fetch-mode (very rarely needed, but does catch one bot every few hours for me)
  • platform-consistency: similarly rarely needed as priority. catches chrome-pretenders that dont have consistent platform headers (says linux and windows at the same time for example). this obviously cant catchy anything that doesnt blatantly lie about its platform, but has a few hits sometimes.
  • ua-list: denies some set of user agents. can read ai.robots.txt and such. usually not needed if your detection settings are agressive enough.

fail response

  • http mode: signal caddy (or other reverse proxy) to do something special
    • e.g. redirect to iocaine or other trap
  • file mode: respond with simple http response or html file
  • generated mode:
    • customizable
      • start text
      • end text
      • char spam in between
    • total length can be set
    • can be gzipped
      • optionally only if client allows it (via Accept-Encoding)
      • "gzip chance" from 0 to 100% (of requests)
    • "continuous failure" mode where a few links that lead into a maze of more failure are generated between start text and spam
  • bullshit mode: responds with random words, generated using a probability distribution

config

default config is automatically dropped to disk and can also be found at src/bombai.toml

it contains a lot of documentation

metrics

dashboard base url can be set in config; metrics available at /bombai/metrics (assuming dashboard is at /bombai).

how to

add to caddyfile as per the caddyfile in this repo. the iocaine part is not required.

@read method GET HEAD
reverse_proxy @read 127.0.0.1:42067 {
	@fallback status 421
	handle_response @fallback

	# optional, if using fail_response.data = http
	@iocaine status 423
	handle_response @iocaine {
		reverse_proxy 127.0.0.1:42069 # iocaine needs to be configured to always serve its poison for this.
	}
}

license

wtfpl+-ai. no ai allowed, everything else allowed.

cargo tree

i dont like big dependency trees. so this one is small.

tudbut@Tud-NixX260 ~/g/bombai (main)> cargo tree
bombai v0.1.0 (/home/tudbut/gitshit/bombai)
├── chrono v0.4.42
│   ├── iana-time-zone v0.1.64
│   └── num-traits v0.2.19
│       [build-dependencies]
│       └── autocfg v1.5.0
├── deborrow v0.3.1
│   └── deborrow-macro v0.2.0 (proc-macro)
├── flate2 v1.1.5
│   ├── crc32fast v1.5.0
│   │   └── cfg-if v1.0.4
│   └── miniz_oxide v0.8.9
│       ├── adler2 v2.0.1
│       └── simd-adler32 v0.3.8
├── horrorhttp v0.2.1
│   └── readformat v1.0.3
├── microlock v0.3.1
├── nanoserde v0.2.1 (https://github.com/tudbut/nanoserde#fc010f51)
│   └── nanoserde-derive v0.2.1 (proc-macro) (https://github.com/tudbut/nanoserde#fc010f51)
└── readformat v1.0.3