DDoS 어디까지 방어해봤니?

DDoS란? DDoS(Distributed Denial of Service)는 웹사이트 또는 네트워크 리소스 운영이 불가능하도록 악성 트래픽을 대량으로 보내는 공격입니다.

서비스가 안 돼요

때는 바야흐로 무더운 여름 날☀️. 고속도로 아스팔트의 열기 사이로 아지랑이가 몽글몽글 피어오르는 출근길이었다. 나를 회사로 인도해주던 스마트폰 네비게이션 화면이 수많은 알림과 빨간색 메시지로 가득찼다. Aka. 평화로웠던 나의 출근 시간이 빨갛게 물든 시간.

<그림 1> 슬랙(Slack) 서비스 알람 채널
<그림 2> 운영 중인 서비스의 비정상 동작으로 인한 상태 코드 이상 알림

서비스 제공사가 제일 두려운 것이 <그림 1>, <그림 2>와 같은 서비스 장애 알림이다. 나 또한 이러한 알림 메시지가 오지 않기를 늘 바라고 있다. 놀란 가슴을 진정시키고 서비스 장애의 원인부터 파악하려 했다. 그 순간, DDoS 공격 알림 채널에 엄청나게 많은 메시지가 쏟아졌다. 그렇다. 서비스 장애를 유발한 원인은 다름아닌 DDoS 공격이었다.

<그림 3> DDoS 공격 IP 차단 채널

트래픽 지진해일을 막아보자

DDoS(Distributed Denial of Service)는 웹사이트 또는 네트워크 리소스 운영이 불가능하도록 악성 트래픽을 대량으로 보내는 공격이다. 한국어로는 ‘분산 서비스 거부 공격’이라고 부른다.

DDoS는 다수의 컴퓨터나 기기에서 타겟 서버(victim)로 대량의 요청을 보내 서버가 요청을 처리하지 못하고 다운되거나 느려지게 만들어 서비스를 중단시킨다. 악성코드에 감염된 컴퓨터 또는 IoT 기기를 이용해 공격하는데, 이러한 기기를 좀비 PC 또는 좀비 컴퓨터(Zombie computer)라고 부른다. C&C 서버(Command & Control Server)에 의해 제어되는 좀비 컴퓨터의 집합은 봇넷(Botnet)이라고 한다.

<그림 4> 1차 DDoS 공격 트래픽
<그림 5> 2차 DDoS 공격 트래픽

일반적인 서비스사라면 DDoS 공격을 받는 입장이겠지만, 구름은 구름IDE라는 클라우드 컨테이너 기반의 통합개발환경(IDE)을 서비스해 DDoS 공격을 하는 입장(?)이 되기도 한다. 이로 인해 DDoS를 탐지하고 방어하기 위한 여러 정책을 운영하고 있다. 

그렇다면 위와 같이 예상치 못한 트래픽이나 공격으로 인한 장애를 극복하는 방법에는 어떤 것이 있을까? 가장 기본적인 몇 가지 방법을 함께 살펴보기로 하자.


1. 무차별 대입 공격으로부터 서버를 보호하는 Fail2ban

Fail2ban은 침입 차단 소프트웨어 프레임워크로, 무차별 대입 공격으로부터 서버를 보호합니다.

시나리오

서비스가 공격받을 때, 1차적으로 모든 트래픽을 받아주는 웹 서버(Web Server)에서 DDoS를 방어하는 방법을 알아보자. 웹 서버는 많이 이용되고 있는 Nginx를 이용하고 Nginx의 Error 로그와 Fail2ban을 이용해 공격을 방어해볼 것이다. 트래픽 생성은 HTTP/HTTPS 스트레스 테스터인 오픈소스 도구 Siege를 이용했다.

설치

Fail2ban 실습 환경은 따로 구축할 필요 없이 구름IDE에서 Ubuntu 18.04 Blank 컨테이너를 생성해 진행한다.

크롬 웹브라우저에서 구름IDE를 열고 [새 컨테이너]를 누른다. 구름IDE는 무료지만 가입해야만 쓸 수 있다. 가입하지 않았다면 도움말을 참고해 회원 가입을 하자.

<그림 6> 구름의 컨테이너 기반의 통합개발환경 구름IDE

컨테이너 이름은 적당히 짓고, 소프트웨어 스택 중 [Blank]를 선택한다(<그림 7> 참고). 템플릿으로는 빈 프로젝트가, OS로는 Ubuntu 18.04 LTS가 선택돼 있을 것이다. 따로 변경할 것은 없다. [생성하기] 눌러 컨테이너를 생성하자. 컨테이너가 생성되면 바로 실행하자.

<그림 7> 컨테이너마다 선택 가능한 소프트웨어 스택들

Nginx 설치하기

다음으로는 Nginx를 설치할 것이다. 구름IDE 하단에 위치한 ‘터미널’ 클릭하고 다음 명령어를 입력한다(<그림 8> 참고). 그러면 리눅스 패키지가 최신 상태로 업데이트된다.

apt-get update
<그림 8> 구름IDE 모습. 하단의 터미널에서 리눅스 명령어를 실행할 수 있다.

Nginx 웹 서버는 다음 명령어로 설치할 수 있다.

apt-get install nginx

DDoS 공격을 탐지하려면 Nginx에도 몇 가지 설정이 필요하다. 구름IDE 터미널에서 vi 명령어로 /etc/nginx/sites-enabled/default 파일을 열고, <그림 9>와 같이 최상단에 아래 코드 한 줄을 추가한다.

vi /etc/nginx/sites-enabled/default
limit_req_zone $binary_remote_addr zone=ddos_limit:10m rate=10r/s;
<그림 9>/etc/nginx/sites-enabled/default 최상단에 코드를 추가하면 된다.
💬 vi 에디터 사용법에 익숙하지 않다면 KLDP의 vi 에디터 사용법 글을 참고하세요.

다음 아래로 스크롤하다보면 ‘location / {’ 코드가 보일 것이다. 다음과 같이 그 중괄호({}) 안에 다음 세 줄을 추가하고 저장한다.

limit_req zone=ddos_limit burst=10 nodelay;
real_ip_header    X-Forwarded-For;
set_real_ip_from 0.0.0.0/0;
<그림 10>/etc/nginx/sites-enabled/default 내용의 중간 location 부분에 코드 세 줄을 추가한 모습

이걸로 Nginx쪽 설정은 끝났다. 터미널에서 다음 명령어를 입력해 Nginx를 실행하자. 잘 따라왔다면 별다른 문제 없이 Nginx가 실행될 것이다.

service nginx start

Fail2ban 설치하기

Fail2ban은 다음 명령어로 설치할 수 있다.

sudo apt install -y fail2ban

보통은 설치 완료 후 Fail2ban이 바로 실행되지만, 구름IDE에서는 Fail2ban의 기본 설정으로 바라보고 있는 sshd 데몬의 로그를 확인할 수 없어 실행에 실패한다(<그림 11> 참조).

<그림 11> Fail2ban 서비스 실행에 실패한 상태

Fail2ban의 설정 파일의 디렉터리 구조를 보면 action.d, fail2ban.d, filter.d, jail.d 등 설정 관련 파일이 많다(<그림 12> 참고). 지면 관계상 다 다룰 수 없어 DDoS 방어에 핵심적인 몇 가지만 소개하겠다.

<그림 12> Fail2ban 설정 파일 구성

Fail2ban 설정 파일 중 jail.local을 다음과 같이 수정하면 Nginx로 오는 DDoS 공격을 방어할 수 있다. 각각의 설정은 주석으로 설명을 남겼으니 읽어보기 바란다. 궁금한 점은 댓글이나 메일로 문의하기 바란다. 아! 문의 전에 좋댓구림(좋아요, 댓글, 구독, 알림설정)은 잊지 말자.

# /etc/fail2ban/jail.d/jail.local

[nginx-limit-req]
enabled = true                       # 설정 on/off
filter = nginx-limit-req             # 사용할 필터 이름
findtime = 60                        # 모니터링 시간 (60초)
maxretry = 10                        # 60초 동안 10번 이벤트 발생 시 차단
bantime = 10800                      # 차단 시간 (3시간)
port = http, https                   # 차단 대상 포트
protocol=tcp                         # 차단 대상의 프로토콜
banaction = iptables-multiport       # 차단 방식 선택 ( iptables 이용 )
action_with_ban = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s"]
action = %(action_with_ban)s    # 차단 액션 등록
logpath = /var/log/nginx/*error.log  # 모니터링할 로그 파일 경로

앞서 문제가 된 sshd 데몬은 /etc/fail2ban/jail.d/defaults-debian.conf 파일을 다음과 같이 수정해서 비활성화하자. [sshd] 바로 밑에 있는 enabled의 값을 true에서 false로 바꾸고 저장하면 된다.

# /etc/fail2ban/jail.d/defaults-debian.conf

[sshd]
enabled = false

Fail2ban을 사용한 DDoS 탐지 및 방어의 원리는 이렇다. 악성 사용자가 DDoS 공격을 시도하면 Nginx가 특정 IP에 대해 서버가 응답하기 전에, Nginx 설정 파일에서 설정한 대기열 10개를 넘어서면 요청한 IP와 limit_req log를 error log에 남긴다. 

Fail2ban은 이 error log을 실시간으로 모니터링한다. 1분 동안 해당 로그가 10번 이상 발생해 임계치에 도달하면 서버 방화벽(iptables)을 이용해 해당 IP의 TCP 80, 443번 포트를 차단한다. DDoS 공격이 Nginx로 도달하지 못하게 막아 불필요한 부하로 서비스가 멈추는 것을 방지하는 식이다.

자, Fail2ban도 실행하자. Nginx 실행과 다르진 않다. 터미널에서 다음 명령어를 입력하기만 하면 된다.

service fail2ban start

siege 설치하기

siege는 대표적인 오픈소스 기반의 스트레스 테스트 도구다. siege도 구름IDE 터미널에서 다음 명령어를 입력해 설치하자.

sudo apt install siege -y

따로 설정할 것은 없다. 실제로 방어가 되는지 확인해보자. 사용한 siege 명령어는 다음과 같다. 

siege -b -c 100 localhost -v

siege로 100명의 사용자가 Nginx 서버로 요청을 보내는 테스트를 진행하면 <그림 13>과 같이 얼마 지나지 않아 siege 테스트가 중단될 것이다.

<그림 13> siege 명령어에 대한 응답 실패

다음 명령어로 Nginx 에러 로그를 확인하면 ddos_limit 문자와 함께 웹 서버가 해당 요청에 더 이상 응답하지 않는 것을 확인할 수 있다.

tail -f /var/log/nginx/error.log
<그림 14> limit_req를 넘겨 기록된 Nginx 에러 로그

2. 웹 익스플로잇과 봇으로부터 보호해주는 AWS WAF

AWS WAF(Web Application Firewall)는 가용성에 영향을 미치거나 보안을 훼손, 또는 과도한 리소스를 소비하는 일반적인 웹 익스플로잇(컴퓨터나 컴퓨터 관련 전자제품의 보안 취약점을 이용한 공격 방법) 및 봇으로부터 애플리케이션을 보호합니다.

AWS 클라우드를 이용해 서비스를 한다면 AWS에서 제공하는 WAF로 DDoS나 무차별 공격과 같은 다양한 공격에 대응할 수 있다.

다만 AWS WAF는 무료인 Fail2ban과 달리 유료 서비스다. 따라서 과도한 요금이 부가되지 않도록 실습에 주의하자.

<그림 15> AWS WAF 비용

설정

AWS Console로 접속 후 서비스 검색창에서 waf를 입력하자. 가장 처음에 나오는 WAF & Shield를 클릭해 WAF 서비스로 이동하자.

<그림 16> AWS Console에서 쉽게 접근할 수 있는 AWS WAF

AWS WAF 서비스 대시보드로 이동하면 <그림 17>과 같이 WAF Welcome 페이지가 반겨준다.

<그림 17> AWS WAF 대시보드 화면

먼저 AWS WAF 대시보드 화면 왼쪽에서 [Web ACLs] 메뉴를 클릭하고 서비스가 동작 중인 리전(Region)으로 이동한다(<그림 18> 참고).

<그림 18> ACL 생성을 위한 리전을 선택 메뉴

우측 상단에 있는 [Create web ACL]를 클릭해 새로운 ACL 작성 페이지로 이동한다. 

<그림 19> ACL 생성 버튼

Name에 적당한 이름을 적고 하단의 [Next]를 눌러 적용하고자 하는 규칙을 추가한다.

<그림 20> Web ACL Step 1 작성 예

추가할 규칙은 5분간 설정한 임계치 이상의 요청이 있으면 이상 행위로 보고 차단하는 간단한 규칙이다. 이러한 규칙을 추가하는 이유는 DDoS 공격은 대량 요청을 짧은 시간 내에 보내기 때문이다. 특정 공격은 천천히 요청을 보내서 이러한 규칙을 통과하기도 하는데, 여기서는 지면 관계상 다루지 않는다. 

Step 2에서는 [Add rules] → [Add my own rules and rule groups]를 클릭해 다른 규칙을 추가할 수도 있다.

<그림 21> Web ACL Step 2 사용자 규칙 추가

이제 규칙을 추가해보자. Rule builter를 선택하고 Rule 이름을 지정하자.

<그림 22> Web ACL Step 2 사용자 규칙 추가

Rate Limit은 100으로 설정해 5분간 100번의 요청을 받으면 잠시 사용자의 요청을 차단하도록 하자. AWS WAF는 차단(Block)뿐 아니라 모니터링만 할 수 있는 Count, 우리가 많이 보는 “당신은 로봇입니까?”를 묻는 CAPTCHA와 브라우저 검증을 하는 Challenge 등을 선택할 수 있다(<그림 24> 참고).

<그림 23> Rate limit을 100으로 설정한다.
<그림 24> Action을 Block으로 설정하자.

이렇게 설정하면 Overview 화면에서 요청에 대한 상황을 그래프로 확인할 수 있다. 차단되는 로그나 허용되는 모든 트래픽을 CloudWatch로 확인할 수 있다. 이 경우 CloudWatch 또한 비용이 추가로 청구될 수 있다.

<그림 25> rate limit에 걸린 트래픽

지금까지 AWS의 유료 서비스인 WAF로 트래픽을 막는 가장 손쉬운 방법을 살펴봤다. 마우스 클릭 몇 번만으로 규칙을 만들 수 있어 크게 어렵진 않았을 것이다. AWS WAF는 소개한 기능뿐 아니라 다양한 방식으로 공격을 판별하는 규칙을 제공한다. AWS WAF의 여러 기능은 보통 유료인 경우가 많으니 과도한 비용이 청구되지 않도록 주의하기 바란다.

3. 자원 크기를 자동으로 조절하는 Auto Scale

오토스케일링(Auto Scaling)은 클라우드의 유연성을 돋보이게 하는 핵심 기술로 CPU, 메모리, 디스크, 네트워크 트래픽과 같은 시스템 자원의 메트릭(Metric) 값을 모니터링해 자원의 크기를 자동으로 조절합니다. 이를 사용하면 사용자는 예상치 못한 서비스 부하에 효과적으로 대응하고 비용을 절감할 수 있습니다.

실제 공격뿐 아니라 갑작스러운 사용자 증가, 혹은 대응하기 어려운 새벽 시간에도 서비스에 문제가 생기지 않게 하는 대표적인 방법이 오토스케일이다.

<그림 26> Auto Scale 구성도

설정

Auto Scaling 실습은 EC2 인스턴스와 Launch Template, 로드밸런서까지 설정돼 있다는 가정 하에 진행한다. Auto Scaling은 AWS EC2 서비스에서 설정 가능하다. 일단 AWS console에 로그인하고 EC2 서비스를 열자.

<그림 27> Console Home에서 EC2 로 이동

EC2 서비스 페이지에서 왼쪽 가장 하단 메뉴를 보면 Auto Scaling Groups 메뉴를 찾을 수 있다.

<그림 28> Auto Scaling Groups 메뉴

Auto Scaling Group 생성 페이지에서 우측 주황색 버튼인 [Create Auto Scaling group]을 클릭한다.

<그림 29> Auto Scaling Groups 페이지

적절한 이름을 넣고 그 아래 Launch template에 기존에 사용 중인 Launch template를 선택하자(<그림 30> 참고).

<그림 30> Auto Scaling Groups 생성

<그림 31>은 Network를 설정할 수 있는 설정 페이지이다. Auto Scaling Groups에 등록하려는 EC2 인스턴스가 있는 VPC를 먼저 선택한 후, Availability Zones와 서브넷(Subnets)을 선택하고 바로 [Skip to review]를 누르면 다른 복잡한 설정 없이 바로 Auto Scaling Groups를 생성할 수 있다.

하지만 우리는 조금 더 자세한 설정을 하기 위해 [Skip to review] 대신 [Next] 버튼을 눌러 다른 옵션들도 살펴볼 것이다.

<그림 31> Auto Scaling Groups 생성 – 2

다음 버튼을 누르면 Auto Scaling Group와 로드밸런서 연결 옵션이 나타난다. 로드밸랜서와 연결하지 않거나, 기존 로드밸랜서와 연결하거나, 새로운 로드밸랜서를 연결하는 선택지 중 하나를 선택할 수 있다. 여기서는 [Attach to an existing load balancer]와 [Choose from your load balancer target groups]을 선택해 로드밸랜서 타깃 그룹과 연결하도록 하자.

<그림 32> Auto Scaling Groups 생성 – 3

앞으로도 두 가지 설정이 더 남았다. 그러나 여기까지만 설정해도 Auto Scaling Groups을 사용하는 데는 무리가 없다. 눈썰미가 있는 사람은 설명 메뉴에서 ‘optional’이란 단어에서 이미 눈치를 챘을 테지만.

첫 옵션은 그룹 크기다. 원하는 기본 용량(capacity)과 최소, 최대 용량을 지정해 Scaling 범위를 지정하면 된다.

두 번째 옵션은 Scaling 정책이다. 여기서는 어떠한 조건에서 Scaling을 할 건지 정책을 설정할 수 있다. 기본 설정은 평균 CPU 사용량이 50%가 되면 스케일링하게 되어 있다.

그대로 두고 [Skip to review]를 눌러 설정을 최종 점검하자. 이상이 없다면 [Create Auto Scaling group]을 클릭해 Auto Scaling Groups을 생성하자.

<그림 33> Auto Scaling Groups 생성 – 3

모든 설정을 마치면 다음과 같이 Auto Scaling Groups이 생성된다. 이제 서비스가 사용하는 EC2 CPU 리소스 사용량에 따라 최대 8대까지 인스턴스가 추가로 생성되게 된다.

팁 하나를 더 알려드리면, 생성한 Auto Scaling Groups의 Desired capacity을 편집하면 수동으로 Scaling을 할 수 있다.

<그림 34> Auto Scaling Groups 생성 – 4

마치며

서비스 규모가 점점 커질수록 외부에서 들어오는 Abuse나 취약점 공격은 늘어날 수밖에 없다. 날마다 새로운 공격 기법과 취약점이 난무하는 오늘날 서비스를 가장 쉽게 공격할 수 있고, 최악의 경우 서비스 멈추게 할 수 있는 DDoS 공격에 대처할 수 있는 세 가지 방법을 살펴봤다. 소개한 세 가지 방법 말고도 DDoS에 대응할 방법은 정말 다양하다. 

가장 기본적인 방법만 소개했지만, DDoS 공격뿐 아니라 APT나 취약점 공격 등 수많은 공격으로 인해 골머리를 싸매고 있는 인프라 운영팀과 보안팀에 이 글이 작은 도움이 되길 바라며 글을 마친다.  

참고자료