brunch

Nginx 마스터링-10

웹서버(Nginx)로 흐르는 서비스거부 공격 패킷 탐지 및 분석

by Younggi Seo





Cloudflare(클라우드 플레어)는 광범위한 네트워크 기능과 특히, 보안에 초점을 둔 웹프락시(Proxy, 웹호스팅을 위한 대리인 서버) 혹은 CDN(Contents Delivery Network) 서비스 공급업체이다. 이 Cloudflare를 통해서 DDoS(분산서비스거부) 공격을 아래의 *Magic Transit, 애니캐스트라는 네트워크 주소를 전달하는 방식을 통해 공격 트래픽을 쪼개서 다른 경로로 내보낼 수 있다.

* Magic Transit(매직 트랜싯) : 기업의 전체 네트워크 인프라로 들어오는 DDoS 공격을 클라우드플레어 네트워크에서 먼저 필터링하고 정상 트래픽만 보내주는 서비스다.

(발췌 : https://share.google/aimode/uDdElxBZdIeKYKj7k)



한국 KISA에서 제공하는 '사이버대피소'와 같은 공격성 트래픽을 바이패스(bypass, 우회)시키는 것은 대규모의 네트워크 패킷이 공격인지의 여부(패턴)를 탐지해야 하는데, 공격의 패턴이 매번 동일하지 않기 때문에 확률적으로 방어 가능성이 떨어진다.


Cloudflare의 CDN 서비스가 좋은 것 중 하나가 서비스 이용 고객(다운스트림 Client)은 웹서버에 직접 연결하지 않고 Cloudflare의 '웹캐시 서버(Edge Router)'로만 트래픽이 흐른다는 거고, 여기서 트래픽 필터링이 가능하다. 이 서비스의 목표는 인터넷의 모든 구간(다른 네트워크)과 상호연결을 수행하여 연결 기반을 넓히고 대기시간(Latency)을 줄이며 일반 비용(서비스 접속 시간)을 줄여서 고객에게 전달하는 효율성을 높인다고 앞서 공유한 팟캐스트의 연사 Erick Seidel이 말한다.


클라우드 보안팀에서 근무할 때, 요즘 뜨는 AI 서비스를 이용하고 있는 한 고객사 문의를 미리 테스트하고자, 클라우드 서비스 중 과금 비용이 어마어마한 분산 서비스 플랫폼을 활성화한 적이 있다. 아뿔싸, 깜빡하고 테스트 이후에 해당 서비스 해지를 안 했는데 불과 2개월여만 몇 천까지 요금이 튀어서 네이티브 클라우드 서비스 제공업체(CSP) 본사 담당자와 10여 통 이상 메일을 주고받으면서 과금된 비용을 회삿돈에서 먹튀 되지 않도록 협의했고, 운이 좋게도 처음 발생한 사고(?)였기 때문에 초기 요금만 제외하고 전부 돌려받았다.


이때 이 클라우드 계정 서비스를 함께 무료로 이용하고 있었던 팀원들의 다른 서비스에 대한 이용도 못하게 증발시켜서 그룹 채팅방에 장문의 사과문을 남겼다. 팀원 중 한 명이 필자의 이런 불규칙적인 서비스 이용 행위를 '패턴(규칙성)'이라는 용어로 비유하면서 위로의 답변을 해줬다.


공격에서도 이러한 규칙이 정형적(똑같은 규칙이 반복)이라면, 이 패턴을 미리 시그니처(정규표현식을 활용해서 방어 솔루션에서 필터링이 가능한 정책 리스트)로 일반화시킨다. 그래서 그와 비슷한 패턴의 공격이 발생하면 방어 솔루션(DDoS 보안 솔루션이나 웹방화벽)에서 필터링해서 차단시켜 버리거나, 아니면 서비스를 유지시키기 위해 아예 보안솔루션을 일시적으로 셧다운 해서 바이패스(Bypass, 우회)시킬 수가 있다.


하지만 패턴이 일정하지 않으면, 대용량의 트래픽이라도 패킷 자체가 탐지가 안되어 보안솔루션의 제한 가용량(Rate Limitation)을 넘겨 서비스 마비가 된다. 그래서 필자가 아는 KISA에 종사하신 네트워크 전문가 분에게 직접 물어봤을 때도 DDoS 공격의 근본적인 해결책은 없다고 대답해 주신 거다.


그럼에도 불구하고, Cloudflare는 초당 100 테라비트(10의 12승으로 1조 개)의 패킷이 한 번에 몰리는 트래픽 과부하 패턴을 보이더라도 서비스 화면이 뜨는 것에 지장이 없다고 한다. 공격(봇넷)의 강점, 분산 네트워크를 오히려 약점으로 뒤바꾸게 할 수 있는 Anycast*라는 네트워크 기본 원리를 활용한 역발상이다.


Cloudflare의 아키텍처에서 물(DDoS 트래픽)은 종점에 도달하기도 전에 이 모든 다른 강에 분산된다.

* Anycast(애니캐스트) : 시스템은 웹에 분산되어 있고 트래픽을 아주 많이 생성하므로 일반적인 Unicast(유니캐스트)로 연결된 시스템을 압도(서비스 마비)할 수 있지만, Anycast 네트워크를 사용하면 트래픽을 직접 처리하는 하나의 원본 서버 대신 로드를 다른 사용 가능한 데이터 센터에 분산시킬 수도 있다.

(발췌 : https://www.cloudflare.com/ko-kr/learning/cdn/glossary/anycast-network/)







저번 세션에서 우분투 가상머신(VM)에 nginx를 배포해 봤으니, 여기로 DoS(Denial of Service, 서비스 거부) 공격 중 하나인 Slowloris 공격(패킷을 쪼개서 실제 정상 패킷이 아닌 트래픽을 흘려보냄) 세 가지를 시도해서 탐지되는 패킷의 페이로드(내용)를 T-Shark라는 와이어샤크 CLI모드용으로 확인해 보겠다.


1. 공격서버(Kali Linux) 세팅

1) 로컬호스트에서 SSH로 공격서버 접속

칼리는 본래 ssh client는 설치되어 있어도 ssh server가 없기 때문에 openssh server를 따로 설치했다.

SSH 서비스 시작 및 활성화


2) 공격 서버 접속

맥북 터미널(Zshell)에서 칼리 리눅스 서버로 접속한 화면



2. 공격 타깃 서버(Ubuntu Server) 세팅

1) T-shark (Wireshark의 CUI(Command User Interface) 버전) 설치

$ sudo apt update && sudo apt install tshark

Tshark라는 리눅스 CLI모드에서 패킷 탐지가 가능한 소프트웨어를 설치하면 위와 같은 설정 화면이 뜨는데, No를 선택하면 슈퍼유저(root)만 패킷탐지 실행이 가능하다.

2) T-shark 패킷 탐지

tshark 설치 후 버전확인
-V(대문자) 플래그를 쓰면 캡처된 패킷의 모든 상세 사항을 덤프로 떠서 보여준다.
tshark는 레거시 유닉스 전문가처럼 리눅스 터미널에서 패킷을 펼쳐 보일 수 있다. tcpdump처럼, 또는 이 브런치 이후 다룰 eBPF와도 비슷하다.
-D 플래그를 사용해서 패킷 캡처 목적으로 사용할 수 있는 모든 인터페이스를 출력해 본 뒤, 해당 인터페이스(enp0s8)로 패킷 캡처를 시작한다.


3. DoS Slowloris 공격 및 패킷 탐지

1) 공격 스크립트 실행

필자의 github(깃헙)에서 참조할 수 있다. 복사해서 파이썬 파일로 생성한다. Vim(Vi 편집기)를 열어서, 소스코드를 붙여 넣기하고 저장한다.

vim slowloris.py


생성한 파일을 실행하면 아래와 같이 공격 툴을 설치하고, 다른 공격툴을 설치하기를 계속 진행할 건지 묻는다.


아래 화면처럼 IP를 묻는데, 공격대상(우분투 서버)의 로컬아이피(터미널 왼쪽 사이드 화면 타이틀에 보임)를 입력하면 공격이 시작된다.

at> 프롬프트가 뜨는데, 공격 시작 후 3분여 정도 지난 뒤 ctrl + D로 두 가지의 다른 DoS 공격을 연이어서 할 수 있다.


2) 공격 패킷 탐지 및 확인

공격 대상 서버에서 트래픽이 어떻게 바뀌는지 확인할 수 있다. Tshark를 통해 enp0 인터페이스를 통해 들어오는 패킷의 페이로드(내용)가 와이어샤크 GUI의 탐지화면과는 달리 색상변화가 없어서 대략 난감하다...

Rudy DoS 공격(위)과 HTTP READ DoS 공격 시 패킷 캡처(아래)
정상적인 패킷이 아니라는 게, SYN(통신 요청) - ACK(통신 승낙) 순이 아니라, RST(재요청)이 WIN(window slide) 값이 0인 채로 응답하는 것만 확인가능하다

그래서 구글 제미나이를 통해 해당 DoS (HTTP Get flooding / Rudy / Http read) 공격 탐지를 위한 T-shark 명령어를 주문했다.

tshark -r capture.pcap -Y "tcp.window_size == 0 and ip.addr == 192.168.1.10"

tshark -r capture.pcap -Y "ip.addr == 192.168.1.10" -T fields -e frame.time -e ip.src -e tcp.window_size -e http.request.method -e http.content_length



이 Slowloris(슬로로리스)라는 DoS 공격은 완전한 패킷을 보내는 듯 하지만, 사실 HTTP 요청의 일부일 뿐이라서, 탐지되는 패킷을 정상으로 받아들인다. 즉, 비정상적인 형태로 만들어진 것이 아니라, 정상적이면서 부분적인 요청을 보낸다. 그렇게 해서 침입탐지 시스템(IDS)이나 호스트 보안 모니터링 시스템은 이 트래픽이 악성이라는 경고를 하지 않으며, 심지어 의심스럽다고 보지도 않는다.


'Slow~loris' 말 그대로 시간제한(timeout) 기본 값이 60초라고 가정하고, 연결이 닫히기 직전인 59초에 연결을 다시 연다. 이 Slowloris 공격은 기다리는 시간 내내 연결 요청 일부분만 그저 계속해서 보낸다. 끝내 웹 서버에서 허용하는 최대 연결 개수 한계치에 도달하거나 유입되는 진짜 연결 요청을 웹 서버가 거절하게 만든다.


웹서버(Apache / IIS / Nginx)에서 DoS 공격을 대비하기 위한 설정변수

아파치 웹서버에서 그 파라미터는 KeepAliveTimeout과 MaxKeepAliveRequests라고 하고, MS의 IIS에서는 connectionTimeout과 maxConnections다. Nginx에서도 마찬가지로 이 공격을 대비해서 건드려야 하는 HTTP 모듈의 변수들을 아래와 같이 조정할 수 있다.


http {
client_header_timeout 5s;
client_body_timeout 5s;
send_timeout 5s;
#... 다른 설정들...
}



다음 파트부터는 'BPF를 활용한 리눅스 시스템 트레이싱'이라는 서적을 참조해서 리눅스 커널 단의 tcpdump와 같은 BPF(Berkely Packet Filter)에 대해서 다루겠다.

keyword