Nginx Rate Limiting
단시간에 대량 요청을 보내는 DDoS, 브루트포스, 자동화 스캔을 제한한다.
limit_req_zone으로 zone을 정의하고, limit_req로 각 location에 적용한다.
핵심 개념
| 지시어 | 설명 |
|---|---|
limit_req_zone | 제한 기준(키), 메모리 크기, 허용 속도(rate) 정의 |
limit_req | zone 적용 및 burst / nodelay 설정 |
burst | rate 초과 시 대기열에 쌓을 수 있는 추가 요청 수 |
nodelay | burst 범위 내 요청을 지연 없이 즉시 처리 (없으면 rate에 맞춰 지연 처리) |
rate 계산 예시
rate=10r/s→ 초당 10건, 즉 100ms마다 1건 허용burst=20 nodelay→ 순간 최대 30건(10 + 20)까지 허용, 초과분은 즉시 503
Zone 분리 전략
경로 특성에 따라 zone을 분리한다. 하나의 zone으로 전체를 제한하면 정상 트래픽도 영향받는다.
| Zone 이름 | 적용 경로 | 허용 속도 | 용도 |
|---|---|---|---|
general | / (전체) | 30r/s | 일반 페이지 요청 |
api | /api/ | 10r/s | API 엔드포인트 |
admin | /admin/, /actuator/ | 5r/m | 관리 경로 — 사람이 직접 접근하므로 분당 기준 |
전체 설정 예시
# /etc/nginx/nginx.conf — http 블록 안에 선언
http {
# Zone 정의
# $binary_remote_addr: IP당 적용 (binary 형식이 메모리 절약)
# 10m: 약 16만 IP 추적 가능한 메모리
limit_req_zone $binary_remote_addr zone=general:10m rate=30r/s;
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=admin:10m rate=5r/m;
# 제한 초과 시 응답 코드 (기본 503 → 429로 변경)
limit_req_status 429;
include /etc/nginx/conf.d/*.conf;
}
# /etc/nginx/conf.d/your-site.conf — server 블록
server {
listen 443 ssl;
server_name example.com;
# 전체 경로 — 일반 rate 적용
location / {
limit_req zone=general burst=50 nodelay;
proxy_pass http://127.0.0.1:8080;
}
# API 경로 — 더 엄격하게
location /api/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://127.0.0.1:8080;
}
# 관리/모니터링 경로 — 가장 엄격하게
location ~* "^/(admin|actuator|management)/" {
limit_req zone=admin burst=3 nodelay;
proxy_pass http://127.0.0.1:8080;
}
}
burst / nodelay 동작 비교
rate=10r/s, burst=5 로 설정 시 초당 20건 요청이 들어오는 경우:
[ nodelay 있음 ]
→ 15건 즉시 처리 (rate 10 + burst 5)
→ 나머지 5건 즉시 429 반환
[ nodelay 없음 ]
→ 10건 즉시 처리
→ 5건은 100ms 간격으로 지연 처리 (대기열)
→ 나머지 5건 429 반환
API처럼 응답 지연이 민감한 경로는 nodelay 사용을 권장한다.
r/m vs r/s 단위 주의
rate=5r/m처럼 분당(r/m) 단위를 사용하면 브라우저 한 번의 페이지 로드에서도
CSS, JS, 이미지 등 자산 요청이 동시에 여러 건 발생하여 503이 빈번하게 나타날 수 있다.
# ❌ r/m 단위 — 페이지 로드 시 503 발생 가능
limit_req_zone $binary_remote_addr zone=admin:10m rate=5r/m;
# ✅ r/s 단위 권장
limit_req_zone $binary_remote_addr zone=general:10m rate=5r/s;
limit_req_zone $binary_remote_addr zone=admin:10m rate=2r/s;
burst 없이 rate만 설정하면 동시 요청이 즉시 차단되므로 burst 설정 필수:
limit_req zone=general burst=20 nodelay;
limit_req zone=admin burst=5 nodelay;
429 응답 커스텀
server {
# 429 발생 시 커스텀 응답
error_page 429 /rate-limit.html;
location = /rate-limit.html {
root /usr/share/nginx/html;
internal;
}
}
적용 방법
# 설정 검사
sudo nginx -t
# 재시작 없이 반영
sudo nginx -s reload
제한 초과 로그 확인
# 429 발생 확인
sudo grep ' 429 ' /var/log/nginx/access.log | tail -20
# IP별 429 빈도
sudo grep ' 429 ' /var/log/nginx/access.log \
| awk '{print $1}' | sort | uniq -c | sort -rn | head -10