메뉴
HN
Hacker News • 16일 전

Read the Docs 대규모 DDoS 공격 분석

IMP
7/10
핵심 요약

문서 호스팅 플랫폼 Read the Docs가 2026년 6월 약 10일간 지속된 사상 최대 규모의 정교한 DDoS 공격을 받았습니다. 분당 550만 요청(평소의 약 100배)이 수백 개 네트워크의 수백만 개 IP에서 동시에 유입되었고, 공격자는 캐시 우회와 TLS/헤더 무작위화, 방어 적응 행동까지 보였습니다. AI 크롤러 증가 이후 인프라 커뮤니티 전반이 겪는 트래픽 남용 문제의 심각성을 보여주는 사례입니다.

번역된 본문

홈 / 블로그 / 엔지니어링 / Read the Docs를 겨냥한 최근 DDoS 공격의 이해

Read the Docs를 겨냥한 최근 DDoS 공격의 이해 2026년 9월 8일 | 태그: ddos, security, infrastructure, performance, cloudflare, terraform David Fischer

2026년 6월 공격 데이터 분석

2026년 6월 중순부터 하순까지, Read the Docs는 역사상 가장 크고 정교한 분산 서비스 거부(DDoS) 공격을 경험했습니다. 최고치에서는 인프라가 분당 550만 개 이상의 요청을 받았으며, 이는 정상 기준 트래픽의 약 100배에 해당합니다. 이 사고는 거의 열흘간 지속되면서 우리의 인프라, 엣지 방어 체계, 사고 대응 프로세스를 시험했습니다.

과거에 봤던 단순한 트래픽 폭주와 달리, 이번 공격은 더 분산되어 있었고 우리의 방어에 빠르게 적응했으며, 의도적으로 캐싱을 우회하는 영역을 공략했습니다. 이제 우리의 소규모 운영 팀이 다시 정상 시간에 잠들 수 있게 되었으므로, 이런 유형 공격의 구조, 기존 레이트 리미팅(속도 제한)이 부분적으로만 완화에 성공한 이유, 그리고 공격 내내 가용성을 (거의) 유지하는 데 실제로 도움이 된 전략을 살펴보고자 합니다.

DDoS 공격의 진화

Read the Docs는 역사적으로 문서를 스크래핑하는 스파이더와 봇에 매우 관대했으며, IP 기반 레이트 리미팅만으로 대부분의 남용 문제를 해결할 수 있었습니다. 약 2년 전부터 AI 크롤러가 보편화되면서 트래픽이 크게 증가하기 시작했고, 개발 인프라 커뮤니티의 다른 구성원들도 비슷한 문제를 겪고 있는 것으로 보입니다. AI가 생성한 스크래퍼를 프록시 네트워크에 연결하는 것은 어렵지 않게 되었습니다. 우리의 방어는 이에 비교적 쉽게 적응했지만, 6월 공격은 지금까지 직면했던 어떤 것보다 10배 이상 컸습니다.

이번 공격의 주요 특징은 다음과 같았습니다:

  • 대규모 볼륨: 최고치에서 분당 550만 개의 요청을 받았으며, 평일 정상 최고치는 분당 10만 개 미만이었습니다.
  • 전 세계적 분산: 전 세계 수백 개 네트워크(ASN)에 걸친 수백만 개의 고유 IP 주소에서 악성 요청이 발생했습니다. 주거용 IP 대역과 대형·소형 호스팅 업체 모두 포함되었습니다.
  • 헤더 및 TLS 무작위화: 공격자는 시그니처 기반 필터(JA3/JA4)를 우회하기 위해 HTTP 요청 헤더와 TLS 연결 매개변수를 체계적으로 무작위화했습니다.
  • 자동화된 CDN 방어의 한계: Read the Docs는 Cloudflare를 사용하며, Cloudflare의 자동 DDoS 방어가 이들이 '알려진 봇넷'이라 부르는 출처의 일부 트래픽을 차단했지만, 공격의 상당 부분은 1차 검사를 통과해 우리의 레이트 리미팅과 WAF 규칙까지 도달했습니다.
  • 캐시 우회: 공격자는 캐시 미스를 유발하는 URL, 즉 고유한 경로의 존재하지 않는 페이지(404)와 임시 리다이렉트(302)를 찾아 의도적으로 공략했습니다.
  • 적응적 행동: 우리가 차단이나 레이트 리미팅을 적용하면, 봇넷은 요청 속도를 조정하고 서로 다른 대상 경로를 순회하며 트래픽을 더 넓은 IP 풀에 분산시켜 우리의 방어 경계를 탐색했습니다.

규모와 광범위함

과거의 소규모 DDoS 공격이나 대규모 분산 스크래퍼는 보통 어느 정도 집중되어 있었습니다. 요청이 소수의 국가에서, 소수의 IP 대역에서, 또는 소수의 브라우저 시그니처에서 발생하는 식이었습니다. 이번 공격은 진정으로 전 세계적이었습니다. 모든 국가에서 동시에 공격이 왔는데, 이는 Cloudflare 콜로(colo)별로 레이트 리미팅 규칙을 적용할 때 악몽과 같은 상황입니다. 단일 IP나 서브넷에서 합리적인 속도로 스크래핑하는 합법적인 봇에는 영향을 주지 않으면서 분산 공격을 제한하는 규칙을 만들기 어렵기 때문입니다.

한 시점에서 공격자가 리다이렉트에 집중했을 때, 단순한 rewrite regex 디렉티브로 하드코딩된 Nginx 리다이렉트에 과도한 트래픽을 쏟아부어, 수평 확장 인프라에서조차 요청이 유실되는 상황이 발생했습니다. 그런 Nginx 리다이렉트는 쉽게 초당 수천 개의 요청을 처리할 수 있는 것인데도 말입니다.

전 세계로 퍼지는 것 외에도, 공격은 Read the Docs의 여러 서비스를 동시에 공격했습니다. 공개 커뮤니티 문서가 공격 [원문 중단]

원문 보기
원문 보기 (영어)
Home / Blog / Engineering / Understanding the Recent DDoS Attack Against Read the Docs Understanding the Recent DDoS Attack Against Read the Docs Sep 8, 2026 Tagged ddos security infrastructure performance cloudflare terraform David Fischer Analytics from the June 2026 attack In mid-to-late June 2026, Read the Docs experienced the largest and most sophisticated distributed denial-of-service (DDoS) attack in our history. At its peak, our infrastructure was hit with over 5.5 million requests per minute , about 100 times our normal baseline traffic. The incident lasted for nearly ten days, testing our infrastructure, our edge defenses, and our incident response processes. Unlike simpler traffic floods we've seen in the past, this attack was more distributed, it adapted to our defenses rapidly, and it purposefully attacked areas that bypassed caching. Now that our small ops team is back to sleeping at normal hours, we wanted to walk through the anatomy of this kind of attack, why our existing rate limiting only partially mitigated it, and what strategies actually helped us (mostly) maintain availability throughout the attack. Evolution of DDoS attacks Read the Docs has historically been very tolerant toward spiders and bots scraping documentation we host, and IP-based rate limiting solved most abuse problems. Starting about two years ago, we began seeing a significant uptick as AI crawlers became more prevalent and it seems other members of the dev infrastructure community are seeing similar issues. It became straightforward to plug an AI-generated scraper into a proxy network. Our defenses adapted to that fairly easily, but the June attack was over 10x larger than anything we had faced. Key characteristics of this attack included: Massive volume : At peak, we received 5.5 million requests per minute , compared to our normal daily peak of under 100k requests per minute. Global distribution : We saw malicious requests originating from millions of unique IP addresses across hundreds of networks (ASNs) globally. This included residential IP blocks as well as major and minor hosting providers. Header & TLS randomization : The attackers systematically randomized HTTP request headers and TLS connection parameters to evade signature-based filters (JA3/JA4). Limitations of automated CDN defenses : Read the Docs uses Cloudflare and while Cloudflare's automated DDoS protection mitigated some traffic originating from what they called "known botnets", a big part of the attack passed that first check and got through to our rate limiting and WAF rules. Cache evasion : Attackers found and deliberately targeted URLs that resulted in cache misses, such as non-existent pages with unique paths (404s) as well as temporary redirects (302s). Adaptive behavior : When we implemented blocks or rate limits, the botnet adjusted its request rates, rotating through different target paths and spreading traffic across broader IP pools to probe our defense boundaries. Scale and breadth Previous minor DDoS attacks or large distributed scrapers we'd seen were typically concentrated in some way. The requests either originated from a small set of countries, or a small set of IP blocks, or they had a small set of browser signatures. This attack was truly global. It came from every country all at once, which is a nightmare when rate limiting rules are applied per Cloudflare colo. It's hard to craft rules that can limit a distributed attack while not hitting legitimate bots scraping at a reasonable rate from a single IP or subnet. At one point when the attackers focused on redirects, they were overwhelming a hardcoded Nginx redirect (a simple rewrite regex directive) with enough traffic to cause dropped requests even on horizontally scaling infrastructure. An Nginx redirect like that can easily handle thousands of requests per second. In addition to spreading across the globe, it also attacked multiple Read the Docs properties. Public community documentation was attacked as well as our commercially hosted docs. We also saw attackers try to take down our author-facing dashboards that require logins. While it was an option (Cloudflare's "Under Attack Mode") to simply give every site visitor, legitimate or otherwise, a JavaScript challenge, we didn't want to do that. This would break every API integration and cause lots of friction for the hundreds of thousands of real docs readers. Instead, we relied on rate limiting and targeted challenges combined with more caching and pushing more features out to the edge. “There's no way we could have handled this attack without Cloudflare.” Adapting to our defenses Read the Docs uses Cloudflare heavily for caching and rate limiting, and there's no way we could have handled this attack without Cloudflare. We have dozens of rate limiting rules (managed through Terraform ) to protect our infrastructure based on IPs, on the thousands of hostnames and hundreds of thousands of subdomains Read the Docs hosts, on ASNs, browser fingerprints, and on combinations of all of these. The attack started on a small number of domains where attackers discovered temporary redirects (302) that were not cached at the edge and were served by our Python backend rather than something like Nginx. Within a few minutes, our operations team had been paged due to a short outage (users may not always notice our outages because cached documentation keeps serving), and within half an hour or so we had moved these redirects to be served at the edge by Cloudflare instead of our servers. We thought that might be the end of it, but instead the attackers tried different tactics across various hosts and services for another week and a half. Analytics showing oscillating "Yo-Yo" traffic levels during the attack. Attackers would ramp up to discover our rate limit thresholds and then back off to let the rate limit windows expire. This is called a yo-yo pattern, and it's designed to maximize the financial costs of auto-scaled infrastructure and cause intermittent service degradation. The attackers knew we were running a web app firewall (WAF) with rate limits and knew how to cause as much damage as possible in spite of that. Defending against volumetric DDoS attacks Defending against multi-million request-per-minute floods requires a defense-in-depth approach with edge caching, web app firewalls, rate limiting, local caches, and request fingerprinting. The fastest request is the one served by the CDN or the web app firewall. Edge caching The first line of defense, and one we were already using heavily, is a proper CDN and ensuring that as few requests as possible hit origin servers. Serving docs from a CDN has a lot of benefits. For Read the Docs, where docs sites change infrequently, we cache fairly aggressively but purge the cache for a particular docs site whenever new documentation is pushed to git and rebuilt. CDNs also make fetching documentation much faster for people geographically further away from our origin servers. However, attackers probing our defenses quickly discovered which requests were cached and which ones weren't by how fast the CDN responded. This means that finding just a few requests that aren't cached gives attackers an angle of attack. We are still finding more paths and endpoints that aren't cached, but even very short-lived cached responses (using the Cache-Control header ) for both redirects and normal 200 responses will help with this kind of attack. A Slack notification when Read the Docs is getting 45k uncached reqs/min. Without caching and rate limiting, auto-scaling infrastructure will just scale out to handle the load at our expense. Rate limiting and fingerprinting Since we didn't want to give a JavaScript challenge to all users, we used targeted rate limiting rules combining bot probability scores with per-IP rate limits to challenge suspicious traffic while letting legitimate users and well-behaved bots browse uninterrupted. Everyone who has solved a JavaScri