DDoS(분산 서비스 거부) 공격은 비정상적인 디지털 통신 기법을 통해 서버의 리소스를 고갈시키는 사이버 공격입니다. 이는 컴퓨터 세계의 '조직적 습격'이라고 할 수 있습니다. 수많은 악성 요청이 결합되어 하나의 강력한 위협이 되고, 숙련된 관리자가 운영하는 서버조차 마비시킬 수 있습니다. 더욱 문제가 되는 것은, 이러한 게릴라성 웹 전쟁을 감행할 수 있는 경로가 다양하다는 점입니다. 다행히도 서버를 적절히 구성하면 이러한 공격에 맞서 싸울 수 있습니다.
Nginx는 유닉스 계열 시스템에서 널리 사용되는 인기 있는 웹 서버로, DDoS 공격의 효과를 크게 제한할 수 있는 내장 기능들을 갖추고 있습니다.
아래에서 Nginx 기반 서버에서 이러한 위협에 대응할 수 있는 몇 가지 효과적인 방법을 소개합니다.
1. 설정 파일 백업하기
설정을 변경하기 전에 반드시 서버 설정 파일을 백업해 두세요. 아래 명령어로 간단히 백업할 수 있습니다:
sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup-original

백업이 완료되면 다음 단계로 진행할 준비가 된 것입니다.
2. 트래픽 확인하기
서버 트래픽을 지속적으로 모니터링하면 보안을 최적화하고, 추후 추가적인 대응 전략을 구현하기가 훨씬 수월해집니다. Nginx에는 바로 이런 용도로 만들어진 모듈이 포함되어 있습니다.
상태 페이지 설정하기
Nginx에는 일반적으로 "stub status"(http_stub_status_module)라는 모듈이 포함되어 있어, 서버 환경에 손쉽게 상태 모니터링 기능을 통합할 수 있습니다. 먼저 아래 명령어로 해당 모듈이 설치되어 있는지 확인하세요:
nginx -V

또는 grep과 함께 사용하면 더 빠르게 찾을 수 있습니다:
nginx -V 2>&1 | grep -o with-http_stub_status_module

위와 같은 출력 결과가 나타나면 정상입니다. 만약 결과가 없다면 해당 모듈을 포함하여 Nginx를 재설치하거나 재컴파일해야 합니다.
확인용 상태 페이지를 설정하는 것은 간단하지만, 보안을 위해 접근 권한을 최소한(본인의 머신)으로 제한해야 합니다. "/etc/nginx/nginx.conf" 위치에 있는 메인 설정 파일을 열어 시작하세요.

파일을 연 후, 모듈을 활성화하기 위해 "http 지시문"에 아래 코드를 추가합니다. 이때 "localhost", "/status_page", "127.0.0.1" 부분은 본인의 환경에 맞게 변경하세요:
server {
listen 80;
listen [::]:80;
server_name localhost;
##
# Status Page Settings
##
location /status_page {
stub_status on;
allow 127.0.0.1;
allow ::1;
deny all;
}
}
참고: 이 파일을 수정하려면 sudo 권한이 필요합니다.

이제 설정을 테스트합니다:
sudo nginx -t

문제가 없다면 서버에 리로드 신호를 보냅니다:
sudo systemctl reload nginx

상태 페이지에 접속하려면 웹 브라우저에서 server_name 주소 뒤에 "/status_page"를 붙여 접속하거나, curl 같은 명령줄 도구를 사용하면 됩니다. (브라우저 캐시가 자동으로 갱신되지 않을 때 유용합니다.) 예제에서 사용된 curl 명령어는 다음과 같습니다:
curl localhost/status_page

브라우저에서 접속하면 아래 이미지와 같은 화면을 볼 수 있습니다.

접속 로그 확인하기
앞서 설정한 상태 페이지에서 비정상적인 트래픽이 발견되면, 서버의 접속 로그를 확인해 보는 것이 좋습니다. 로그 파일은 "/var/log/nginx/access.log"에 위치하며, 사용된 HTTP 메서드, 접속 시도 날짜/시간, 사용자 에이전트(User Agent), 접근된 페이지 등이 기록되어 있습니다.

3. 연결 수 제한하기
DDoS 공격을 막기 위한 여러 유용한 전술 중에서도, 가장 간단하면서도 효과적인 방법 중 하나는 들어오는 트래픽의 속도를 제한하는 것입니다.
이상적으로는 악성 봇이 사람이 불가능한 속도로 서버를 압도하지 못하도록 접근을 충분히 제한하면서, 동시에 일반 사용자에게는 합리적인 속도를 유지해야 합니다. Nginx에서는 limit_req_zone과 limit_req 지시문으로 이를 구현할 수 있습니다. 아래 코드는 서버가 노출하는 모든 location에서 사용할 메모리와 요청 속도 제한을 설정합니다:
limit_req_zone $binary_remote_addr zone=speedbump:10m rate=10r/s;
"zone"은 사용자 요청을 저장하는 메모리 공간의 이름과 크기(여기서는 10MB)를 지정합니다. "rate"는 Nginx가 매초 허용할 최대 요청 수를 의미합니다(예제에서는 초당 10개). 이 코드를 '규칙'이라고 생각하고, 다음 코드를 그 규칙의 '적용'이라고 이해하면 됩니다:
limit_req zone=speedbump burst=20;
위 코드는 단순히 제한 규칙을 적용하는 것 이상의 역할을 합니다. 평소보다 약간 빠르게 도착한 정상적인 연결을 부드럽게 처리하기 위해 최대 20개의 요청으로 구성된 작은 대기열(queue)도 함께 생성합니다. 규칙과 대기열을 모두 초과하는 요청에는 클라이언트에게 503 오류가 반환됩니다. 두 지시문이 nginx.conf에 적용된 모습은 다음과 같습니다:

4. IP 주소 블랙리스트 처리
서버를 DDoS 공격하는 IP 주소를 파악할 수 있다면, 해당 IP를 블랙리스트에 등록하여 그 IP에서 오는 모든 연결을 차단할 수 있습니다.
아래 코드를 server 지시문에 추가하세요:
location / {
deny 123.123.123.0/28;
# ...
}
5. 특정 파일 요청 차단하기
DDoS 공격이 서버의 특정 파일을 겨냥하는 경우도 있습니다. 예를 들어 WordPress의 xmlrpc.php 파일은 대부분의 WordPress 서버에서 공격 대상이 되는 대표적인 파일입니다. 이런 경우 해당 파일로 향하는 모든 요청을 차단할 수 있습니다. 아래 코드를 server 지시문에 추가하세요:
location /xmlrpc.php {
deny all;
}
위 과정을 따라 하면 대부분의 DDoS 공격을 효과적으로 제한할 수 있습니다. 추가적인 보안 옵션을 적용하고 싶다면 Nginx 공식 문서를 참고하는 것도 좋습니다.