
curl과 비슷하지만 Anubis 및 Cloudflare 봇 차단을 우회합니다.
$ nix run github:fzakaria/anubis-fetch -- https://lore.kernel.org/linux-mm/some-thread/T/
Anubis 작업 증명(PoW) 방어벽과 Cloudflare 핑거프린트 검사 뒤에 있는 URL을 가져오는 빠른 (Go) CLI — 챌린지를 프로세스 내부에서 해결하고, 정말 필요할 때만 실제 브라우저를 사용합니다.
점점 더 많은 사이트 — lore.kernel.org, GNOME, kernel.org 등 — 가 Anubis 뒤에 있습니다. 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)를 발급합니다. 브라우저는 다음 방문 때 다시 챌린지를 받지 않으며, 우리도 마찬가지입니다. 쿠키는 호스트별로 저장됩니다(쿠키 저장 참고).req를 통해 나가며 — 동일한 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}}
이를 해결하려면 hex(sha256(randomData ‖ nonce))가 difficulty 개수의 0으로 시작하도록 하는 nonce를 찾아야 합니다(nonce는 10진수 문자열입니다). 그런 다음 답을 다시 제출합니다:
GET /.within.website/x/cmd/anubis/api/pass-challenge?id=…&response=<hash>&nonce=<n>&redir=<url>&elapsedTime=<ms>
…그러면 인증 쿠키가 설정되고 실제 페이지로 리다이렉트됩니다. 난이도 4(lore/kernel.org/GNOME의 기본값)는 약 65k 해시이며 — Go에서는 1밀리초 미만입니다.
직접 실행:
$ nix run github:fzakaria/anubis-fetch -- <url>
프로필에 설치:
$ 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
| 플래그 | 설명 |
|---|---|
--text | HTML 대신 읽기 쉬운 일반 텍스트로 렌더링 |
--timeout MS | 단계별 타임아웃(밀리초, 기본값 30000) |
--ua STRING | User-Agent 재정의 |
--browser | 솔버를 건너뛰고 바로 헤드리스 브라우저 사용 |
--no-browser | 브라우저를 절대 사용하지 않음. 솔버로 처리할 수 없으면 종료 코드 3 반환 |
--no-cache | 영구 쿠키 저장소를 읽거나 쓰지 않음 |
# 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"
가져오기가 성공하면 인증 쿠키가 $XDG_CACHE_HOME/anubis-fetch/cookies/<host>.json에 저장됩니다(~/.cache/…로 폴백). 해당 호스트에 대한 다음 실행은 작업 증명이나 브라우저 없이 바로 통과합니다 — 브라우저 재방문과 정확히 동일합니다. 브라우저 폴백으로 얻은 쿠키도 저장되므로, 이후 실행에서는 빠른 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"))에 고정되어 있어, 해시 구성이 변경되면 조용히 잘못된 결과를 반환하는 대신 단위 테스트가 실패합니다.