며칠 전에 Nginx에서 DoS, DDoS 관련 설정을 공부해보고 설정한 바 있는데, 이에 대해 간단히 포스팅 해보고자 한다.
공부하며 작성한 내용이기 때문에 오류가 있을 수 있습니다.
악의적으로 서버에 request를 매우 빠르게 지속적으로 넣게되면 서버가 뻗어버릴 수 있다.
이럴때는 시간 당 request 개수를 제한하고, 해당 제한 개수를 초과하게 되면 그 request는 deny 하는 설정을 해주면 된다.
다음 예시를 보자.
limit_req_zone $binary_remote_addr zone=ddos_req:10m rate=5r/s;
server {
# ...
location /login {
limit_req zone=ddos_req;
# ...
}
}
하나씩 살펴보도록 하자.
1) limit_req_zone $binary_remote_addr zone=ddos_req:10m rate=5r/s;
2) limit_req zone=ddos_req;
위와 같이 설정을 모두 마치게 되면 /login 요청에 대해서는 하나의 클라이언트 ip의 request에 대해 1초에 최대 5개까지만 받을 수 있게 되고, 나머지 요청에 대해서는 deny한다.
deny 하게되면 status code 기본값은 503이지만, 다음과 같이 limit_req_status 설정을 통해 status code를 지정해줄 수 있다.
limit_req_zone $binary_remote_addr zone=ddos_req:10m rate=5r/s;
limit_req_status 404;
server {
# ...
location /login {
limit_req zone=ddos_req;
# ...
}
}
만약 초과된 request에 대해 좀 더 허용하고 싶다면, burst를 이용할 수 있다.
다음을 보자.
limit_req zone=ddos_req burst=5;
burst=5가 추가된 것을 확인할 수 있다.
이는 초과된 request에 대해 최대 5개까지를 버킷에 임시로 담아두고, 앞선 request들에 대한 처리가 끝난 후 차례대로 처리하게 하는 설정이다.
그렇다면 위에서 설정했었던 내용과 합쳐서 다음의 내용을 만들면
limit_req_zone $binary_remote_addr zone=ddos_req:10m rate=5r/s;
limit_req_status 404;
server {
# ...
location /login {
limit_req zone=ddos_req burst=5;
# ...
}
}
/login 요청에 대해서는 1초에 최대 10개의 request를 받을 수 있게 된다.
(1초에 5개 처리, 나머지 5개는 버킷에 담아두었다가 나중에 처리)
하나의 클라이언트 ip에서 동시에 여러 request를 넣게 되면 이 또한 서버에 부담을 줄 수 있다.
이럴때는 동시 request 개수 제한을 설정할 수 있다.
limit_conn_zone $binary_remote_addr zone=ddos_conn:10m;
server {
# ...
location /login {
limit_conn ddos_conn 10;
# ...
}
}
하나의 클라이언트 ip당 동시에 최대 10개의 request만 처리하게 해준다.
만약 30개의 request를 동시에 보내게 된다면 나머지 10개만 처리되고 나머지 20개는 deny된다.
request 비율 제한 설정과 거의 동일하므로 더 자세한 설명은 생략하겠다.
특정 ip들에 대해 아예 request를 못하게 제한할 수도 있다.
location / {
deny 123.123.123.3;
deny 123.123.123.5;
deny 123.123.123.7;
# ...
}
더 자세한 내용들은 여기를 참고하자.
악의적으로 request의 커넥션을 최대한 오랫동안 유지시켜 다른 ip에서의 request를 못하게 하는 등의 공격이 있을 수 있다. 이 공격은 Slowloris라는 공격과 많은 관련이 있다.
이것을 방지하기 위해 request의 만료 시간을 설정할 수 있다.
server {
client_body_timeout 5s;
client_header_timeout 5s;
# ...
}
위 설정은 body와 header 각각의 write동작 사이에 최대 시간을 5초로 설정해놓은 것이다.
위와 같이 설정해놓지 않으면 기본값은 60초이다.