서버를 DoS하는 방법

발행: (2026년 1월 18일 오전 05:17 GMT+9)
8 min read
원문: Dev.to

Source: Dev.to

번역을 진행하려면 실제 텍스트 내용이 필요합니다. 현재 제공된 내용은 소스 링크뿐이므로, 번역할 본문을 알려주시면 한국어로 번역해 드리겠습니다.

Disclaimer

이 실험은 내가 소유한 시스템을 이용한 통제된 홈 랩에서 수행되었습니다. 실제 시스템은 손상되지 않았습니다. 이는 교육 목적으로만 사용됩니다.

시작은 이렇게

사이버 보안을 배우는 많은 사람들처럼, 나는 서비스 거부(DoS) 공격이 거대한 봇넷, 엄청난 대역폭, 그리고 할리우드 수준의 해킹을 필요로 한다고 생각했었다. 하지만 그렇지 않다는 것이 밝혀졌다. 필요한 것은 취약한 서버와 그 취약점을 이용할 방법뿐—악성코드도, 특수한 익스플로잇도 필요 없고, 단지 잘못 설계된 애플리케이션과 할 수 있다는 태도만 있으면 된다.

DoS vs. DDoS

특징DoS (Denial of Service)DDoS (Distributed Denial of Service)
출처단일 출처 (일대일)다수의 손상된 장치 (다대일)
실행시작 및 차단이 더 간단함탐지, 완화가 더 어려우며 영향이 큼
트래픽제한된 양대규모 분산 트래픽
일반적인 사용소규모 테스트 또는 내부 악용공공 서비스에 대한 대규모 공격

이 실험에서는 한 대의 머신을 사용해 목표를 공격하므로 DoS 시나리오입니다.

내가 만든 실험실

Oracle VirtualBox를 사용하여 작은 격리된 실험실을 구축했습니다:

  • Kali Linux → 공격자 머신
  • Ubuntu Linux → 대상 머신

두 VM은 Host‑only network를 통해 연결되어 있어, 인터넷과 완전히 격리된 상태에서 서로 통신할 수 있었습니다. 이를 통해 실험을 합법적이고 안전하게, 그리고 제한된 환경에서 진행할 수 있었습니다.

취약한 서버

아래 파이썬 코드에서 무엇이 잘못됐는지 찾을 수 있나요?

from http.server import BaseHTTPRequestHandler, HTTPServer
import time

a = 0

class VulnerableHTTPRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        global a
        time.sleep(3)                     # <-- intentional delay
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        self.wfile.write(bytes(f"Request processed. Count: {a}", "utf-8"))
        a += 1

def run(server_class=HTTPServer, handler_class=VulnerableHTTPRequestHandler, port=8080):
    server_address = ('', port)
    httpd = server_class(server_address, handler_class)
    print(f"Starting vulnerable server on port {port}...")
    httpd.serve_forever()

if __name__ == "__main__":
    run()

보셨나요? time.sleep(3)

이 줄은 “무거운 처리”를 시뮬레이션하기 위해 추가된 것이며, 전체 취약점이 바로 여기서 발생합니다:

  • 서버가 단일 스레드로 동작합니다.
  • 각 요청이 3초 동안 블록됩니다.
  • 속도 제한이나 동시성 처리가 전혀 없습니다.

이로 인해 애플리케이션 레이어 DoS 공격에 이상적인 대상이 됩니다.

Starting the Server

Ubuntu VM에서 다음을 실행합니다:

python3 vulnerable_server1.py

서버가 8080 포트에서 시작됩니다. Kali VM에서 정상 동작을 확인하려면 다음을 실행합니다:

curl http://192.168.56.103:8080

각 요청마다 응답이 반환되고 카운터가 증가합니다.

The Attack

Kali에서 ApacheBench를 실행했습니다:

ab -n 50 -c 10 http://192.168.56.103:8080/
  • 총 50개의 요청
  • 동시 10개의 요청

이 숫자는 겸손해 보이지만, 서버는 금세 “멈춘” 상태가 되었습니다. 응답이 느려지고 요청이 대기열에 쌓이기 시작했습니다. 네트워크를 과부하 시키거나 OS를 충돌시킨 것이 아니라, 단지 서버가 설계된 한계보다 더 많은 작업을 수행하도록 요청했을 뿐입니다.

ApacheBench results

실제로 일어난 일

Because the server is single‑threaded, each request blocks for 3 seconds. Only one request can be processed at a time, so when 10 requests arrive simultaneously:

  1. One request is handled.
  2. The remaining nine wait in the queue.
  3. New requests keep piling up.

This is an application‑layer DoS, not a bandwidth attack.

Wireshark에서 공격 보기

보너스로, 나는 Kali에서 Wireshark를 사용해 다음 필터로 트래픽을 캡처했습니다:

ip.addr == 192.168.56.103 && tcp.port == 8080

캡처 내용은 다음과 같습니다:

  • 반복되는 HTTP GET 요청
  • 지연된 응답
  • TCP 재전송
  • 증가하는 혼잡

Wireshark 캡처

Real‑World Relevance

  • 내부 도구
  • API
  • 마이크로서비스
  • 맞춤형 대시보드

공격자는 항상 무언가를 “깨뜨릴” 필요는 없습니다; 단순히 형편없는 코드가 스스로 오류를 일으키기를 기다릴 수 있습니다. 실제 운영 환경에서는 이러한 결함이 (희망컨대) 신속하게 패치되겠지만, 학습 연습으로는 훌륭합니다.

Mitigations

  • 비동기 또는 멀티스레드 서버를 사용하세요 (예: aiohttp, gunicorn, uvicorn).
  • 속도 제한을 추가하세요.
  • 애플리케이션 앞에 리버스 프록시(예: Nginx)를 배치하세요.

결론

내 서버를 직접 부수어 본 것은 지금까지 배운 것 중 가장 가치 있는 교훈 중 하나였습니다. 이는 애플리케이션‑계층 DoS가 어떻게 작동하는지, 설계 선택이 왜 중요한지, 그리고 실제 공격 트래픽이 어떤 모습인지 보여주었습니다.

사이버 보안을 배우고 있다면, 이런 실험실을 구축해 보길 강력히 추천합니다: 안전하고, 합법적이며, 눈을 뜨게 하는 경험이 될 것입니다.

추가: 위 설정을 실험하면서 이 블로그 글을 작성했습니다. 실험실을 그대로 재현하고 더 탐구해 보세요!

마무리 계획이 없어서 HTTP 스프레이 DoS 공격도 테스트해 보았지만, 블로그가 너무 길어졌습니다. 도구를 확인하고 싶다면 제 GitHub에 있습니다. 시간이 된다면 앞으로 며칠 안에 개선할 계획입니다.

Back to Blog

관련 글

더 보기 »

기술은 구원자가 아니라 촉진자다

왜 사고의 명확성이 사용하는 도구보다 더 중요한가? Technology는 종종 마법 스위치처럼 취급된다—켜기만 하면 모든 것이 개선된다. 새로운 software, ...

에이전틱 코딩에 입문하기

Copilot Agent와의 경험 나는 주로 GitHub Copilot을 사용해 인라인 편집과 PR 리뷰를 수행했으며, 대부분의 사고는 내 머리로 했습니다. 최근 나는 t...