어느날 log를 보는데 대량의 api가 같은 ip로(해외) 난사가 되어있는걸 발견했다.
beta같은 환경은 이미 nginx에서 ip제한을 걸어두었는데,
live환경에서는 ip제한을 걸어두기가 애매해서 어떻게 할까 하다가 nginx에서 시간당 ip별 횟수제한을 걸 수 있는 방법을 찾아서 시도해보았다.
nginx.conf
또는 해당 서버의 설정 파일에서 아래와 같이 설정한다.
http {
# IP 기반 요청 제한 설정 (초당 4번 허용)
limit_req_zone $binary_remote_addr zone=perip:10m rate=4r/s;
server {
listen 80;
server_name example.com;
location / {
# IP 기반 요청 제한 적용, 초당 4회 요청 이상 시 503 응답
limit_req zone=perip burst=4 nodelay;
proxy_pass http://backend;
}
}
}
limit_req_zone $binary_remote_addr zone=perip:10m rate=4r/s;
$binary_remote_addr
: 클라이언트의 IP 주소를 기준으로 제한.zone=perip:10m
: 공유 메모리 영역(perip)을 10MB 크기로 설정(약 16만 개의 IP 저장 가능).rate=4r/s
: 초당 4번의 요청만 허용.
limit_req zone=perip burst=4 nodelay;
burst=4
: 초과 요청을 최대 4개까지 허용하고 이후부터는 제한.nodelay
: burst 허용 내에서도 즉시 처리(지연 없음) /
nodelay가 없다면 초과 요청이 발생하면 순차적으로 대기 후 처리된다.- 요청이
4r/s
를 초과하면503
(서비스 사용 불가) 응답.
이렇게 설정해주면 된다.. (from GPT)
이렇게 설정을 했더니.. 해당 도메인을 타고오는 모든 url에서 ip제한이 걸리기 시작했다..
대표적으로.. 프론트화면도 이미지같은것 렌더링시 지연 혹은 에러 이슈가 발생했다.
그래서, 처음에 이것저것 설정을 해보았고 결과적으로 서버에 오는것만 ip제한을 걸도록 범위를 구체화하였다.
location / {
limit_req zone=perip burst=4 nodelay;
proxy_pass http://backend;
}
이렇게 설정하면, 해당 도메인 하위단의 주소 모두 ip제한이 걸려서
location /api {
limit_req zone=perip burst=4 nodelay;
proxy_pass http://backend_api;
}
}
이렇게, 만약 서버가로 가는 주소가 /api 라 한다면..
위에처럼 서버주소로 가는 주소들만 ip제한이 걸리도록 수정했다.
이렇게 설정하면, 부하도 방지할 수 있고, ip제한도 걸 수 있다.
설정하지 않았을 때, default값은 서버가 처리할수 있는 양만큼의 값들을 모두 수용한다고 한다.