
크롤러의 이름이 아닌 검증에 집중하기: 웹봇 인증, IP 체크 및 세 번째 관문
요약
AI 크롤러를 식별하고 차단하는 과정에서 User-Agent 위조 문제를 해결하기 위한 검증 전략을 다룹니다. 단순한 이름 확인을 넘어 IP와 DNS를 활용한 정교한 인증 모델을 제안합니다.
핵심 포인트
- User-Agent는 위조가 가능하므로 크롤러 식별의 유일한 수단이 될 수 없음
- IP 기반 검증 시 역방향 DNS 조회를 통해 호스트네임을 확인해야 함
- 확인된 호스트네임이 다시 원래의 IP로 정방향 확인(Forward-resolve)되는지 검증 필수
2주 전, 저는 서버 로그에서 AI 크롤러가 403 에러를 받는 것을 확인하라고 사람들에게 말했습니다. @wrencalloway는 당연한 다음 질문을 던졌습니다. '좋아요, 차단하는 방법은 찾았는데, 어떻게 하면 올바른 크롤러만 통과시키고 모두를 들여보내지 않을 수 있을까요?'
이것이 바로 그 게시글이며, 솔직히 말해 그는 이 글의 공동 작성자입니다. '세 개의 관문 모델', '정체성은 의도가 아니다'라는 틀, IP 화이트리스트를 무너뜨리는 순환 문제: 이 모든 것은 저희 스레드에서 가져온 것이고, 저는 작성을 했습니다. 생각하는 과정 자체가 두 사람의 작업이었습니다. 모두에게 공로를 돌립니다.
미리 말씀드리자면, 이것을 제 개인 에지(edge)에 아직 배포한 적은 없습니다. 제대로 구현하기 위한 연구 단계입니다. 만약 이 내용을 프로덕션 환경에서 사용하신다면, 댓글에서 제가 무언가를 배우게 될 것입니다.
사실은 두 가지 질문인 하나의 문제
AI 크롤러가 여러분의 콘텐츠에 도달하기를 원한다면 — 그것이 ChatGPT, Perplexity, Gemini 등에서 인용되는 방법입니다. 하지만 인터넷상의 모든 스크래퍼가 그 뒤를 따라 들어오기를 원하지는 않습니다.
'좋은 것만 들여보내고 나쁜 것은 막는다'는 한 가지 작업처럼 들립니다. 하지만 그것은 두 가지이며 서로 충돌합니다. GPTBot을 위해 문을 더 넓게 열면, GPTBot이라는 헤더를 입력할 의향이 있는 모든 것에 대해 문을 연 것입니다. 닫으면, 여러분이 나타나려고 했던 답변들에서 사라지게 됩니다.
문제 전체는 정체성(identity)에 있습니다: 요청이 주장하는 크롤러가 정말로 그 크롤러로부터 온 것인지 어떻게 알 수 있을까요? 아래의 모든 내용은 이 질문에 대한 세 가지 점진적으로 더 솔직한 답변입니다.
답변 1 - 이름 (그리고 왜 가치가 없는지)
게으른 해결책: User-Agent에 GPTBot이 포함된 것은 무엇이든 허용합니다.
User-Agent는 문자열일 뿐입니다. 누구나 입력할 수 있습니다. 스크래퍼가 자신을 GPTBot으로 표시하고, 통과하며, AI 가시성을 위한 여러분의 제스처는 이제 정확히 막으려고 했던 트래픽에 대한 열린 문이 됩니다.
이름은 정체성이 아닙니다. 그것은 주장일 뿐입니다. 방문자가 위조할 수 없는 무언가가 필요합니다.
답변 2 - 출신지 (IP)
더 나은 방법: 요청이 실제로 어디에서 왔는지 확인하는 것입니다. 제대로 수행한다면, 이는 단순한 IP 조회가 아니라 두 단계의 DNS 과정입니다:
- 요청한 IP를 역방향 DNS (Reverse-DNS) 조회 → 호스트네임(hostname) 획득
- 해당 호스트네임이 벤더(vendor)의 소유인지 확인 -
*.crawl.openai.com,*.anthropic.com,*.perplexity.ai,*.googlebot.com - 해당 호스트네임을 정방향 확인 (Forward-resolve) → 반드시 원래의 IP를 반환해야 함

스크래퍼는 호스트네임을 사칭할 수 있습니다. 하지만 벤더의 DNS가 자신의 IP로 정방향 확인(forward-resolve)되도록 만들 수는 없습니다. 양방향이 모두 일치해야 합니다.
일부 벤더는 대조를 위해 원시 범위(raw ranges)를 공개하기도 합니다:
- OpenAI - gptbot.json, searchbot.json, chatgpt-user.json
- Perplexity - perplexitybot.json, perplexity-user.json
- Google - crawler ranges
기원이 깨지는 지점 - 세 가지 균열, 모두 작지 않음
모두가 공개하는 것은 아닙니다. 이 부분은 저를 놀라게 했습니다: Anthropic은 ClaudeBot을 위한 IP 범위를 공개하지 않습니다. 그들의 문서에 있는 IP들은 크롤러가 아닌 Claude API를 위한 것입니다. ClaudeBot을 식별하기 위한 그들 자체의 가이드는 User-Agent와 *.anthropic.com에 대한 역방향 DNS(reverse-DNS) 확인입니다. 따라서 가장 큰 세 가지 크롤러 중 하나에 대해서는
순환 (Rotation). 이것은 @wrencalloway가 언급한 허점이며, 가장 날카로운 지점입니다:
오래된 허용 목록 (allowlist)과 20분의 403 오류 창(window)은 모두 실질적인 비용이며, "JSON을 더 자주 폴링(poll)하면 된다"는 말은 폴링 자체가 필요하지 않았어야 할 설계에 붙이는 임시방편(band-aid)일 뿐입니다.
발표된 모든 IP 범위는 움직이는 타겟의 스냅샷일 뿐입니다. 벤더(vendor)는 IP를 순환(rotate)시키거나 새로운 블록을 늦게 배포하며, 당신은 이미 틀려버린 허용 목록(allowlist)과 정당한 크롤러가 403 오류를 겪게 되는 시간 사이에서 선택해야 합니다. 당신은 더 이상 신원을 검증하는 것이 아닙니다. CIDR 블록을 보살피고(babysitting) JSON이 최신 상태이기를 바랄 뿐입니다.
답변 3 - 증명 (Web Bot Auth)
이 지점은 신뢰 모델이 단순히 까다로워지는 것이 아니라 형태 자체가 변하는 곳입니다.
Web Bot Auth - Cloudflare가 주도하는 IETF 초안 (draft-meunier-web-bot-auth-architecture, RFC 9421 HTTP Message Signatures 기반) -는 각 크롤러가 **Ed25519 키로 자신의 요청에 서명(sign)**하도록 합니다. 공개 키(public key)는 벤더 자체 도메인의 잘 알려진 디렉토리(well-known directory)에 존재합니다. 당신은 서명을 검증합니다. 신원은 패킷이 어디에서 왔는지로부터 추론하는 것이 아니라, 암호학(cryptography)에 의해 증명됩니다.
이 변화가 핵심입니다: _"이 연결이 어디에서 시작되었는가"_에서 _"당신이 키를 보유하고 있음을 증명할 수 있는가"_로의 전환입니다. 이는 순환(rotation) 상황에서도 살아남습니다. 요청이 어느 데이터 센터에서 출발했는지는 상관하지 않습니다. 보살펴야 할 CIDR도, 폴링해야 할 JSON도 없습니다.
이 기술은 실재하며 빠르게 움직이고 있습니다:
- Signed Agents 디렉토리를 포함한 Cloudflare의 Verified Bots 프로그램에 통합됨
- ChatGPT의 에이전트가 2025년 첫 번째 서명 코호트(signed cohort)에 포함됨
- AWS WAF가 2025년 말에 Web Bot Auth 지원을 추가하여 검증된 에이전트를 자동으로 허용함
솔직한 상태를 말씀드리자면: 승인된 표준(ratified standard)이 아닌, 활발히 논의 중인 IETF 초안(draft) 단계입니다. 하지만 Cloudflare, OpenAI, Anthropic, AWS가 발맞추어 움직이고 있으므로, 이는 이미 사실상의 표준(de-facto) 방향입니다.
증명이 깨지는 지점
이는 실제로 서명(sign)을 하는 크롤러들에게만 도움이 됩니다. 그리고 당신이 가장 차단하고 싶어 하는 스크레이퍼(scrapers)들은 정확히 이 방식을 절대 채택하지 않을 이들입니다. 서명은 정직한 자를 검증합니다. 부정직한 자들에게는 아무런 효과가 없습니다.
그렇다면 왜 서명이 승리할 때까지 그냥 기다리지 않는 걸까요?
서명이 해결하는 질문이 보기보다 훨씬 좁은 범위이기 때문입니다. 여기 @wrencalloway가 도달한 재정의(reframing)가 있는데, 이는 우리 스레드 중 가장 날카로운 통찰입니다.
서명은 질문을 "당신은 누구인가"에서 "당신은 무엇을 하고 있는가"로 옮깁니다.
이 문장을 곱씹어 보십시오. 유효한 서명은 정체성(identity)을 증명할 뿐, 의도(intent)를 증명하지는 않습니다. 운 나쁜 하루를 보내고 있는 합법적인 크롤러와 탈취된 키를 사용하는 공격자는 서명 계층(signature layer)에서는 동일하게 행동합니다. 둘 다 유효한 서명을 제시하기 때문입니다. 검증은 당신에게 "이름"을 건네줍니다. 하지만 그 이름을 가진 자가 현재 초당 400개의 요청으로 당신의 오리진(origin)을 두들기고 있는지에 대해서는 아무것도 말해주지 않습니다.
이는 다른 모든 것들의 밑바탕에 항상 존재하는 기본 요소가 있다는 것을 의미합니다. 바로 행동(behaviour)입니다. 속도 제한(Rate limits), 요청 패턴(request patterns), 클라이언트가 문을 통과한 후 무엇을 시도하는지 등이 그것입니다. 검증은 당신에게 이름을 가져다줍니다. 행동은 그 이름이 계속해서 이름답게 행동할 수 있을지를 결정합니다.
모델: 하나의 관문이 아닌 세 개의 관문
세 가지 답변을 순서대로 배치하면 그것들은 서로 경쟁하지 않고 쌓이게 됩니다.
- 서명되었는가? 서명을 검증합니다 → 빠른 경로(fast-path)로 처리합니다. (웹봇 인증 (Web Bot Auth) - 증명)
- 서명되지는 않았지만, 알려진 크롤러라고 주장하는가? 역방향 DNS(Reverse-DNS) + 순방향 확인(forward-confirm), 또는 공개된 IP 대역을 확인합니다. (IP - 오리진)
- 어느 관문이든 통과했다면 - 이제 지켜보십시오. 속도 제한과 행동 패턴을 모든 대상에 대해 항상 가동합니다. (기본 요소)

@wrencalloway는 이를 _대체(replacement)가 아닌 추가(additive)_라고 표현했으며, 일단 이 관문들을 이해하고 나면 그 이유가 명확해집니다. 서명(Signatures)은 IP 계층을 대체하는 것이 아니라, 그 폭발 반경(blast radius)을 축소합니다. 서명을 하는 정직한 크롤러들은 상황에 따라 판단할 수밖에 없었던 대상군(pool)에서 벗어나게 됩니다. 그렇게 되면 'IP와 분위기(vibes)'로 판단해야 하는 관문에 남는 대상은 더 작고 지저분해집니다. 즉, 대부분 악의적인 행위자(bad actors)들로 구성된 집단이 되며, 이 집단에 대해서는 훨씬 더 공격적으로 대응하기가 훨씬 수월해집니다. 그리고 이 모든 관문 뒤에서 행동(behaviour)은 결코 감시를 멈추지 않습니다. 정체성(identity)은 결코 의도(intent)와 같은 것이 아니기 때문입니다.
세상이 따라잡는 동안 가짜를 식별하기
서명이 보편화되기 전까지, 대부분의 작업은 User-Agent 거짓말쟁이를 잡아내는 것입니다. 그 징후들은 일관적입니다:
- 벤더 일치 항목이 없는(no vendor match) 일반 호스트(Hetzner, OVH, DigitalOcean)로 역방향 조회(Reverse-resolves)됨
- NXDOMAIN - 역방향 DNS(reverse-DNS)가 전혀 없음
/admin,/.env,/wp-login으로 직행함 - 실제 크롤러는 비밀 정보가 아닌 콘텐츠를 읽습니다.- 분당 수백 개의 요청을 보내며, 크롤링 지연(Crawl-Delay)이 없음
- 이름에 오타가 있음:
GPT-Bot또는 존재하지 않는 버전(ClaudeBot/2.x)
이 중 어느 하나도 단독으로는 증거가 될 수 없습니다. 하지만 이들이 모이면 배지를 달고 있는 스크래퍼(scraper)가 됩니다.
내가 얻은 교훈
이 전체적인 단계는 하나의 아이디어가 스스로에게 더 정직해지는 과정입니다:
- **이름(The name)**은 방문자에게 자신을 식별할 것을 요구합니다. 문자열(string)을 신뢰합니다.
- **오리진(The origin)**은 그들이 어디서 왔는지 묻습니다. 순환되거나 공개되지 않는 주소(address)를 신뢰합니다.
- **증명(The proof)**은 그들이 키(key)를 보유하고 있는지 증명할 것을 요구합니다. 수학(math)을 신뢰하지만, 이는 오직 '누구(who)'에 대해서일 뿐, '무엇(what)'에 대해서는 아닙니다.
각 관문은 신뢰를 방문자가 속일 수 없는 무언가에 더 가깝게 이동시킵니다. 하지만 그 어떤 것도 결승선은 아닙니다. 결승선이란 존재하지 않기 때문입니다. 완벽한 정체성조차 의도에 대해서는 아무것도 알려주지 않습니다. 가능한 곳에서는 증명(proof)을 통해 검증하고, 불가능한 곳에서는 오리진(origin)을 통해 검증하며, 모든 이들에 대해서는 행동(behaviour)으로 방어선을 유지해야 합니다. 이름은 결코 선량한 행동을 약속하는 것이 아니었기 때문입니다.
저는 아직 이것을 구축하지 않았습니다. 구축하게 된다면, 시그니처(signatures)를 최우선으로 하고, IP를 보조 수단(fallback)으로 사용하며, 그 밑바탕에는 행동(behaviour)을 두겠습니다. 그리고 무엇이 망가졌는지에 대해 기록할 것입니다. 왜냐하면 항상 무언가는 망가지기 때문입니다. 만약 여러분이 이미 이를 실행하고 있다면, 제가 무엇을 과소평가하고 있는지 알려주세요. 지난번에도 정확히 그런 방식으로 이 포스트가 작성되었습니다.
관련 읽을거리:
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기