[Python] 사설 서버 24시간 감시를 위한 비동기 모니터링 봇 구축기 (feat. Asyncio, Redis, AWS Lambda)

김민우·2026년 2월 1일


왜 굳이 '봇(Bot)'을 만들었나?

안녕하세요. MT-LAB(먹튀랩)의 백엔드 리드 개발자입니다. 우리 팀은 매일 수십 개의 신규 사이트가 생기고 사라지는 이 시장에서, "어떻게 하면 인간의 주관을 배제하고 오직 데이터로만 안전성을 검증할 수 있을까?"를 고민했습니다.

사람은 잠을 자고, 실수를 합니다. 하지만 서버는 24시간 깨어 있습니다. 그래서 우리는 전 세계 3,000개 이상의 사설 서버를 실시간으로 핑(Ping) 체크하고, HTML 구조 변경을 감지하는 자동화 봇 'Watchdog'을 개발했습니다.

오늘은 그 개발 과정에서 겪은 동시성(Concurrency) 문제 해결과 안티 크롤링 우회 기법에 대해 기술적으로 공유하려 합니다.

  1. Tech Stack (사용 기술)
    우리가 구축한 모니터링 시스템의 핵심 스택은 다음과 같습니다. 가벼우면서도 확장성(Scalability)을 최우선으로 고려했습니다.

Language: Python 3.11 (Type Hinting 적극 활용)

Crawling: aiohttp (비동기 요청), Selenium (동적 페이지 렌더링)

Queue: Redis (URL 스케줄링 및 중복 제거)

Database: PostgreSQL (메타 데이터), InfluxDB (시계열 로그 데이터)

Deploy: AWS Lambda + CloudWatch (Serverless 아키텍처)

  1. Architecture: 동기(Sync) vs 비동기(Async)의 싸움
    초기 버전은 requests 라이브러리를 사용한 동기 방식이었습니다. 하지만 3,000개의 사이트를 전수 조사하는 데 40분이 넘게 걸렸습니다. 검증 사이트로서 '실시간성'이 떨어진다는 건 치명적이었죠.

우리는 이를 asyncio와 aiohttp를 이용한 완전 비동기(Fully Asynchronous) 구조로 리팩토링했습니다.

Python
import asyncio
import aiohttp
import time
from typing import List

비동기 세션으로 상태 코드 체크

async def fetch_status(session: aiohttp.ClientSession, url: str):
try:
async with session.get(url, timeout=10) as response:

        # 200 OK가 아니면 서버 이상 징후로 판단
        return url, response.status
except Exception as e:
    return url, 500  # 서버 다운으로 간주

async def main(urls: List[str]):
async with aiohttp.ClientSession() as session:
tasks = [fetch_status(session, url) for url in urls]

    # 3000개 요청을 동시에 병렬 처리 (Concurrent)
    results = await asyncio.gather(*tasks)
    return results

결과: 40분 걸리던 작업이 3분 내로 단축됨

if name == "main":
start = time.time()
asyncio.run(main(target_site_list))
print(f"Completed in {time.time() - start} seconds")
이 코드를 통해 우리는 3분 간격으로 전 세계 모든 타겟 사이트의 생존 여부(Heartbeat)를 체크할 수 있게 되었습니다.

  1. Bypassing WAF: 클라우드플레어를 뚫어라
    단순히 requests만 날리면 대부분의 사이트는 403 Forbidden을 뱉습니다. Cloudflare나 Akamai 같은 WAF(웹 방화벽)가 봇을 차단하기 때문입니다.

우리는 이를 우회하기 위해 Undetected-Chromedriver와 User-Agent 로테이션 기술을 적용했습니다.

[핵심 로직]

헤더 위장: 매 요청마다 User-Agent를 최신 버전의 Chrome, Firefox, Edge 등으로 랜덤 교체합니다.

헤드리스 탐지 우회: navigator.webdriver 플래그를 false로 조작하여 브라우저인 척 연기합니다.

Python
from selenium import webdriver
from selenium_stealth import stealth

def create_stealth_driver():
options = webdriver.ChromeOptions()
options.add_argument("start-maximized")
options.add_argument("--headless")
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)

driver = webdriver.Chrome(options=options)

# 셀레니움 스텔스 적용 (봇 탐지 스크립트 무력화)
stealth(driver,
    languages=["en-US", "en"],
    vendor="Google Inc.",
    platform="Win32",
    webgl_vendor="Intel Inc.",
    renderer="Intel Iris OpenGL Engine",
    fix_hairline=True,
)
return driver

이 기술 덕분에 MT-LAB의 봇은 일반 유저와 100% 동일한 환경으로 인식되어, 관리자 페이지나 숨겨진 로그인 페이지까지 접근하여 데이터를 수집할 수 있습니다.

  1. Anomaly Detection: '먹튀'를 감지하는 알고리즘
    데이터를 수집했다면 분석을 해야 합니다. 우리는 수집된 HTML DOM 트리를 파싱하여 다음과 같은 '이상 징후(Anomaly)'가 발견되면 즉시 Slack으로 알람을 보냅니다.

Case A. 팝업창 키워드 분석

BeautifulSoup으로 사이트의 모든 텍스트를 긁어온 뒤, NLP(자연어 처리) 모듈을 돌립니다.

"긴급 점검", "계좌 변경", "디도스 공격" 같은 단어의 빈도수가 평소보다 급증하면 위험 등급을 [Warning]으로 격상합니다.

Case B. 도메인 리다이렉트 (Domain Redirect)

response.history를 추적합니다.

어제까지 site-a.com이었던 곳이 오늘 갑자기 site-b.com으로 리다이렉트 된다면? 이는 도메인 세탁(Domain Washing)의 전형적인 수법입니다. 봇은 이를 놓치지 않고 DB에 '이력'으로 남깁니다.

Python

리다이렉트 추적 로직 (의사 코드)

if response.history:
original_url = response.history[0].url
final_url = response.url

if original_url != final_url:
    print(f"[ALERT] 도메인 변경 감지: {original_url} -> {final_url}")
    # DB에 '먹튀 의심' 태그 추가 및 슬랙 전송
    send_slack_alert(channel="#security-log", msg=f"도메인 세탁 의심: {final_url}")
  1. Data Pipeline: 데이터는 거짓말을 하지 않는다
    이렇게 수집된 하루 10만 건 이상의 로그는 InfluxDB에 시계열 데이터로 저장됩니다. 우리는 이 데이터를 바탕으로 '사이트 수명 예측 모델'을 돌립니다.

서버 응답 속도가 느려지기 시작하는 시점

고객센터 게시판 글 리젠 속도가 줄어드는 시점

입금 보너스 배너가 3개 이상 늘어나는 시점

이 모든 데이터가 교차하는 순간, 우리 시스템은 해당 사이트를 [SCAM CONFIRMED] 상태로 변경하고 블랙리스트에 등재합니다.

  1. Outro: 기술로 증명하는 안전
    개발자로서 이 프로젝트를 진행하며 느낀 점은 하나입니다. "검증은 감(Feeling)이 아니라 과학(Science)이어야 한다"는 것입니다.

"친절하다", "빠르다"는 주관적인 평가는 믿을 수 없습니다. 오직 서버가 뱉어내는 HTTP Status Code 200과 Latency(지연 시간), 그리고 블록체인 트랜잭션만이 진실을 말해줍니다.

우리가 만든 이 봇은 지금 이 순간에도 전 세계의 사설 서버를 24시간 감시하고 있습니다. MT-LAB이 제공하는 정보는 누군가의 '카더라'가 아닌, 수백만 줄의 로그 데이터에서 정제된 기술적 팩트입니다.

혹시 자동화된 검증 시스템의 전체 데이터가 궁금하신가요? 저희 기술 블로그가 아닌, 실제 서비스 페이지에서 그 결과를 확인하실 수 있습니다.

👉 먹튀랩 기술팀 모니터링 현황 보기

profile
보안분석가

0개의 댓글