
Come curl, ma supera i muri anti-bot di Anubis e Cloudflare.
$ nix run github:fzakaria/anubis-fetch -- https://lore.kernel.org/linux-mm/some-thread/T/
Un CLI veloce (in Go) per recuperare URL dietro i muri proof-of-work di Anubis e i controlli di fingerprint di Cloudflare — risolvendo la sfida in-process e ricorrendo a un browser reale solo quando necessario.
Un numero crescente di siti — lore.kernel.org, GNOME, kernel.org e molti altri — si trovano dietro Anubis, un muro anti-bot che obbliga il browser a risolvere una proof-of-work SHA-256 prima di servire qualsiasi contenuto. È ottimo per fermare gli scraper. Ed è anche ottimo per fermare te quando vuoi semplicemente fare curl di una discussione in una mailing list:
$ curl -s https://lore.kernel.org/linux-mm/some-thread/T/ | grep -o '<title>.*</title>'
<title>Making sure you're not a bot!</title> # 🤢
anubis-fetch ti restituisce la pagina vera:
$ anubis-fetch https://lore.kernel.org/linux-mm/some-thread/T/ | grep -o '<title>.*</title>'
<title>[PATCH 0/2] ...</title> # 🥳
I muri anti-bot vivono su due livelli diversi, e anubis-fetch li gestisce entrambi, partendo dal passo più economico:
techaro.lol-anubis-auth) dopo che hai superato la verifica una volta; un browser non viene nuovamente sfidato alla visita successiva, e nemmeno noi. I cookie vengono salvati per host (vedi Persistenza dei cookie).req impersonando un vero Chrome — stessa impronta TLS/JA3 + HTTP/2 — il che supera anche il fingerprinting passivo di Cloudflare. Se la risposta è una sfida Anubis, forziamo il nonce e lo inviamo. Nessun browser, ~0,6s.chromedp, che esegue qualsiasi JavaScript il sito serva.[!NOTE] Il ripiego scatta per: i metodi di sfida
preact/metarefreshdi Anubis, un metodo sconosciuto/futuro, una difficoltà troppo alta per la forza bruta, una soluzione rifiutata, oppure una sfida JavaScript attiva di Cloudflare (Managed Challenge / Turnstile / "I'm Under Attack"). L'impersonificazione supera Cloudflare passivo; solo un browser supera i livelli JavaScript attivi. Quindianubis-fetchdegrada a "più lento", mai "rotto".
Perché è ~4× più lento e trascina un Chromium da ~200 MB in ogni fetch. Il risolutore in-process è il caso comune; il browser è la rete di sicurezza.
| Percorso | Tempo di attesa | Richiede Chromium |
|---|---|---|
| Risolutore (proof-of-work Anubis) | ~0,6s | no |
| Ripiego sul browser | ~2,0s | sì |
Anubis incorpora una sfida come JSON nella pagina:
{"rules":{"algorithm":"fast","difficulty":4},
"challenge":{"id":"…","method":"fast","randomData":"6214bd88…","difficulty":4}}
Risolverla significa trovare un nonce tale che hex(sha256(randomData ‖ nonce)) inizi con difficulty caratteri zero (il nonce è la sua stringa in base 10). Poi consegnamo la risposta:
GET /.within.website/x/cmd/anubis/api/pass-challenge?id=…&response=<hash>&nonce=<n>&redir=<url>&elapsedTime=<ms>
…che imposta il cookie di autenticazione e reindirizza alla pagina reale. La difficoltà 4 (il default su lore/kernel.org/GNOME) richiede ~65k hash — sub-millisecondo in Go.
Eseguito direttamente:
$ nix run github:fzakaria/anubis-fetch -- <url>
Installalo nel tuo profilo:
$ nix profile install github:fzakaria/anubis-fetch
Oppure aggiungilo al tuo flake:
{
inputs.anubis-fetch.url = "github:fzakaria/anubis-fetch";
# poi, ad es. in home.packages / environment.systemPackages:
# inputs.anubis-fetch.packages.${system}.default
}
$ anubis-fetch [flags] URL
| Flag | Significato |
|---|---|
--text | mostra testo semplice leggibile invece di HTML |
--timeout MS | timeout per passo in millisecondi (default 30000) |
--ua STRING | sovrascrive lo User-Agent |
--browser | salta il risolutore; vai direttamente al browser headless |
--no-browser | non usare mai il browser; esci con codice 3 se la risoluzione non può essere applicata |
--no-cache | non leggere né scrivere il cookie jar persistente |
# HTML su stdout
$ anubis-fetch https://lore.kernel.org/linux-mm/some-thread/T/
# testo semplice leggibile
$ anubis-fetch --text https://lore.kernel.org/linux-mm/some-thread/T/
# minimale/veloce — utile negli script; esce con 3 se servirebbe un browser
$ anubis-fetch --no-browser https://example.com/ && echo "got it"
Dopo un fetch riuscito, il cookie di autenticazione viene scritto in
$XDG_CACHE_HOME/anubis-fetch/cookies/<host>.json (con fallback su
~/.cache/…). L'esecuzione successiva per quell'host viene lasciata passare
direttamente — niente proof-of-work, niente browser — esattamente come la
rivisitazione di un browser. Anche i cookie ottenuti tramite il ripiego sul
browser vengono salvati, così un'esecuzione successiva può seguire il percorso
HTTP veloce. Usa --no-cache per disabilitare, oppure elimina il file per
forzare una nuova risoluzione.
Tutto è collegato tramite il flake:
$ nix develop # shell di sviluppo: go, gopls, chromium, treefmt
$ go test ./... # test unitari (ermetici — nessuna rete)
$ nix build # compila il binario wrapper
$ nix flake check # build + test + formattazione
$ nix fmt # formatta Go + Nix tramite treefmt (gofmt + alejandra)
L'implementazione della proof-of-work è vincolata al vettore di test pubblicato
da Anubis stesso (sha256("hunter" + "0")), così una deriva nella costruzione
dell'hash fa fallire un test unitario invece di restituire silenziosamente
spazzatura.