[Nginx] DoS, DDoS 공격 방어 설정

김주원·2020년 8월 25일
4

Nginx

목록 보기
2/2
post-thumbnail

들어가기에 앞서

며칠 전에 Nginx에서 DoS, DDoS 관련 설정을 공부해보고 설정한 바 있는데, 이에 대해 간단히 포스팅 해보고자 한다.

공부하며 작성한 내용이기 때문에 오류가 있을 수 있습니다.

request 비율 제한

악의적으로 서버에 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;

  • limit_req_zone
    • request 비율 제한 설정을 위해 작성
  • $binary_remote_addr
    • 클라이언트 ip 주소에 대한 정보
  • zone=ddos_req:10m
    • 클라이언트 ip에 대한 request 상태를 저장하기 위한 메모리 영역 확보
    • 메모리 영역의 이름을 ddos_req로 설정한 것 (사용자 마음대로 변경 가능)
    • 10m는 10mb의 메모리 영역을 할당하겠다는 것
  • rate=5r/s
    • 클라이언트 ip에 대한 request를 1초(s)에 최대 5개(5r)받을 수 있다는 것
    • s는 분 단위인 m으로도 설정 가능
    • ex) 10r/s -> 1초에 최대 10개
    • ex) 30r/m -> 2초에 최대 1개 (60초에 최대 30개)

2) limit_req zone=ddos_req;

  • limit_req
    • limit_req_zone에서 설정했던 정보를 적용하겠다는 뜻
  • zone=ddos_req
    • 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개는 버킷에 담아두었다가 나중에 처리)

동시 request 제한

하나의 클라이언트 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 접근 제한

특정 ip들에 대해 아예 request를 못하게 제한할 수도 있다.

location / {
    deny 123.123.123.3;
    deny 123.123.123.5;
    deny 123.123.123.7;
    # ...
}

더 자세한 내용들은 여기를 참고하자.

request 만료 시간 설정

악의적으로 request의 커넥션을 최대한 오랫동안 유지시켜 다른 ip에서의 request를 못하게 하는 등의 공격이 있을 수 있다. 이 공격은 Slowloris라는 공격과 많은 관련이 있다.
이것을 방지하기 위해 request의 만료 시간을 설정할 수 있다.

server {
    client_body_timeout 5s;
    client_header_timeout 5s;
    # ...
}

위 설정은 body와 header 각각의 write동작 사이에 최대 시간을 5초로 설정해놓은 것이다.

위와 같이 설정해놓지 않으면 기본값은 60초이다.

레퍼런스

profile
자기계발 블로그

0개의 댓글