diff --git a/README.md b/README.md index 0b0581e..dd3dac2 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,22 @@ # Mesozoa +Intermediate reverse proxy that protects your server from crawlers by forcing the browser to run proof of work. + +## Why? + Why not Anubis? Because it provides no build instructions and only supports Docker. Why not using Realm completely? Because the hook system is useless and only allows filtering. +And because it looked like a fun little project. + ## Install +[Install rustup](https://rustup.rs) and a nightly Rust toolchain. + + # Build executable at ./target/release/mesozoa + cargo build --release + Must be used behind a reverse proxy providing `X-Forwarded-For`. ## Challenge protocol @@ -14,24 +25,28 @@ Must be used behind a reverse proxy providing `X-Forwarded-For`. Sent by the server as a cookie. -`secret <- chosen randomly, long term` - -`salt <- chosen randomly, not stored` - -`timestamp <- UNIX time in seconds, 64 bits, big endian` - -`ua <- User-Agent from request header` - -`ip <- X-Forwarded-For from request header (client's IP)` +* `secret`: chosen randomly at startup +* `salt`: chosen randomly each time +* `timestamp`: UNIX time in seconds, 64 bits, big endian +* `ua`: `User-Agent` from request header +* `ip`: `X-Forwarded-For` from request header (client's IP) `set-cookie: mesozoa-challenge=BASE64(salt || timestamp || SHA3-256(secret || salt || timestamp || ip || "/" || ua))` -Where `BASE64` is unpadded. +Where `BASE64` is URL-safe unpadded. ### Challenge verification Request must contain both cookies `mesozoa-challenge` and `mesozoa-proof`. +Server checks challenge is correct and timestamp not too old. + +`cookie: mesozoa-proof=nonce` + +`hash = SHA2-256(nonce || challenge)` + +Client must find a `nonce` matching `/[0-9a-zA-Z_-]{8}/` such that `hash` starts with at least some number of zeros (in binary representation, MSB-first). + ## Security ### Network handling and HTTP parsing @@ -50,6 +65,18 @@ SHA2 (used for PoW) is vulnerable but nonce is at the beginning so this is not a I would like a better PoW: memory-bound and ideally non-parallel. Cuckoo seems a good candidate. +## Contribution + +Patches and forks are welcome. Send an e-mail to `tuxmain ât zettascript ðøt org`. + +If people are interested, I may switch to a public forge like Codeberg. + +The "A" in GNU AGPL means that if you host a publicly available instance of a modified version, then you should also make the modified source code available to users. +For example, this can take the form of a link to a repository in the challenge page or in the protected website. +As the challenge page's source code is directly distributed by the server, you can modify it independently. +(unless adding a compiled object, like WASM. Then you have to publish its source.) +Configuration file can be modified and kept secret, of course. + ## License [Support me via LiberaPay](https://liberapay.com/tuxmain/donate) diff --git a/src/challenge.html b/src/challenge.html index 6a92181..6854e2e 100644 --- a/src/challenge.html +++ b/src/challenge.html @@ -4,9 +4,29 @@
+ This service is protected against abusive crawlers by a proof of work mechanism.
+ We are sorry for the inconvenience.
+
+ Powered by Mesozoa,
+ distributed under license GNU AGPL v3 without any warranty.
+