대부분의 호스팅 플랜은 DDoS 보호를 약속합니다. 이는 보통 서버에 도달하기 전에 대량의 쓰레기 패킷 홍수(3계층과 4계층)를 걸러내는 것을 뜻합니다. 천 개의 "진짜" 브라우저가 가장 느린 페이지를 동시에 불러오는 것은 막지 못합니다. 이런 애플리케이션 계층(7계층) 공격은 평범한 방문자처럼 보이며, 직접 대처해야 합니다. 배경 지식은 DDoS 보호란 무엇인가를 참고하세요.
차이 이해하기
- 볼륨형 홍수: 네트워크 회선을 가득 채웁니다. 호스트나 업스트림이 걸러 줍니다.
- 프로토콜 공격: 연결 테이블을 고갈시킵니다. 대부분 네트워크 차원에서 처리됩니다.
- 7계층 공격: 정상처럼 보이는 HTTP 요청으로 CPU, 데이터베이스, 워커를 소진시킵니다. 이 공격은 애플리케이션까지 도달합니다.
1단계: Nginx에서 요청 속도 제한
한 주소가 요청할 수 있는 속도에 상한을 두세요. http 블록에 zone을 정의하고 사이트에 적용합니다.
limit_req_zone $binary_remote_addr zone=perip:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=connip:10m;
server {
location / {
limit_req zone=perip burst=20 nodelay;
limit_conn connip 20;
}
location = /login {
limit_req zone=perip burst=3 nodelay;
}
}
로그인과 검색은 비용이 크므로 훨씬 더 엄격한 제한을 두세요.
2단계: 가능한 것은 캐시하기
캐시된 페이지는 제공하는 데 비용이 거의 들지 않습니다. 비로그인 트래픽에 FastCGI 또는 프록시 캐싱을 켜세요. 30~60초만으로도 같은 요청의 홍수가 실제 요청 몇 개로 줄어듭니다.
fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=site:50m inactive=10m;
fastcgi_cache site;
fastcgi_cache_valid 200 60s;
fastcgi_cache_use_stale updating error timeout;
3단계: 적절한 타임아웃 설정
느린 연결 공격은 워커를 계속 붙잡아 둡니다. 제한 시간을 줄이세요.
client_body_timeout 10s;
client_header_timeout 10s;
send_timeout 15s;
keepalive_timeout 15s;
client_max_body_size 5m;
4단계: fail2ban으로 반복 위반자 차단
속도 제한에 걸린 주소를 차단하세요. Nginx는 거부된 요청을 오류 로그에 기록하며, 필터가 이를 찾아낼 수 있습니다.
[nginx-limit-req]
enabled = true
filter = nginx-limit-req
logpath = /var/log/nginx/error.log
maxretry = 10
findtime = 60
bantime = 1h
5단계: 심각해지면 앞단에 프록시 두기
봇 챌린지가 있는 리버스 프록시나 CDN은 VPS 한 대로는 감당할 수 없는 공격을 흡수할 수 있습니다. 원본 IP 비밀 유지하기에 설명된 대로 원본을 보호하는 것을 잊지 마세요. 그렇지 않으면 공격자가 우회합니다.
발생하기 전에 준비하기
- 가장 느린 페이지를 파악하고 고치거나 캐시하세요.
- 급증을 빨리 알아챌 수 있도록 모니터링을 유지하세요.
- 계획을 세우세요: 더 엄격한 제한, 점검 페이지, 더 큰 서버.
UFW 및 fail2ban 가이드의 기본 내용도 함께 적용하세요.