{"id":"IL-0253","org":"Mozilla","date":"2022-01-13","docs":[],"title":{"en":"Firefox froze and could not load any web content for close to two hours, stuck in an HTTP/3 request to Telemetry","ko":"Firefox 가 네트워크 스레드의 무한 루프에 빠져 전 세계에서 2시간 가까이 웹 페이지를 열지 못했다"},"domain":["gcp","networking"],"impact":{"scope":"Firefox could not load web content; the browser hung on its single network socket thread","users":"Firefox users worldwide","region":"worldwide"},"review":{"written_by":"session","reviewed_at":null,"reviewed_by":null},"lessons":{"en":"The hang needed three things together: a provider-side change to the HTTP version, a Rust component calling the network stack through viaduct, and a case-sensitive header lookup deep in the HTTP/3 code. Leaving the load balancers on an automatic default let the provider's change apply without any action from Mozilla, and an announcement would likely have led to a controlled test in staging first. A change of HTTP version and an extra networking layer such as viaduct are significant enough to be covered by system tests.","ko":"문제는 처음 보기보다 훨씬 복잡했고 여러 요인이 함께 작용했다. GCP 가 HTTP/3 기본값 변경을 예고했다면 사고를 완전히 막지는 못했어도 스테이징 환경 같은 곳에서 더 통제된 실험과 배포를 할 수 있었을 것이다. 로드 밸런서를 명시적인 값 대신 \"Automatic (default)\" 로 둔 탓에 변경이 저절로 적용됐다. Firefox Desktop 에서 HTTP/3 와 viaduct 를 함께 쓰는 조합은 CI 가 시험하지 않았다. 모든 조합을 시험할 수는 없어도 HTTP 버전 선택이나 viaduct 같은 추가 네트워크 계층은 시험했어야 했다. HTTP 버전을 바꿔 가며 시스템 테스트를 더 돌렸다면 이 문제를 찾았을 것이다."},"related":[],"sources":[{"url":"https://hacks.mozilla.org/2022/02/retrospective-and-technical-details-on-the-recent-firefox-outage/","kind":"blog","archived":"https://web.archive.org/web/20261023154852/https://hacks.mozilla.org/2022/02/retrospective-and-technical-details-on-the-recent-firefox-outage/"}],"summary":{"en":"Firefox relies on Mozilla-run services for updates, telemetry, certificate management and crash reporting, hosted by several cloud providers behind load balancers. On Google Cloud Platform these load balancers have an HTTP/3 setting with the states \"Enabled\", \"Disabled\" and \"Automatic (default)\", and Mozilla's were on \"Automatic (default)\". When GCP made HTTP/3 the default, Firefox, which uses HTTP/3 whenever a server supports it, began sending some requests to these services over HTTP/3. The most critical services, such as updates, use a beConservative flag that keeps experimental technology such as HTTP/3 out of their connections.\n\nAll HTTP/3 traffic goes through Necko, the Firefox networking stack. Rust components reach Necko through an intermediate library called viaduct, which lower-cases every header. For HTTP/3 uploads, the higher-level Necko API checks for a Content-Length header without regard to case and adds one if it is missing, while the lower-level HTTP/3 code looks it up case-sensitively. Telemetry was the only Rust component in Firefox Desktop that used the network stack and added a Content-Length header. The HTTP/3 code did not find the lower-cased header, considered the request complete while its body was still unsent, and then looped forever because it only stopped when nothing was left to send. The loop ran on the single socket thread, so the whole browser lost network access.\n\nMozilla explicitly disabled HTTP/3 on its GCP load balancers at 09:12 UTC, which unblocked users before the root cause was understood. Mozilla named three contributing factors: GCP's change was not announced, the \"Automatic (default)\" setting let it apply automatically, and the continuous integration system did not cover HTTP/3 combined with viaduct on Firefox Desktop, since the HTTP/3 tests covered the protocol and Necko only as web content uses them.","ko":"Firefox 의 업데이트, 텔레메트리, 인증서 관리, 크래시 보고 같은 내부 서비스는 여러 클라우드 제공자에 올라가 있고 로드 밸런서가 부하를 나눈다. GCP 로드 밸런서의 HTTP/3 지원 설정은 \"Enabled\", \"Disabled\", \"Automatic (default)\" 셋 가운데 하나를 고르게 되어 있고, Mozilla 는 \"Automatic (default)\" 로 두었다. 2022년 1월 13일 07:28 UTC 에 GCP 가 예고 없이 HTTP/3 를 기본으로 바꿨고, Firefox 는 서버가 지원하면 HTTP/3 를 쓰므로 내부 서비스로 가는 연결 일부가 HTTP/2 대신 HTTP/3 를 쓰게 됐다. 업데이트처럼 아주 중요한 서비스는 beConservative 플래그를 써서 HTTP/3 같은 실험적인 기술을 연결에 쓰지 않는다.\n\nFirefox 의 HTTP/3 연결은 모두 네트워크 스택 Necko 를 거친다. 네트워크에 직접 접근해야 하는 Rust 구성 요소는 viaduct 라는 중간 라이브러리를 통해 Necko 를 부른다. Necko 의 상위 API 는 업로드 요청에 Content-Length 헤더가 있는지 대소문자를 가리지 않고 확인하고 없으면 넣는다. 하위 HTTP/3 코드는 이 헤더로 요청 크기를 정하는데 대소문자를 가려서 찾는다. viaduct 는 헤더를 모두 소문자로 바꿔 넘기므로, viaduct 를 거친 요청은 상위 확인은 통과하지만 HTTP/3 코드는 헤더를 찾지 못한다. Firefox Desktop 에서 네트워크 스택을 쓰면서 Content-Length 헤더를 넣는 Rust 구성 요소는 지금 Telemetry 하나뿐이다.\n\n헤더를 찾지 못한 HTTP/3 코드는 요청이 끝났다고 보고 실제 본문을 보내지 않았다. 그런데 이 코드는 보낼 내용이 남지 않아야 끝나기 때문에 오류를 내지 않고 끝없이 돌았다. 모든 네트워크 요청이 소켓 스레드 하나를 거치므로 이 루프가 다른 통신을 모두 막아 Firefox 가 응답하지 않았다. Mozilla 는 09:12 UTC 에 GCP 에서 HTTP/3 를 명시적으로 껐고 사용자들이 다시 브라우저를 쓸 수 있게 됐다."},"trigger":{"en":"At 07:28 UTC on 13 January 2022 GCP deployed an unannounced change that made HTTP/3 the default for load balancers set to \"Automatic (default)\", so some Firefox connections to Mozilla's services, including Telemetry, started using HTTP/3 instead of HTTP/2.","ko":"2022년 1월 13일 07:28 UTC 에 GCP 가 예고 없이 로드 밸런서의 HTTP/3 를 기본으로 켰다. Mozilla 의 로드 밸런서는 \"Automatic (default)\" 설정이어서 Firefox 가 Telemetry 서비스로 여는 연결 일부가 HTTP/2 대신 HTTP/3 를 쓰게 됐다."},"severity":"unknown","symptoms":["service-unavailable"],"timeline":{"detected_after":null,"resolved_after":"1h 44m"},"date_kind":"incident","detection":{"en":"A spike in crashes reported through the Firefox crash reporter, and reports of browser hangs from inside and outside Mozilla.","ko":"크래시 리포터로 들어오는 크래시가 갑자기 늘었고, Mozilla 안팎에서 브라우저가 멈춘다는 신고가 여럿 들어왔다."},"components":["cloud-load-balancer","http-client-library"],"root_cause":"software-bug","remediation":[{"text":{"en":"Explicitly disabled HTTP/3 on the GCP load balancers at 09:12 UTC","ko":"09:12 UTC 에 GCP 에서 HTTP/3 를 명시적으로 껐다."}}],"action_items":[{"text":{"en":"Work with GCP to improve the situation around unannounced changes such as the HTTP/3 default","ko":"GCP 와 함께 예고 없는 기본값 변경 문제를 개선한다."}},{"text":{"en":"Review all service configurations to avoid similar mistakes","ko":"비슷한 실수를 막으려고 모든 서비스의 설정을 다시 검토한다."}},{"text":{"en":"Run more system tests with different HTTP versions","ko":"HTTP 버전을 바꿔 가며 시스템 테스트를 더 돌린다."}},{"text":{"en":"Find ways to make the browser more resilient to such problems and to speed up incident response","ko":"이런 문제에 브라우저가 더 잘 견디고 사고 대응이 더 빨라지도록 할 조치를 찾는다."}}],"contributing":["default-config-unchanged","test-coverage-gap"],"recurrence_of":null,"symptoms_text":{"en":"On 13 January 2022, shortly after 07:28 UTC, Mozilla saw a spike in crashes reported through the Firefox crash reporter and received several reports, from inside and outside Mozilla, of the browser hanging. For close to two hours Firefox was unusable for users worldwide and could not load web content.\n\nThe backlog of unprocessed crash reports grew to close to 300K. Incident response found that the browser was hanging inside a network request to one of the Firefox internal services. All network requests in Firefox go through one socket thread, so that one stuck request blocked every other network request. Users who had disabled Telemetry did not see the problem.\n\nThe team first looked for a change of its own and found that no updates or configuration changes had shipped. HTTP/3 had been enabled since Firefox 88 and was in active use on popular websites, so it did not look like a new factor. Suspecting an invisible change by a cloud provider, the team checked its load balancer settings, which had not changed, and then found in logs that the load balancers of the Telemetry service were serving HTTP/3 connections, which they had not done before. Tests with various tools and remote services, even against the Telemetry staging server, did not reproduce the hang; only Firefox itself did, against the staging server.","ko":"2022년 1월 13일 07:28 UTC 직후 크래시 리포터로 들어오는 크래시가 갑자기 늘었고, Mozilla 안팎에서 브라우저가 멈춘다는 신고가 여럿 들어왔다. 전 세계 사용자의 Firefox 가 2시간 가까이 웹 콘텐츠를 불러오지 못하고 쓸 수 없는 상태가 됐다.\n\n처리되지 않은 크래시 보고가 쌓여 30만 건 가까이 됐다.\n\n조사해 보니 Firefox 는 내부 서비스 하나로 가는 네트워크 요청 안에서 멈춰 있었다. 모든 네트워크 요청이 소켓 스레드 하나를 거치기 때문에 이 스레드가 막히자 다른 네트워크 통신도 모두 막혔다.\n\n팀은 문제를 일으킨 변경을 찾아보았지만 Mozilla 쪽에서는 원인이 될 만한 업데이트나 설정 변경을 내보낸 적이 없었다. HTTP/3 는 Firefox 88 부터 켜져 있었고 인기 있는 웹사이트 몇 곳도 이미 쓰고 있었다. 팀은 클라우드 제공자 쪽에서 로드 밸런서 동작을 바꾸는 변경이 눈에 띄지 않게 나갔다고 의심했다. 자세히 살펴보니 Mozilla 의 설정은 하나도 바뀌지 않았다. 그러다 로그에서 Telemetry 서비스의 로드 밸런서가 전에 없던 HTTP/3 연결을 받고 있는 것을 찾았다.\n\nTelemetry 를 끈 사용자는 증상이 사라졌다. 여러 도구와 원격 서비스로 시험해도 재현되지 않았고, 원래 설정 그대로 둔 Telemetry 스테이징 서버에 평범하게 연결해도 재현되지 않았다. Firefox 자체로 스테이징 서버에 연결했을 때만 재현됐다."},"updated_at":"2026-11-14T12:33:50.192447Z","url":"https://benchlet.com/incidentlib/app/cases/IL-0253","org_slug":"mozilla"}