원문 캡처 · jpb.dev
원문 캡처 · jpb.dev

MacBook Pro에서 GPU 풀이기를 만들어 Anubis의 작업증명 과제를 풀었다. 난이도 6 과제를 푸는 데 약 5밀리초가 걸렸고, 과제를 가져와 로컬 HTTP 서비스에서 계산하고 결과를 제출한 뒤 보호된 페이지를 여는 전체 과정은 약 19밀리초였다. 같은 노트북의 Chrome에서는 같은 과제를 푸는 데 평균 약 22초가 걸렸고, iPhone 17 Pro Max에서는 거의 3분이 걸렸다. 풀이기는 최신형 아이폰보다 약 3만 배 빨랐다.

Anubis는 AI 기업의 스크래핑에 대응하는 수단으로 소개된다. README는 트래픽으로부터 소규모 사이트를 보호한다고 설명한다. 여기서는 이 위협 모델을 살펴봤다.

인터넷을 괴롭히는 봇이 AI 기업의 학습 데이터 수집에서 비롯됐다는 주장이 많다. 이 글에서는 그 주장을 논쟁하지 않고 사실이라고 가정한다. 대형 AI 모델을 만드는 기업이 문제라면, 이들은 막대한 컴퓨팅 자원을 이용할 수 있다. 예를 들어 메타는 2024년에 각각 H100 GPU 24,576개를 갖춘 클러스터 두 곳을 소개했다.

이 GPU들이 놀고 있다거나 작업증명 과제를 푸는 데 가장 적합하다고 말하는 것은 아니다. 다만 그런 수준의 엔지니어링 예산을 가진 조직과 일반 방문자가 컴퓨팅 경쟁을 벌이도록 하는 것이 바람직한지 의문이 든다.

Anubis의 작업증명 측정 방식

실험에서는 Anubis v1.28.2로 Nginx가 제공하는 정적 HTML 페이지를 보호했다. 모든 방문자에게 난이도 6의 fast 작업증명 과제를 설정했다.

난이도 6이 모든 Anubis 방문자에게 적용되는 기본 과제는 아니다. 포함된 정책은 의심 점수에 따라 난이도 2와 4를 포함해 다르게 대응하며, 난이도 6은 설정된 가장 높은 단계다. 더 많은 계산이 필요한 과제가 어떤 결과를 낳는지 보기 위해 난이도 6을 선택했다. 포함된 정책

과제는 다음 조건을 만족하는 논스(nonce), 즉 숫자를 찾는 것이다.

SHA256(challenge_data + decimal_nonce)

결과가 지정된 개수만큼 16진수 0으로 시작해야 한다. 0이 여섯 개면 24비트가 0이어야 하므로, 새 해시 하나가 조건을 만족할 확률은 약 1,677만 분의 1이다. 난이도가 한 단계 오를 때마다 기대 작업량은 16배가 된다. 검증 구현

브라우저가 직접 계산해야 한다는 조건은 없다. 서버는 해답을 받아 검증한다. 클라이언트는 과제를 받아 다른 곳에 계산을 맡긴 뒤, 적절한 쿠키와 연결 식별 정보를 유지하면서 답을 제출할 수 있다.

SHA-256을 깨거나 영리한 논스를 예측하거나 검증 오류를 악용한 것은 아니다. Anubis가 요구한 계산을 더 빠르게 수행하도록 적합한 구현을 사용했다.

Hashcat만으로는 부족했다

처음에는 Hashcat을 사용했다. 기본 SHA-256 모드는 정확히 일치하는 해시를 찾기 때문에, 여섯 개의 앞자리 0을 허용하도록 커널을 조금 수정한 별도 복사본을 만들었다.

Apple M5 Max의 40코어 GPU에서 이 버전은 초당 약 3억8,200만~3억9,300만 해시를 처리했다. Anubis는 이 방식으로 나온 해답을 정상적으로 받아들였다. 순수 해시 계산 속도만 보면 같은 노트북에서 Chrome을 사용하는 것보다 이미 400배 빨랐다.

그러나 과제를 처리할 때마다 Hashcat을 실행하면 초기화와 자동 튜닝 때문에 반복 실행에서도 약 1.72초가 걸렸다.

개념 증명으로, 로컬 HTTP API와 크기 제한이 있는 대기열을 앞에 둔 상시 실행형 네이티브 Metal 작업자를 만들었다. 작업자는 컴파일된 GPU 파이프라인과 버퍼를 작업 사이에도 유지한다.

또 다른 최적화도 적용했다. 과제에는 고정된 ASCII 128바이트 뒤에 논스가 붙는다. SHA-256은 64바이트 블록 단위로 처리하므로 첫 두 블록은 과제마다 같다. 작업자는 이 시작 블록을 한 번 계산한 뒤, GPU가 논스와 패딩이 들어 있는 마지막 블록만 처리해 탐색하도록 했다. 이 최적화로 해시 하나를 계산하는 데 걸리는 시간을 약 66% 줄였다.

측정 결과와 비교

같은 노트북에서 얻은 최종 결과는 다음과 같다.

테스트평균 시간95백분위수과제 수
전체 메시지를 해시한 맞춤형 GPU 풀이기15.97 ms44.03 ms100
고정된 접두부를 재사용한 맞춤형 GPU 풀이기5.19 ms14.24 ms100
로컬 HTTP를 이용한 상시 실행 GPU 풀이기, 클라이언트 1개6.03 ms15.19 ms200
로컬 Anubis 처리 전체 과정19.02 ms26.85 ms20

더 긴 테스트에서는 서로 다른 과제 3,000개를 17.03초에 풀었다. 클라이언트 8개가 대기열에 과제를 넣었을 때 초당 176개를 처리한 셈이다. 각 해답을 Anubis에 확인시켰고 모두 승인됐다. 이 부하 테스트의 과제는 형식과 난이도는 같았지만 Anubis에서 가져온 것이 아니라 로컬에서 생성했다.

브라우저가 과제를 푸는 시간과 비교하면 차이가 크다. 앞서 설명했듯 같은 노트북의 Chrome은 같은 난이도 과제를 푸는 데 약 22초가 걸렸다. MacBook Pro에서 Chrome으로 과제 페이지를 시험했을 때 페이지에 표시된 해시 처리량은 초당 75만~76만 회였다. iPhone 17 Pro Max에서는 같은 페이지가 초당 10만~11만 회를 표시했고, 해결에는 거의 3분이 걸렸다.

풀이기는 초당 약 31억 해시를 처리했다. Anubis 과제를 푸는 속도는 최신형 아이폰보다 3만 배 이상 빨랐다. 이 풀이기의 소스 코드는 명백한 이유로 공개하지 않는다.

난이도를 올리면 일반 방문자에게 더 큰 부담이 간다

난이도를 6에서 7로 높이면 기대 작업량은 16배가 된다. 관측한 브라우저 속도로 계산하면 아이폰에서 평균 40분 이상 연산해야 한다. 측정한 GPU 처리량으로는 약 65밀리초가 걸린다.

난이도를 높여도 하드웨어 격차는 그대로다. 정당한 방문자와 준비된 스크레이퍼가 비용을 똑같이 부담하게 만들지는 못한다.

한편 보호 페이지를 가져오는 데 수십에서 수백 밀리초가 걸린다면, 5밀리초 계산은 상대적으로 작은 추가 비용일 수 있다. 스크레이퍼는 네트워크 요청과 다른 작업을 겹쳐 처리하고, 공유 풀이기가 새 과제를 풀도록 할 수 있다. 유효한 쿠키를 얻고 나면 다시 인증이 필요해질 때까지 이후 페이지 요청에서 과제 비용은 사라진다.

다른 작업증명 알고리즘과 공개 사이트 조사

여기까지는 난이도 설정만 바꾸고 Anubis의 기본 설정으로 실험했다. 적이 대규모 GPU를 보유한 상황에서 SHA-256은 작업증명 과제에 적합하지 않은 선택이다. 이런 종류의 가속을 어렵게 하려는 대체 작업증명 알고리즘이 있으며, Anubis는 이를 기본으로 지원한다.

Anubis는 Argon2id와 HashX를 지원한다. 같은 MacBook Pro에서 두 알고리즘을 시험해 이 글에서 활용한 속도 차이가 얼마나 달라지는지 살펴봤다. 평균 해결 시간은 다음과 같다.

알고리즘난이도Chrome네이티브 CPUGPU
Argon2id6비트233.45 ms86.85 ms83.39 ms
HashX20비트191.06 ms8.82 ms9.78 ms

네이티브 CPU와 GPU의 차이는 거의 사라졌다. 그러나 Chrome 밖에서 알고리즘을 실행하는 편이 여전히 더 빨랐다. 특히 HashX에서는 외부 서비스가 과제를 처리하는 데 이점이 있다.

그렇다면 Anubis를 사용하는 사이트는 모두 Argon2id나 HashX를 쓸까? SHA-256을 사용하는 기본 fast 알고리즘은 아무도 쓰지 않을까?

2026년 10월 24일, Anubis 사용을 공개적으로 알린 공개 웹사이트 15곳을 조사했다. 이 가운데 14곳은 확인 가능한 과제 설정을 반환했고, 모두 SHA-256을 사용했다.

사이트알고리즘난이도Anubis 버전
Linux kernel GitSHA-25651.26.2
Linux mailing-list archiveSHA-25641.26.2
FFmpeg TracSHA-25621.28.1
FreeBSD SVNSHA-25641.26.2
Sourceware GitSHA-25641.27.0
GCC BugzillaSHA-25641.27.0
freedesktop.org GitLabSHA-25621.27.0
OpenWrtSHA-25621.22.0-20250926
FreeCAD WikiSHA-25641.28.1
ScummVM WikiSHA-25631.27.0
Hosted WeblateSHA-25621.27.0
Valve Developer CommunitySHA-25641.23.1
NixOS Hydra과제 없음——
Haiku development trackerSHA-25621.28.2
Purism GitLabSHA-25641.28.1

이 결과는 상당히 놀라웠다. 조사한 사이트 15곳 중 14곳이 SHA-256을 사용했고, 나머지 한 곳은 과제를 제시하지 않았다. 일부 사이트 운영자가 AI 기업이 과제를 푸는 데 연산 자원을 쓰겠다는 생각을 믿기 어렵다고 말한 글을 읽은 터라 특히 의외였다. 알고리즘이 SHA-256이라면 봇 스크레이퍼가 과제를 푸는 일은 간단하다.

Anubis를 사용한다면 설정을 바꾸라고 권한다.

사용 중인 소프트웨어 버전을 그대로 공개하는 것도 좋지 않다. Anubis에 보안 취약점이 공개되면, 영향을 받는 버전을 실행하는 사이트를 찾아 공격하는 봇을 만들기가 매우 쉽다. 여기서 말하는 취약점은 봇 보호를 우회하는 정도의 사소한 문제가 아니다. Anubis는 서버 어딘가에서 실행해야 하는 인프라 구성요소다. Anubis에 취약점이 있으면 서버 전체를 장악하는 진입점으로 악용될 수 있다. Anubis에서 버전 공개를 끄는 설정은 찾지 못했으므로, 이 점은 사이트 운영자에게 책임을 묻지 않겠다.

Anubis를 어떻게 봐야 하나

Anubis는 꽤 괜찮은 소프트웨어라고 생각한다. 제대로 사용하면 일부 봇을 막을 수도 있다. 하지만 실제 사이트에서는 설정이 잘못된 경우가 분명히 보인다. 앞서 말했듯 AI 기업과 연산 경쟁을 하는 동안, 방문자는 금이 간 화면을 쓰는 8년 된 중고 휴대전화를 들고 있을 수도 있다. 특히 SHA-256을 사용한다면 AI 기업을 막기 전에 이용자를 불쾌하게 만들 가능성이 높다.

이 글에 사용한 HTTP 서비스는 Codex의 도움을 받아 만들었다. 이 서비스는 Anubis 과제를 매우 빠르게 푼다. GPT-6 Astra는 Daybreak 접근 권한 없이 중간 추론 설정으로 이를 만들었다. 사이버 보안 안전장치가 완화된 모델을 이용할 수 없는 사람도 이런 작업을 할 수 있다는 뜻이다. 안전장치를 우회하려고 Astra에 모호하게 요청한 것도 아니다. 스크레이퍼도 Anubis를 우회하기 위해 정확히 이런 방식을 쓰고 있다고 가정하는 편이 낫다.

보안 연구자는 아니며 보안에 관심이 있고 오랫동안 웹사이트를 만들어 왔다. 이 글의 주장에는 유보를 두고 읽어도 좋다. 물을 마시고 좋은 하루 보내길 바란다.