Nginx HTTP/2 다중화 악용 봇넷 폭주? 서버 터지기 전에 당장 바꿔야 할 3가지 설정 💥
아니 요즘 Nginx HTTP/2 다중화 기능 악용한 변종 봇넷 때문에 서버 뻗는 집들 속출한다는데 진짜 실화인가요?
웹사이트 속도 올려보겠다고 신나게 HTTP/2 켜뒀더니, 봇넷 놈들이 그 멀티플렉싱(Multiplexing) 통로를 쥐어짜서 서버 CPU를 100%로 구워버리는 신종 지옥이 펼쳐지고 있습니다.
모니터링 알람 울려서 들여다봤더니 Load Average 50 찍히고 사이트 뻗어있으면 진짜 뚝배기 깨고 싶어지죠.
하지만 너무 걱정 마세요. 오늘 Nginx 설정 몇 줄로 이 기괴한 HTTP/2 멀티플렉싱 DDoS 방어 무력화 꼼수를 박살 내는 법 알려드립니다.
"속도 빠르게 해준대서 HTTP/2 켰는데 봇넷한테 대문 훤히 열어준 꼴 ㅋㅋㅋ"
Nginx HTTP/2 Rapid Reset 원인, 속도 빨라지라고 튼 기능이 서버 도륙내는 이유
HTTP/2 Rapid Reset(CVE-2023-44487) 공격은 하나의 TCP 연결 안에서 무수히 많은 스트림을 요청한 직후 즉시 취소(RST_STREAM)하는 기법으로, 서버가 cancellation 처리를 하느라 CPU를 100% 점유하게 만들어 다운시킵니다.
기존 HTTP/1.1 공격은 커넥션을 수천 개씩 뚫어야 해서 방화벽이나 IP 차단 장비에 금방 걸렸는데요.
HTTP/2는 다중화(Multiplexing) 덕분에 TCP 커넥션 딱 1개만 뚫어놓고 그 안에서 수십만 개의 데이터 요청 스트림을 쏘아댈 수 있습니다.
문제는 봇넷이 요청을 쏘자마자 "아 참, 취소할게요!" 하는 RST_STREAM 프레임을 1초에 수만 번 들이붓는다는 겁니다.
서버 입장에선 요청 들어오니까 메모리 할당하고 준비하려는데, 0.001초 만에 취소 신호가 들어오니 내부 리소스 정리하느라 CPU가 비명을 지르며 뻗는 거죠.
과거 공공기관 DDoS 공격 방어 가이드에서도 다뤘듯 L7 계층 공격은 IP 차단만으로 막기 꽤 까다롭습니다.
http2_max_concurrent_streams 설정 방법, 봇넷 꼼수 무력화하는 최적 설정값
Nginx 설정 파일에서 http2_max_concurrent_streams 값을 기본값인 128보다 낮은 64~120 수준으로 제한하면 한 연결당 생성 가능한 동시 요청 수를 통제하여 봇넷 공격을 무력화할 수 있습니다.
기본 Nginx 설정에서는 한 커넥션당 동시 스트림 수가 128개로 잡혀있는데, 봇넷은 이 128개를 초당 수만 번 순환시키며 서버 리소스를 갈아 넣습니다.
nginx.conf나 해당 virtual host 설정 파일의 http 또는 server 블록에 아래처럼 딱 한 줄 추가해 주세요.
http {
# 동시 스트림 수를 64~100 수준으로 타이트하게 축소
http2_max_concurrent_streams 96;
# 연결당 최대 요청 수도 불필요하게 높이지 않기
keepalive_requests 1000;
}
이렇게 고쳐두면 한 놈이 단일 연결에서 폭풍 스트림을 쥐어짜려고 할 때 Nginx가 스트림 한도를 쳐내며 서버 과부하를 막아줍니다.
진짜 간단한 설정인데 이거 하나 안 해둬서 몇 시간 동안 장애 대응하는 엔지니어분들 많습니다.
Nginx 봇넷 차단 limit_req 적용법, IP 폭격 1초 만에 걸러내는 실전 꿀팁
Nginx의 limit_req_zone 지시어로 클라이언트 IP당 초당 요청 수를 제한(예: rate=10r/s)하고 burst 파라미터를 조합하면 비정상적인 HTTP/2 499 에러 폭주 트래픽을 효율적으로 차단할 수 있습니다.
동시 스트림 제한만으로 불안하다면 IP 기반 속도 제한 레이어를 무조건 깔아줘야 합니다.
이건 봇넷이 스트림 취소를 때리든 말든, 클라이언트 IP가 1초에 보낼 수 있는 요청 자체를 제한해 버리는 제로 트러스트 보안 가이드 방식의 근본적 방어벽입니다.
# http 블록에 속도 제한 존 정의 (10MB 메모리, 초당 10회 요청 제한)
limit_req_zone $binary_remote_addr zone=http2_botnet_limit:10m rate=10r/s;
server {
listen 443 ssl http2;
server_name example.com;
location / {
# burst=20으로 순간 트래픽은 허용하되 nodelay로 초과분 즉시 차단
limit_req zone=http2_botnet_limit burst=20 nodelay;
proxy_pass http://backend_app;
}
}
공격 시 Nginx 액세스 로그를 보면 클라이언트가 멋대로 끊어버린 499 에러 코드가 도배되는 현상을 볼 수 있는데요.
위 설정을 적용해 두면 봇넷 트래픽이 지연 없이 바로 503 Service Temporarily Unavailable로 튕겨 나가며 백엔드 서버로 가는 부담을 100% 차단해 줍니다.
무엇보다 Nginx 패키지를 1.25.3 이상 (또는 배포판 최신 보안 패치 버전) 으로 업데이트하는 것이 가장 근본적인 해결책이라는 점도 잊지 마세요!
자주 묻는 질문 (FAQ)
Q. Nginx 1.25.3 이상 버전으로 업데이트하면 Rapid Reset 봇넷이 완전 차단되나요?
최신 버전 패치는 스트림 생성 후 즉시 취소하는 루프 폭격을 자체적으로 탐지하고 제어하지만, 애플리케이션 L7 DDoS 전반을 막으려면 limit_req 설정과 CDN 병행이 필수입니다.
Q. http2_max_concurrent_streams 값을 너무 낮추면 일반 사용자 웹서핑이 느려지나요?
일반적인 웹 브라우저는 한 페이지를 로딩할 때 동시에 30~50개 이상의 스트림을 거의 사용하지 않으므로 64~120 정도로 설정해도 서비스에 전혀 지장이 없습니다.
Q. Nginx 로그에 499 에러가 쏟아지는데 봇넷 공격 징후인가요?
클라이언트가 서버 응답이 나가기 전에 연결을 끊었을 때 499 에러가 발생하며, Rapid Reset 공격 시 이 에러가 초당 수천 건 이상 급증하는 특징이 있습니다.
Nginx HTTP/2 다중화 악용 봇넷 방어 고도화 설정, 지금 서버에 바로 체크해보셨나요?
아직도 기본 설정 그대로 돌리고 있다면 오늘 당장 Nginx 설정 파일 열어서 스트림 제한과 rate limiting 걸어두는 걸 강력 추천합니다.
여러분 서버는 지금 안전하신가요? 봇넷 공격 경험이나 나만의 Nginx 꿀팁이 있다면 댓글로 썰 풀어주세요! 도움이 되셨다면 공유 부탁드립니다 🚀