자해 서비스 거부(DDoS) 공격

일부 풀 리퀘스트를 검토하는 데 만족스럽게 불평하고 있었는데, 다음 코드가 저를 전율하게 만들었습니다.

var unsent-messages = new List();

function log(message) {
    unsent-message =+ message
}

every (5 secs) {
    send-all(unsent-messages)
    unsent-message = new List();
}


그랬더니 미소가 지어졌습니다. 비슷한 코드 조각으로 인해 10억 달러 규모의 회사가 중단되는 것을 본 적이 있습니다.

정전 1



모든 좋은 중단과 마찬가지로 일부 네트워크 구성 오류로 시작되었습니다.

이 경우 네트워크 문제로 인해 외부에서 회사의 모든 시스템에 연결할 수 없어 몇 분 동안 정전이 발생했습니다.

변화가 되돌려지고, 서비스가 복구되고, 책임이 할당되고, 관료주의가 추가되고, 우리 모두는 일터로 돌아갔습니다.

적어도 몇 분 동안.

정전 2



첫 번째 중단을 수정한 부작용은 수천 개의 클라이언트 브라우저가 천둥 같은 무리처럼 몇 초 만에 다시 연결을 시도하는 것이었습니다.

브라우저 통계 서비스를 제외한 모든 서비스가 기반을 유지합니다.

브라우저 통계 서비스(통계 서비스)



통계 서비스는 웹 애플리케이션의 특정 하위 집합에 대해 한 팀의 기능 사용 데이터를 수집하기 위해 탄생했습니다.



서비스는 브라우저에서 보낸 사용 데이터를 디스크에 기록하고 Splunk는 로그 파일을 읽고 개발자는 Splunk에서 대시보드와 알림을 작성합니다.

그것은 모두 셀프 서비스였고 관료주의적 마찰이 매우 적었습니다. 즉, 모든 프런트 엔드 팀이 결국 이를 채택했습니다.

어떤 것이 어떻게 실패했는지(일명 예외), 어떤 방식으로(일명 stacktrace) 실패했는지 모르면 어떤 통계도 완전하지 않습니다.

그리고 여기에서 문제가 시작되었습니다.

오류의 큰 더미



첫 번째 중단 동안 백엔드 서비스에 연결할 수 없었기 때문에 클라이언트의 브라우저는 실패한 모든 시도의 통계를 수집했습니다.

첫 번째 중단이 수정되었을 때 통계 서비스는 다음과 같았습니다.



서비스는 디스크에 충분히 빨리 쓸 수 없었기 때문에 통계 서비스에 요청이 쌓이기 시작했습니다.

쌓인 요청은 메모리 압력을 증가시켰고 통계 서비스가 미친 듯이 GC에 발생하여 대기 시간이 더 길어졌습니다.

Apaches는 통계 서비스 인스턴스가 적시에 응답하지 않는다는 것을 알아차렸을 때 원하는 것과는 반대로 요청을 다른 인스턴스로 재전송하여 기본적으로 압력을 두 배로 높였습니다.

그리고 이러한 모든 요청이 실패하거나 시간 초과되기 시작하면 클라이언트의 브라우저는 부지런히 실패를 기록하고 보고할 오류 더미에 추가했습니다.

디도스 공격



부상에 소금을 추가하기 위해 프런트 엔드 통계 라이브러리는 데이터를 잃지 않도록 설계되었으므로 통계 서비스에 대한 요청이 실패해도 통계가 재설정되지 않습니다.

사실, 실패한 통계 요청은 기록되고 다음 통계 서비스 호출에 추가되어 통계 메시지 크기가 점점 더 커져 이미 고군분투하고 있는 통계 서비스와 그 경로에 있는 모든 것에 점점 더 많은 압력을 가했습니다.

트래픽 양으로 인해 Apache 계층이 질식하기 시작하여 다른 다운스트림 서비스에 대한 요청이 점점 느려졌습니다.

이것은 클라이언트 브라우저의 오류 수를 증가시켰고, 통계 요청의 크기를 더욱 증가시켰고, 이로 인해 Apache가 훨씬 더 질식하게 되었고, 추가 대기 시간이 추가되어 더 많은 오류, 더 큰 요청, 더 많은 대기 시간, 더 많은 오류 등이 발생했습니다.



최종 결과: 전 세계 수천 개의 브라우저가 몇 초마다 메가바이트 길이의 POST 요청을 통계 서비스에 전송하여 통계 서비스 및 기타 모든 것이 실패했음을 통계 서비스에 알립니다.

자해 분산 서비스 거부 공격으로 인한 완전한 중단.

정상 상태 패턴



여러 가지가 잘못되었습니다(그리고 여러 가지를 나중에 고쳤습니다).

초기 코드 조각에 초점을 맞추면 Steady State pattern을 적용하면 문제를 피할 수 있습니다.

Steady State는 명백한 사실을 지적합니다: nothing is infinite . 메모리도, CPU도, 대역폭도, 디스크도, 시간도, 돈도 아닙니다.

따라서 몇 가지 제한을 설정해야 합니다. 이 경우 보내지 않은 메시지 배열의 최대 크기입니다.

이러한 제한을 추가하는 것은 대부분 fear of missing out 때문에 무섭습니다.

그러나 이러한 제한이 없으면 특히 문제가 발생하기 시작할 때 시스템의 안정성이 위험에 처합니다.

그리고 그것을 기억하십시오 ...

좋은 웹페이지 즐겨찾기