$ nix run github:fzakaria/anubis-fetch -- --text https://lore.kernel.org/
一个 Go CLI,用于获取位于 Anubis 工作量证明挑战之后的 URL。它在进程内解决旧版 SHA-256 和 WASM 挑战,并以无头 Chromium 作为回退方案。
诸如 lore.kernel.org 和 kernel.org 之类的站点使用 Anubis 要求在提供页面之前完成工作量证明。普通的 HTTP 客户端可能会收到挑战页面,而不是所请求的内容。anubis-fetch 会解决挑战、提交答案,并将结果页面写入 stdout。
req 来模拟 Chrome 的 TLS 和 HTTP/2 指纹。这有助于应对被动式机器人检测,包括 Cloudflare 的检测。对于 Anubis 的 fast 和 slow 方法,该工具计算一个 nonce 并直接提交答案。对于 WASM 方法 sha256、argon2id 和 hashx,它会下载站点的模块,并使用 wazero 在 Go 中运行它。chromedp 驱动的无头 Chromium 会运行站点所提供的挑战代码。浏览器回退可处理 Anubis 的 preact 和 metarefresh 方法,以及 Cloudflare 挑战页面(带有 cf-mitigated: challenge 的响应)。当旧版 SHA-256 难度超过其限制、WASM 执行失败或超时,或者 Anubis 拒绝某个解答时,该工具也会回退。使用 --browser 可直接从 Chromium 开始,或使用 --no-browser 要求走 HTTP 路径。所有三种 WASM 方法都可在 --no-browser 下工作。
原生求解器避免了每次获取都启动浏览器进程。对于需要回退的挑战,Nix 包中仍然包含 Chromium。
原始 SHA-256 路径的大致获取时间:
| 路径 | 实际耗时 | 需要 Chromium |
|---|---|---|
| 进程内 SHA-256 求解器 | ~0.6s | 否 |
| 浏览器回退 | ~2.0s | 是 |
针对本地 Anubis 服务器在难度 2 下的 WASM 获取时间:
| WASM 方法 | 中位实际耗时 | 需要 Chromium |
|---|---|---|
| SHA-256 | ~0.025s | 否 |
| Argon2id | ~0.55s-2.33s | 否 |
| HashX | ~0.041s | 否 |
对于 fast 和 slow 方法,Anubis 将挑战嵌入页面中:
{"rules":{"algorithm":"fast","difficulty":4},
"challenge":{"id":"...","method":"fast","randomData":"6214bd88...","difficulty":4}}
求解器寻找一个 nonce,使得 hex(sha256(randomData || nonce)) 以 difficulty 个零字符开头。该 nonce 被编码为十进制字符串。答案被提交给 Anubis:
GET /.within.website/x/cmd/anubis/api/pass-challenge?id=...&response=<hash>&nonce=<n>&redir=<url>&elapsedTime=<ms>
成功的响应会设置一个认证 cookie,并重定向到所请求的页面。难度 4 平均需要约 65,536 次哈希计算。
对于 sha256、argon2id 和 hashx,Anubis 提供一个实现工作量证明的 WebAssembly 模块。anubis-fetch 下载该模块,将挑战的十六进制数据解码为字节,并将数据和难度传递给该模块。该模块搜索一个 nonce,并返回 nonce 和哈希,以提交到上述同一端点。
该模块使用 wazero 在 Go 进程内运行,因此这些方法可在 --no-browser 下工作。执行有内存和时间限制。该模块定义难度规则;WASM 难度数值与旧版 SHA-256 方法不能直接比较。
直接运行:
$ nix run github:fzakaria/anubis-fetch -- <url>
或者将输入添加到你的 flake:
{
inputs.anubis-fetch.url = "github:fzakaria/anubis-fetch";
}
将 inputs.anubis-fetch.packages.${system}.default 添加到 home.packages 或 environment.systemPackages。
anubis-fetch [flags] URL
| 标志 | 作用 |
|---|---|
--text | 将 HTML 转换为纯文本 |
--timeout MS | 设置每步超时时间(毫秒);默认 30000 |
--ua STRING | 设置 User-Agent |
--browser | 直接使用 Chromium |
--no-browser | 如果 HTTP 求解器需要浏览器回退,则以 3 退出 |
--no-cache | 禁用读取和写入已保存的 cookie |
--help, -h | 打印用法并退出 |
# HTML to stdout
anubis-fetch https://lore.kernel.org/
# Plain text
anubis-fetch --text https://lore.kernel.org/
# Require the HTTP path; check for exit status 3
anubis-fetch --no-browser https://lore.kernel.org/
Cookie 按主机保存在 $XDG_CACHE_HOME/anubis-fetch/cookies/<host>.json,或者当 XDG_CACHE_HOME 未设置时保存在 ~/.cache/anubis-fetch/cookies/<host>.json。有效的认证 cookie 可以让后续请求跳过挑战。通过 Chromium 获取的 cookie 也会被保存,同时保存 Chromium 的 User-Agent。Cloudflare 仅在其获得 cf_clearance 时所用的 User-Agent 下承认该 cookie,因此后续对该主机的 HTTP 请求会发送已保存的 User-Agent,除非 --ua 覆盖它。
使用 --no-cache 可在不保存 cookie 的情况下获取,或删除该主机的文件以丢弃它们。过期或被拒绝的 cookie 需要重新挑战。
$ nix develop # Go, gopls, Chromium, treefmt
$ go test ./... # Go unit tests
$ nix build # Packaged CLI
$ nix flake check # Builds, tests, and formatting
$ nix fmt # Format Go and Nix