요약
HN에 글이 오른 뒤 사이트를 느리게 만든 주범은 사람이 아니라 봇이었습니다.
피드 리더 sprinklz.io를 만든 개발자 새미 스트라우스의 경험담입니다. HN 글이 추천 100개 남짓을 받은 뒤 사이트가 크게 느려졌고, 며칠이 지나도 오히려 나빠지자 원인을 직접 추적했습니다.
왜 중요한가
- 작은 사이트가 널리 알려지면 실제 방문자보다 자동화된 봇이 더 큰 부하를 만들 수 있음을 보여 줍니다.
- 접속 지표가 실제 사용자 수와 맞지 않았고, 요청을 경로별로 쪼개 보고서야 원인이 드러났습니다.
- 작성자는 봇 차단만이 아니라 사이트 자체를 빠르고 튼튼하게 만들어야 한다는 결론을 얻었습니다.
핵심 내용
- 전체 트래픽의 절반 가까이가 웹사이트 변경을 감시해 AI 뉴스레터로 요약하는 서비스 한 곳에서 나왔습니다.
- 이 서비스는 1분에도 여러 번씩 사이트를 조회했고, 작성자는 이름을 밝히지 않고 차단했습니다.
- 요청 대부분은 기사를 불러오지도, 화면을 그리는 자바스크립트를 실행하지도 않았습니다.
- 앤트로픽·오픈AI의 크롤러와 구글 검색 봇 말고도 워드프레스 파일을 뒤지는 취약점 스캐너가 있었습니다.
- AI 크롤러는 막고 검색 봇은 허용하는 robots.txt와 요청 속도 제한을 넣고 인프라도 손봤습니다.
HN 반응
- 여러 이용자가 비슷한 일을 겪었다며 AWS, Azure, Alibaba Cloud 같은 클라우드 대역을 통째로 막았다고 전했습니다.
- 반면 가정용 회선 IP를 계속 바꿔 쓰는 봇넷은 IP 차단이나 fail2ban(실패 요청이 잦은 IP를 막는 도구)으로 막기 어렵다는 지적이 이어졌습니다.
스팸, 악용, 공격적인 스크래핑이 너무 심해서 제 거의 모든 사이트에서 다음을 차단해야 했습니다.
그 밖에도 ASN 몇 개를 더 막았습니다. 단순한 스크래핑이라면 차라리 괜찮겠지만, 실제로는 에이전트를 동원한 악용인 경우가 많습니다. 취약점을 찾겠다고 스팸 요청을 보내거나(*), 값어치 있는 내용이나 동적인 내용이 거의 없는 페이지를 수백만 개씩 긁어 갑니다. 이런 클라우드 업체들은 자기네 영역에서 벌어지는 악용을 반드시 통제해야 합니다.
2년 전에 알리바바 클라우드를 차단했는데, 그동안 모든 경로가 4xx를 돌려주는데도 제 도메인 하나에 지금도 하루 100만 번씩 요청이 들어옵니다.
애플도 최근 몇 달 사이 스크래핑을 공격적으로 늘렸습니다. 다행히 robots.txt는 지키고 있습니다.
답답한 건 제 실제 사용자 중 일부가 회사 VPN을 통해 이런 클라우드를 거쳐 접속한다는 점입니다. 게다가 평판이 별로인 AI 스크래퍼 중에는 가정용 IP로 이루어진 전 세계 봇넷을 써서 긁어 가는 곳이 많습니다. 그래서 실제 사람에게 피해를 주지 않고 이들을 찾아내 차단하기가 더 어렵습니다.
* 유출된 .env 경로, 관리자 페이지 무차별 대입 같은 것들입니다.
적응도 안 하는 상대라면 그냥 패킷을 조용히 버리는 편이 낫겠네요.
Bing 봇도 똑같아요. 왜 그렇게까지 말을 안 듣는지 모르겠습니다.
마이크로소프트는 '동의'라는 걸 이해해 본 적이 없죠.
애플리케이션 차원에서 차단하는 건 아주 비효율적으로 보입니다. 이런 도메인은 네트워크(IP) 차원에서 막아야 합니다. 해당 도메인과 IP에서 들어오는 패킷은 그냥 버리고, 서버가 존재한다는 사실조차 확인해 주지 않도록 아무것도 돌려보내지 마세요.
지금은 Cloudflare에서 엣지 단계로 차단하고 있어서 애플리케이션에는 전혀 닿지 않습니다.
도메인 레지스트리 운영자 입장에서는 Cloudflare가 압도적으로 최악입니다.
Google DNS는 바쁘긴 해도 IP 수가 얼마 안 되고 그럭저럭 합리적입니다. 그런데 Cloudflare는 트래픽이 끝도 없이 계속 들어옵니다. 도대체 뭘 얻으려는 건지 모르겠습니다. 같은 Cloudflare IP에서 TCP 쿼리도 봤으니, 이게 그쪽이 DDoS 공격을 받아서 생긴 결과도 아닙니다.
오래전부터 패치 안 된 공유기나 데스크톱을 대량 스크립트로 뚫습니다.
Cloudflare 터널로 C&C를 구축합니다.
이렇게 해킹한 시스템을 가정용 프록시 엔드포인트로 국가 지원 해커부터 10대까지 아무에게나 팝니다.
그중 일부는 데이터 스크래핑 서비스일 겁니다.
ASN이나 IP로 막으려는 건 제 꼬리를 쫓는 일입니다. 잘해야 몇 달 통하겠죠.
신뢰망(web of trust)을 기반으로 한 평행 웹을 만들고 싶어지네요.
Cloudflare가 일을 아주 잘해요. 다른 VM에서 옮겨 보고 알았습니다.
인터넷을 통제하는 데는 확실히 그렇죠.
fail2ban으로 어떻게 해 볼 수는 없나요? 예를 들어 401이나 404 응답을 받는 요청이 몇 번 쌓이거나, 사람이라고 보기엔 너무 빠른 연속 요청이 들어오면 그 주소를 48시간 동안 차단하는 식으로요.
나중에 그 주소에서 정상 요청이 오더라도 아마 통과할 겁니다.
다만 수십만 개일 수도 있는 주소 목록을 iptables가 모든 연결마다 얼마나 잘 대조해 낼지는 잘 모르겠네요.
fail2ban은 가정용 IP 봇넷에는 잘 안 통합니다. IP 하나가 보통 요청을 두어 번 보내고 나면 바로 바뀌거든요.
ipset은 엄청나게 많은 주소도 처리할 수 있습니다. 요즘 fail2ban은 분명 ipset을 쓸 거예요.
작년에 저는 봇 트래픽을 zip 폭탄으로 처리한다는 글을 썼습니다0. 그 글이 웹 전체에 엄청나게 퍼졌고, 저는 후회하고 있습니다. 서버가 봇 트래픽에 완전히 압도당했거든요. 몇 달을 시달린 끝에 더 나은 전략을 찾아야 했는데, 그게 입을 다무는 것이었습니다.
작년에 당신 글을 읽고 그대로 적용해 봤습니다. 효과가 있는지 확인할 방법이 없어서 결국 접었습니다. 압축된 데이터에 압축도 미리 계산해 둔 거라 해도 그걸 내보내는 것 자체가 대역폭 낭비였습니다. 정상 사용자의 브라우저에 날아갈 수도 있었고요(오탐).
제 사이트의 가장 큰 문제는 봇이 CGIT 저장소를 때린다는 점입니다. 파일을 열 때마다 구문 강조 스크립트가 돌거든요.
그래서 상식 퀴즈 같은 방식을 도입했습니다. 정답을 맞히면 가능한 한 오래 유지되는 접근 쿠키를 주기 때문에, 정상 사용자는 최대한 적게 번거롭게 됩니다.
그러니까 결국 봇에는 눈에 띄는 영향이 없었다는 건가요?
소규모에서는 잘 먹혔습니다. 하지만 파리 몇 마리를 쫓는 것과 말벌 떼와 싸우는 건 전혀 다른 일이죠. 작은 digitalocean 드롭릿에서 1MB짜리 파일을 하루에 100만 번 내보내는 건 불가능합니다. 한마디로 확장이 안 됐습니다. 게다가 AI 봇은 보통 사양이 더 좋은 머신으로 오고, 폭탄을 맞아도 더 빨리 회복합니다.
왜 DigitalOcean에서 내보내신 건가요?
CDN을 쓰지 그랬어요?
페이지의 내용, 즉 원본 HTML 자체를 zip 폭탄으로 바꿔치기하는 방식이라서요. 예를 들어 https://example.com 이 악성 봇인지 확인한 다음, 결과에 따라 gzip으로 압축한 HTML이나 압축한 폭탄을 보냅니다. 그래서 CDN으로 바꾸거나 리디렉션할 수 없습니다. 봇은 리디렉션을 그냥 무시할 테니까요.
정말 성가시겠네요. 설명 감사합니다! 저도 새로 만든 작은 제품을 곧 출시하려는데, 지난번 제품도 봇에 시달렸거든요.
다행히 다른 분들이 겪은 것처럼 악의적인 수준은 아니었지만, 그래도 짜증스러웠어요.
그 기법을 패킷 압축에도 적용할 수 있나요?
저도 겪었습니다. 제 게임[1]이 사실상 위키백과 문서 수천 개를 그대로 미러링한 거라 클라우드 이그레스 요금이 크게 나왔어요. AI 봇이 모든 페이지를 마구 두드려 대서 캐시 적중률이 낮았습니다. [1] https://redactle.net (덤비세요, Claude)
https://github.com/borestad/blocklist-abuseipdb 에 올라 있는 모든 곳의 트래픽을 차단하시길 정말 권합니다.
공유해 주셔서 감사합니다. 편집증 있는 셀프 호스터로서 이미 잔뜩 갖춘 차단 목록에 이것도 추가할게요.
저도 여기 댓글에 제가 만든 온라인 게임 링크를 한 번 올렸는데, 곧바로 좋은 트래픽과 나쁜 트래픽이 온갖 종류로 몰려왔습니다.
제 작업을 좋아해서 LinkedIn에서 저를 찾아 긍정적인 메시지와 함께 연결 요청을 보낸 사람들도 있었습니다. 반면 어떻게든 SQL 인젝션이나 공격을 시도하고, 입력창이란 입력창에는 모조리 욕설을 남긴 사람들도 있었죠.
누군가는 사이트를 통째로 복사해서 몇 군데만 살짝 바꾼 자기 버전을 호스팅했습니다. 링크 하나를 지우지 않고 그대로 둔 덕에 그쪽 사본에서 유입되는 트래픽이 생겨서야 알았습니다.
이게 전부 HN 댓글 하나에서 벌어진 일이고, AI가 나오기 전의 일입니다. 워드프레스나 PHP의 알려진 취약점을 노리는 것으로 짐작되는 일상적인 요청이 매일 쏟아지는 건 말할 것도 없고요.
인터넷은 온갖 주체가 드나드는 수문이고, 그중 상당수는 자동화된 존재입니다. HN 같은 곳에 링크가 올라가면 그 밸브가 특히 활짝 열리는 거죠.
저도 그랬어요. HN에 글을 올린 뒤 트래픽 때문에 사이트가 한동안 먹통이 됐습니다. 제가 보기엔 저를 DDoS하려는 것 같아요 (알루미늄 호일 모자를 씁니다)
저는 몇 가지 이유로(*) Anubis를 직접 만들어 쓰고 있는데, 정상 크롤러를 화이트리스트에 올려 둬도 전체 트래픽의 80% 넘게가 챌린지를 통과하지 못하는 봇입니다.
* 프록시로 앞에 세우지 않고 기존 앱 옆에서 같이 돌릴 수 있도록 elixir 버전이 필요했습니다. 이렇게 하면 기존 앱이 호출자가 이미 화이트리스트에 있는지 확인하고, 없으면 챌린저 https://sphinx.8by3.com 로 리디렉션합니다. 챌린지를 통과하면 거기서 원래 사이트(예: https://tuhat.net )로 돌려보냅니다.
직접 만드신다면 Anubis처럼 영리할 필요는 없을 겁니다. JS로 CPU를 꽤 먹는 작업이면 충분하고, 메모리까지 많이 먹게 만들 수 있다면 가산점입니다. 지금은 CPU를 많이 쓰는 작업이면 대부분의 봇이 실행을 포기합니다(웹의 상당 부분이 JS 없이는 접근 불가라 JS 자체는 많이 돌리지만요). 그리고 당신의 챌린지를 WASM 같은 걸로 최적화해 줄 일은 없습니다. 그 챌린지가 지켜 주는 사이트가 얼마 안 돼서 그럴 가치가 없거든요. 반면 Anubis의 챌린지는 널리 쓰이니 그렇게 최적화할 만할 수 있고, 그래서 그 프로젝트는 영리함 겨루기의 소모전에 갇혀 있습니다. 메모리 집약적인 문제와 JS보다 효율적인 무언가로 하루빨리 옮겨 가야 하는 게 분명하죠.
저도 기성품 대신 직접 구현하려는 가장 큰 이유가 두 가지 있습니다.
위에서 말한 점들
일부 집단에는 더 어려운 일을 시키는 심술을 부릴 수 있다는 점입니다(더 긴 챌린지, 봇은 신경도 안 쓸 시간 지연 추가 등). "안녕하세요, 북미 IP님. 관세를 사실상 직접 내는 걸 보니 번거로운 걸 정말 좋아하시나 봐요. 자, 제가 일을 좀 더 얹어 드릴게요!"
이런 생각을 하시는 걸 보니 미국 밖에 계신가 보네요.
그냥 "관세 때문에 당신네 나라에 화가 나서 대기 시간을 더 줍니다"라고 말하는 거나 마찬가지예요. 관세를 매기는 나라 사람들에게 이렇게 앙갚음하고 싶어진다는 건, 관세가 당신에게 어떤 식으로든 악영향을 줬다는 뜻이잖아요. 관세가 투표로 그걸 밀어붙인 관세 부과국 사람들이 '사실상 내는 것'이라는 당신 주장과는 맞지 않죠.