2025년 11월 18일 11:20 UTC에 Cloudflare 네트워크에서 핵심 트래픽 전달에 중대한 장애가 발생했습니다. 원인은 Bot Management가 사용하는 특성 파일을 생성하는 데이터베이스 시스템의 권한 변경으로 잘못된 파일이 배포된 것이었으며, 14:30경 주된 영향이 해소되고 17:06에 모든 서비스가 정상화되었습니다. 사고의 원인, 영향, 대응 과정과 재발 방지 계획을 상세히 설명합니다.
2025-11-18
읽는 데 12분

2025년 11월 18일 11:20 UTC(이 블로그의 모든 시간은 UTC)부터, Cloudflare의 네트워크는 핵심 네트워크 트래픽 전달에서 심각한 실패를 겪기 시작했습니다. 이는 인터넷 사용자가 고객 사이트에 접속하려 할 때 Cloudflare 네트워크 내부 오류를 나타내는 에러 페이지로 표시되었습니다.
이번 문제는 어떠한 사이버 공격이나 악의적인 활동에 의해 직접적 또는 간접적으로 발생한 것이 아닙니다. 대신, 데이터베이스 시스템 중 하나의 권한 변경으로 인해 데이터베이스가 Bot Management 시스템에서 사용하는 "특성(feature) 파일"에 중복 항목을 다수 출력하게 되었고, 그 결과 해당 파일의 크기가 두 배가 되었습니다. 예상보다 큰 특성 파일이 네트워크를 구성하는 모든 머신으로 전파되었습니다.
네트워크 전반의 트래픽을 라우팅하는 이들 머신에서 실행되는 소프트웨어는 지속적으로 변화하는 위협에 맞춰 Bot Management 시스템을 최신 상태로 유지하기 위해 이 특성 파일을 읽습니다. 그런데 이 소프트웨어에는 특성 파일 크기에 대한 상한이 있었고, 그 상한이 두 배로 커진 파일 크기보다 낮았습니다. 그로 인해 소프트웨어가 실패했습니다.
초기에는 우리가 목격한 증상이 초대형 DDoS 공격 때문이라고 잘못 의심했지만, 곧 핵심 문제를 올바르게 파악하여 예상보다 큰 특성 파일의 전파를 중단하고 이전 버전 파일로 교체할 수 있었습니다. 14:30경에는 핵심 트래픽이 대부분 정상적으로 흐르기 시작했습니다. 이후 몇 시간 동안 트래픽이 급격히 복귀하면서 네트워크 여러 부분에 가중된 부하를 완화하기 위해 작업했습니다. 17:06 현재 Cloudflare의 모든 시스템이 정상적으로 작동하고 있습니다.
고객 여러분과 전반적인 인터넷에 끼친 영향에 대해 사과드립니다. Cloudflare가 인터넷 생태계에서 차지하는 중요성을 고려할 때, 당사 시스템의 어떤 장애라도 용납될 수 없습니다. 네트워크가 트래픽을 라우팅할 수 없었던 시간이 있었다는 사실은 우리 팀 모두에게 매우 고통스럽습니다. 오늘 우리는 여러분의 기대에 미치지 못했습니다.
이 게시물은 정확히 어떤 일이 일어났는지, 어떤 시스템과 프로세스가 실패했는지에 대한 심층 보고입니다. 또한 이러한 장애가 다시는 발생하지 않도록 하기 위해 우리가 무엇을 할 계획인지에 대한 시작점이기도 합니다(끝이 아닙니다).
아래 차트는 Cloudflare 네트워크가 제공한 5xx HTTP 상태 코드의 볼륨을 보여줍니다. 이는 보통 매우 낮아야 하며, 실제로 장애가 시작되기 직전까지도 낮게 유지되었습니다.
11:20 이전의 볼륨은 네트워크 전반에서 관측되는 5xx 오류의 예상 기준선입니다. 이후 스파이크와 그에 따른 변동은 잘못된 특성 파일을 로드하면서 시스템이 실패했음을 보여줍니다. 주목할 점은, 그 뒤 시스템이 한동안 회복되었다는 것입니다. 내부 오류로서는 매우 이례적인 행동이었습니다.
설명하자면, 해당 파일은 권한 관리 개선을 위해 점진적으로 업데이트 중이던 ClickHouse 데이터베이스 클러스터에서 실행되는 쿼리에 의해 5분마다 생성되었습니다. 쿼리가 업데이트된 클러스터 일부에서 실행된 경우에만 잘못된 데이터가 생성되었습니다. 그 결과, 5분마다 올바른 구성 파일 또는 잘못된 구성 파일이 생성되어 네트워크 전체로 빠르게 전파될 가능성이 있었습니다.
이러한 변동성 때문에, 네트워크에 때때로 올바른, 때때로 잘못된 구성 파일이 배포되면서 시스템 전체가 회복되었다가 다시 실패하는 현상이 겹쳐 무슨 일이 일어나는지 불분명해졌습니다. 초기에는 이것이 공격 때문일 수 있다고 믿게 만들었습니다. 결국에는 모든 ClickHouse 노드가 잘못된 구성 파일을 생성하게 되었고, 변동성은 실패 상태로 고정되었습니다.
오류는 근본 원인이 14:30부터 파악되고 해결되기 전까지 지속되었습니다. 우리는 잘못된 특성 파일의 생성 및 전파를 중단하고, 검증된 정상 파일을 특성 파일 배포 큐에 수동으로 삽입하여 문제를 해결했습니다. 그리고 우리의 코어 프록시를 강제로 재시작했습니다.
위 차트의 남은 긴 꼬리는, 잘못된 상태에 들어간 서비스들을 팀이 재시작한 과정이며, 17:06에 5xx 오류 코드 볼륨이 정상으로 복귀했습니다.
다음 서비스가 영향을 받았습니다:
| 서비스/제품 | 영향 설명 |
|---|---|
| 핵심 CDN 및 보안 서비스 | HTTP 5xx 상태 코드. 이 게시물 상단의 스크린샷은 최종 사용자에게 제공된 일반적인 오류 페이지를 보여줍니다. |
| Turnstile | Turnstile이 로드되지 않았습니다. |
| Workers KV | 코어 프록시 실패로 KV의 "프런트 엔드" 게이트웨이에 대한 요청이 실패하면서 HTTP 5xx 오류가 크게 증가했습니다. |
| 대시보드 | 대시보드는 대부분 동작했지만, 로그인 페이지에서 Turnstile을 사용할 수 없어서 대부분의 사용자가 로그인할 수 없었습니다. |
| Email Security | 이메일 처리 및 전달은 영향을 받지 않았으나, 스팸 탐지 정확도를 낮추고 일부 신규 도메인 연령 감지를 트리거하지 못하게 하는 IP 평판 소스에 일시적으로 접근하지 못했습니다. 중요한 고객 영향은 관찰되지 않았습니다. 또한 일부 자동 이동(Auto Move) 작업에서 실패가 있었고, 영향을 받은 모든 메시지는 검토 후 수정되었습니다. |
| Access | 대부분의 사용자에게 인증 실패가 광범위하게 발생했으며, 사고 시작 시점부터 13:05 롤백이 시작될 때까지 이어졌습니다. 기존 Access 세션은 영향을 받지 않았습니다. 실패한 모든 인증 시도는 오류 페이지로 이어졌고, 이로 인해 인증이 실패하는 동안 해당 사용자가 대상 애플리케이션에 도달하는 일은 없었습니다. 이 기간 동안의 성공적인 로그인은 사건 중에도 올바르게 로깅되었습니다. 당시 시도된 Access 구성 업데이트는 실패했거나 매우 느리게 전파되었을 것입니다. 모든 구성 업데이트는 지금은 복구되었습니다. |
HTTP 5xx 오류를 반환하는 것 외에도, 영향 기간 동안 CDN 응답 지연 시간이 크게 증가했습니다. 이는 포착되지 않은 오류에 추가 디버깅 정보를 자동으로 부가하는 디버깅 및 가시성(observability) 시스템이 많은 CPU를 사용했기 때문입니다.
Cloudflare로 들어오는 모든 요청은 네트워크를 통해 명확히 정의된 경로를 따릅니다. 웹 페이지를 로드하는 브라우저 요청일 수도, API를 호출하는 모바일 앱일 수도, 다른 서비스에서 발생한 자동화 트래픽일 수도 있습니다. 이러한 요청은 먼저 HTTP 및 TLS 계층에서 종료되고, 이후 코어 프록시 시스템(내부적으로 FL, 즉 "Frontline"이라고 부름)으로 흘러 들어가며, 마지막으로 Pingora를 거쳐 캐시 조회를 수행하거나 필요 시 오리진에서 데이터를 가져옵니다.
코어 프록시가 어떻게 동작하는지에 대한 자세한 내용은 여기에서 공유한 바 있습니다.
요청이 코어 프록시를 통과하는 동안, 우리는 네트워크에서 제공하는 다양한 보안 및 성능 제품을 실행합니다. 프록시는 각 고객의 고유한 구성과 설정을 적용하며, WAF 규칙과 DDoS 보호 강제부터 Developer Platform 및 R2로의 트래픽 라우팅까지 수행합니다. 이는 프록시를 통과하는 트래픽에 구성 및 정책 규칙을 적용하는 도메인 특화 모듈들의 집합을 통해 이뤄집니다.
그 모듈 중 하나인 Bot Management가 오늘 장애의 원인이었습니다.
Cloudflare의 Bot Management에는, 그 외 시스템들과 함께, 네트워크를 통과하는 모든 요청에 대한 봇 점수를 생성하는 데 사용하는 머신러닝 모델이 포함되어 있습니다. 고객은 봇 점수를 사용해 어떤 봇이 자신의 사이트에 접근할 수 있는지 제어합니다.
이 모델은 입력으로 "특성(feature)" 구성 파일을 사용합니다. 여기서 특성이란, 해당 요청이 자동화된 것인지 아닌지에 대해 모델이 예측을 내리기 위해 사용하는 개별 속성을 의미합니다. 특성 구성 파일은 개별 특성들의 모음입니다.
이 특성 파일은 몇 분마다 새로 고쳐져 전체 네트워크에 게시되며, 인터넷 전반의 트래픽 흐름 변화를 반영할 수 있게 해줍니다. 새로운 유형의 봇과 새로운 봇 공격에 대응할 수 있도록 해줍니다. 따라서 악의적인 행위자들이 빠르게 전술을 바꾸는 만큼, 이 파일을 자주, 빠르게 롤아웃하는 것이 중요합니다.
이 파일을 생성하는 ClickHouse 쿼리 동작(아래 설명)이 변경되면서, 중복된 "특성" 행이 대량으로 들어가게 되었고, 그 결과 이전에 고정 크기였던 특성 구성 파일의 크기가 변하면서 봇 모듈에서 오류가 발생했습니다.
그 결과, 고객 트래픽을 처리하는 코어 프록시 시스템은 봇 모듈에 의존하는 트래픽에 대해 HTTP 5xx 오류 코드를 반환했습니다. 코어 프록시에 의존하는 Workers KV와 Access도 영향을 받았습니다.
이번 사고와 별개로, 우리는 현재 고객 트래픽을 새로운 버전의 프록시 서비스(내부적으로 FL2라고 함)로 마이그레이션 중입니다. 두 버전 모두 이번 이슈의 영향을 받았으나, 관측된 영향은 달랐습니다.
새로운 FL2 프록시 엔진에 배포된 고객은 HTTP 5xx 오류를 관찰했습니다. 기존 프록시 엔진(FL)에서는 오류가 보이지 않았지만, 봇 점수가 올바르게 생성되지 않아 모든 트래픽이 봇 점수 0을 받았습니다. 봇 차단 규칙을 배포해 둔 고객은 대규모 오탐을 경험했을 수 있습니다. 규칙에서 봇 점수를 사용하지 않았던 고객은 영향을 받지 않았습니다.
우리를 혼란스럽게 하여 공격일 수 있다고 믿게 만든 또 다른 겉보기 증상도 있었습니다. Cloudflare의 상태 페이지가 다운된 것입니다. 상태 페이지는 Cloudflare 인프라 외부에서 완전히 호스팅되며 Cloudflare에 대한 종속성이 없습니다. 결과적으로는 단순한 우연이었지만, 일부 대응 팀에게는 공격자가 당사 시스템과 상태 페이지를 동시에 겨냥하고 있다고 믿게 만들었습니다. 당시 상태 페이지 방문자는 다음과 같은 오류 메시지를 보았습니다:
내부 사건 채팅방에서는, 이것이 최근 빈발한 고용량 AisuruDDoS 공격의 연장선일 수 있다고 우려했습니다:

앞서 언급했듯, 기본 쿼리 동작의 변경으로 특성 파일에 중복 행이 대량 포함되었습니다. 문제의 데이터베이스 시스템은 ClickHouse 소프트웨어를 사용합니다.
배경 설명을 위해, ClickHouse의 분산 쿼리가 어떻게 동작하는지 이해하는 것이 도움이 됩니다. ClickHouse 클러스터는 여러 샤드로 구성됩니다. 모든 샤드에서 데이터를 조회하려면 default 데이터베이스에 이른바 분산 테이블(Distributed 테이블 엔진 구동)을 둡니다. Distributed 엔진은 r0 데이터베이스의 기본 테이블을 쿼리합니다. 기본 테이블은 ClickHouse 클러스터의 각 샤드에 데이터가 저장되는 곳입니다.
분산 테이블에 대한 쿼리는 공유 시스템 계정으로 실행됩니다. 분산 쿼리의 보안성과 안정성을 향상하기 위한 노력의 일환으로, 이를 초기 사용자 계정으로 실행하도록 전환하는 작업을 진행 중입니다.
오늘 이전까지, ClickHouse 사용자는 system.tables 또는 system.columns 같은 ClickHouse 시스템 테이블에서 테이블 메타데이터를 조회할 때 default 데이터베이스의 테이블만 볼 수 있었습니다.
사용자가 이미 r0의 기본 테이블에 암묵적으로 접근할 수 있으므로, 11:05에 이 접근을 명시적으로 부여해 사용자가 해당 테이블의 메타데이터도 볼 수 있게 변경했습니다. 모든 분산 하위 쿼리가 초기 사용자로 실행되도록 함으로써 쿼리 한도와 접근 권한을 보다 세밀하게 평가할 수 있고, 한 사용자의 불량 하위 쿼리가 다른 사용자에게 영향을 미치는 것을 방지할 수 있습니다.
위 변경으로 인해 사용자는 자신이 접근 권한을 가진 테이블의 정확한 메타데이터를 모두 볼 수 있게 되었습니다. 불행히도 과거에는 아래와 같은 쿼리가 반환하는 열 목록에 "default" 데이터베이스만 포함된다고 가정했습니다:
SELECT
name,
type
FROM system.columns
WHERE
table = 'http_requests_features'
order by name;
주의할 점은, 이 쿼리가 데이터베이스 이름으로 필터링하지 않는다는 것입니다. 특정 ClickHouse 클러스터의 사용자들에게 명시적 권한을 점진적으로 롤아웃함에 따라, 11:05 변경 이후 위 쿼리는 r0 데이터베이스에 저장된 기본 테이블에 대한 열까지 포함하여 열의 "중복"을 반환하기 시작했습니다.
안타깝게도, 이는 Bot Management 특성 파일 생성 로직이 파일의 각 입력 "특성"을 구성하기 위해 수행하던 바로 그 유형의 쿼리였습니다.
위 쿼리는 다음과 같은(단순화된 예시의) 열 표를 반환합니다:
그러나 사용자에게 부여된 추가 권한의 일환으로, 응답에는 이제 r0 스키마의 모든 메타데이터가 포함되었고, 결과적으로 응답 행 수가 두 배 이상으로 늘어 최종 파일 출력의 행(즉, 특성) 수도 영향을 받았습니다.
프록시 서비스에서 실행되는 각 모듈에는 무한한 메모리 사용을 방지하고 성능 최적화를 위해 메모리를 사전 할당하기 위한 여러 제한이 있습니다. 이번 사례에서 Bot Management 시스템은 런타임에 사용할 수 있는 머신러닝 특성의 수에 제한이 있습니다. 현재 제한은 200으로 설정되어 있으며, 이는 현재 약 60개 특성 사용량보다 훨씬 높습니다. 다시 말해, 성능상의 이유로 특성에 대한 메모리를 사전 할당하기 때문에 이 제한이 존재합니다.
200개를 초과하는 특성을 가진 잘못된 파일이 서버로 전파되자, 이 제한에 도달했고 시스템이 패닉을 일으켰습니다. 해당 확인을 수행하며 처리되지 않은 오류의 원인이 된 FL2의 Rust 코드 일부는 아래와 같습니다:
이로 인해 다음과 같은 패닉이 발생했고, 결과적으로 5xx 오류로 이어졌습니다:
thread fl2_worker_thread panicked: called Result::unwrap() on an Err value
코어 프록시에 의존하는 다른 시스템들도 사고 동안 영향을 받았습니다. 여기에는 Workers KV와 Cloudflare Access가 포함됩니다. 팀은 13:04에 Workers KV가 코어 프록시를 우회하도록 패치를 적용하여 이들 시스템에 대한 영향을 줄일 수 있었습니다. 이후 Workers KV에 의존하는 모든 다운스트림 시스템(Access 자체 등)에서 오류율이 감소했습니다.
Cloudflare 대시보드도 내부적으로 Workers KV를 사용하고 로그인 플로우의 일부로 Cloudflare Turnstile이 배포되어 있어 영향을 받았습니다.
Turnstile도 이번 장애의 영향을 받아, 활성 대시보드 세션이 없던 고객은 로그인할 수 없었습니다. 이는 아래 그래프에서 보이듯 두 구간에서 가용성이 낮게 나타났습니다: 11:3013:10, 그리고 14:4015:30 사이입니다.
첫 번째 구간(11:30~13:10)은 일부 컨트롤 플레인 및 대시보드 기능이 의존하는 Workers KV의 영향 때문이었습니다. 13:10에 Workers KV가 코어 프록시 시스템을 우회하면서 복구되었습니다. 두 번째 대시보드 영향 구간은 특성 구성 데이터를 복구한 이후 발생했습니다. 로그인 시도 누적이 대시보드를 압도하기 시작했고, 이 누적과 재시도가 결합되어 지연 시간이 상승하며 대시보드 가용성이 낮아졌습니다. 컨트롤 플레인의 동시성 확장으로 약 15:30에 가용성이 복구되었습니다.
이제 시스템이 온라인으로 복귀해 정상 작동하고 있으며, 향후 이와 같은 실패에 대비해 시스템을 강화하는 작업을 이미 시작했습니다. 특히 다음을 수행하고 있습니다:
오늘은 Cloudflare의 2019년 이후 최악의 장애였습니다. 대시보드를 사용할 수 없게 만든 장애도 있었고, 신규 기능이 한동안 사용 불가능했던 적도 있었습니다. 하지만 지난 6년 넘는 기간 동안, 핵심 트래픽의 대다수가 우리 네트워크를 통해 흐르지 못하게 만든 이런 수준의 장애는 없었습니다.
오늘과 같은 장애는 용납될 수 없습니다. 우리는 트래픽이 항상 계속 흐르도록 장애에 매우 탄력적으로 대처하는 아키텍처를 설계했습니다. 과거에 장애를 겪을 때마다 우리는 더 새롭고 탄력적인 시스템을 구축해 왔습니다.
Cloudflare 전 팀을 대표하여, 오늘 우리가 인터넷에 끼친 고통에 대해 사과드립니다.
| 시간(UTC) | 상태 | 설명 |
|---|---|---|
| 11:05 | 정상. | 데이터베이스 접근 제어 변경 사항 배포. |
| 11:28 | 영향 시작. | 배포가 고객 환경에 도달, 고객 HTTP 트래픽에서 첫 오류 관찰. |
| 11:32-13:05 | 팀이 트래픽 증가와 Workers KV 서비스 오류를 조사. | 초기 증상은 Workers KV 응답률 저하로 보였고, 이로 인해 다른 Cloudflare 서비스에 다운스트림 영향이 발생하는 것으로 보였습니다. 트래픽 조정과 계정 제한 같은 완화책을 시도하여 Workers KV 서비스를 정상 수준으로 복구하려 했습니다. 첫 자동화 테스트가 11:31에 문제를 감지했으며, 11:32에 수동 조사가 시작되었습니다. 11:35에 인시던트 콜이 개설되었습니다. |
| 13:05 | Workers KV 및 Cloudflare Access 우회 적용 — 영향 감소. | 조사 과정에서 Workers KV와 Cloudflare Access가 내부 시스템 우회를 사용해 코어 프록시의 이전 버전으로 폴백하도록 했습니다. 이전 버전에도 문제가 있었지만, 아래 설명처럼 영향이 더 작았습니다. |
| 13:37 | Bot Management 구성 파일을 마지막으로 정상 동작하던 버전으로 롤백하는 작업에 집중. | Bot Management 구성 파일이 사건의 트리거라는 확신을 가졌습니다. 여러 작업 흐름에서 서비스를 복구하는 방법을 모색했으며, 가장 빠른 작업 흐름은 이전 버전 파일을 복원하는 것이었습니다. |
| 14:24 | 새로운 Bot Management 구성 파일의 생성 및 전파 중단. | Bot Management 모듈이 500 오류의 원인이며, 잘못된 구성 파일 때문임을 확인했습니다. 새로운 Bot Management 구성 파일의 자동 배포를 중단했습니다. |
| 14:24 | 새 파일 테스트 완료. | 이전 버전 구성 파일로 성공적으로 복구되는 것을 관찰했으며, 전 세계적으로 수정을 가속화하는 데 집중했습니다. |
| 14:30 | 주된 영향 해소. 다운스트림 서비스의 오류 감소 시작. | 올바른 Bot Management 구성 파일이 전 세계에 배포되었고, 대부분의 서비스가 정상적으로 동작하기 시작했습니다. |
| 17:06 | 모든 서비스 복구. 영향 종료. | 모든 다운스트림 서비스가 재시작되었고 모든 운영이 완전히 복원되었습니다. |
Cloudflare의 커넥티비티 클라우드는 기업 전체 네트워크를 보호하고, 고객이 인터넷 규모의 애플리케이션을 효율적으로 구축하며, 모든 웹사이트나 인터넷 애플리케이션을 가속하고, DDoS 공격을 방어하며, 해커를 저지하고, Zero Trust로의 여정을 돕습니다.
어떤 기기에서든 1.1.1.1을 방문하여, 인터넷을 더 빠르고 안전하게 만들어 주는 무료 앱을 시작해 보세요.
더 나은 인터넷 구축을 돕는 우리의 미션에 대해 더 알아보려면 여기서 시작하세요. 새로운 커리어를 찾고 계시다면 채용 공고를 확인해 보세요.