$ nix run github:fzakaria/anubis-fetch -- https://lore.kernel.org/linux-mm/some-thread/T/
一个快速(Go)CLI 工具,用于从 Anubis 工作量证明墙和 Cloudflare 指纹检测之后获取 URL — 在进程内解决挑战,仅在必要时才启动真实浏览器。
越来越多的网站 — lore.kernel.org、GNOME、kernel.org 等等 — 都位于 Anubis 这个机器人防护墙之后。它会要求你的浏览器在提供任何内容之前先解决一个 SHA-256 工作量证明。它在阻止爬虫方面非常有效。不过,当你想用 curl 获取一个邮件列表线程时,它也同样擅长阻止你:
$ 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 则能让你拿到真实页面:
$ anubis-fetch https://lore.kernel.org/linux-mm/some-thread/T/ | grep -o '<title>.*</title>'
<title>[PATCH 0/2] ...</title> # 🥳
机器人防护墙存在于两个不同的层面,anubis-fetch 会按成本从低到高依次处理:
techaro.lol-anubis-auth);浏览器在下次访问时不会被再次挑战,我们同样不会。Cookie 按主机持久化保存(参见 Cookie 持久化)。req 发出,模拟真实的 Chrome — 相同的 TLS/JA3 + HTTP/2 指纹 — 这也能通过 Cloudflare 的被动指纹检测。如果响应是 Anubis 挑战,我们就暴力破解 nonce 并提交。无需浏览器,约 0.6 秒。chromedp 驱动无头 Chromium,运行网站提供的任何 JavaScript。[!NOTE] 回退机制在以下情况触发:Anubis 的
preact/metarefresh挑战方式、未知/未来的方式、难度过高无法暴力破解、解决方案被拒绝,或 Cloudflare 主动 JS 挑战(Managed Challenge / Turnstile / "I'm Under Attack")。模拟即可通过被动 Cloudflare 的检测;只有浏览器才能通过主动 JS 层。因此anubis-fetch只会"变慢",绝不会"不可用"。
因为这样会慢大约 4 倍,并且每次抓取都要拖入一个约 200 MB 的 Chromium。进程内求解器才是常见场景;浏览器只是安全网。
| 路径 | 实际耗时 | 需要 Chromium |
|---|---|---|
| 求解器(Anubis 工作量证明) | ~0.6s | 否 |
| 浏览器回退 | ~2.0s | 是 |
Anubis 将挑战以 JSON 形式嵌入页面中:
{"rules":{"algorithm":"fast","difficulty":4},
"challenge":{"id":"…","method":"fast","randomData":"6214bd88…","difficulty":4}}
解决它意味着找到一个 nonce,使得 hex(sha256(randomData ‖ nonce)) 以 difficulty 个零字符开头(nonce 是其十进制字符串)。然后我们将答案交回:
GET /.within.website/x/cmd/anubis/api/pass-challenge?id=…&response=<hash>&nonce=<n>&redir=<url>&elapsedTime=<ms>
…这会设置认证 cookie 并重定向到真实页面。难度 4(lore/kernel.org/GNOME 上的默认值)大约是 6.5 万次哈希 — 在 Go 中不到一毫秒。
直接运行:
$ nix run github:fzakaria/anubis-fetch -- <url>
安装到你的 profile 中:
$ nix profile install github:fzakaria/anubis-fetch
或者将其添加到自己的 flake 中:
{
inputs.anubis-fetch.url = "github:fzakaria/anubis-fetch";
# then, e.g. in home.packages / environment.systemPackages:
# inputs.anubis-fetch.packages.${system}.default
}
$ anubis-fetch [flags] URL
# HTML to stdout
$ anubis-fetch https://lore.kernel.org/linux-mm/some-thread/T/
# readable plain text
$ anubis-fetch --text https://lore.kernel.org/linux-mm/some-thread/T/
# lean/fast only — useful in scripts; exits 3 if it would need a browser
$ anubis-fetch --no-browser https://example.com/ && echo "got it"
成功抓取后,认证 cookie 会被写入
$XDG_CACHE_HOME/anubis-fetch/cookies/<host>.json(回退到
~/.cache/…)。下次对该主机的运行会直接放行 — 无需
工作量证明,也无需浏览器 — 与浏览器再次访问完全一致。通过
浏览器回退获取的 cookie 也会被保存,因此后续运行可以直接走快速的
HTTP 路径。使用 --no-cache 可禁用,或者直接删除该文件以强制
重新求解。
一切都通过 flake 串联起来:
$ nix develop # dev shell: go, gopls, chromium, treefmt
$ go test ./... # unit tests (hermetic — no network)
$ nix build # build the wrapped binary
$ nix flake check # build + tests + formatting
$ nix fmt # format Go + Nix via treefmt (gofmt + alejandra)
工作量证明实现与 Anubis 自己发布的测试
向量(sha256("hunter" + "0"))绑定,因此哈希构造的任何偏差都会导致
单元测试失败,而不是静默返回垃圾数据。
| 标志 | 含义 |
|---|
--text | 渲染可读的纯文本而非 HTML |
--timeout MS | 每步超时时间,单位为毫秒(默认 30000) |
--ua STRING | 覆盖 User-Agent |
--browser | 跳过求解器;直接使用无头浏览器 |
--no-browser | 绝不使用浏览器;若求解无法应用则退出码为 3 |
--no-cache | 不读取也不写入持久化 cookie jar |