OPEN HYPER STEP
← 목록으로 (화이트햇 보안)
SECURITY · 71 / 84
security
CHAPTER 71 / 84
읽기 약 2
FUNCTION

서브넷 스캐너 만들기


핵심 개념

ipaddress 모듈 + ThreadPoolExecutor로 로컬 네트워크의 활성 호스트를 탐지한다.

본문

서브넷 순회 — ipaddress 모듈

PYTHON📋 코드 (20줄)
# ⚠️ 이 코드는 허가된 환경에서만 사용하세요.
import ipaddress

def list_subnet_hosts(cidr: str) -> list[str]:
    """CIDR 표기로 서브넷 내 모든 호스트 IP 나열."""
    network = ipaddress.ip_network(cidr, strict=False)
    return [str(ip) for ip in network.hosts()]

# /24 서브넷 — 254개 호스트
hosts = list_subnet_hosts('192.168.1.0/24')
print(len(hosts))  # 254
print(hosts[:3])   # ['192.168.1.1', '192.168.1.2', '192.168.1.3']

# /16 서브넷은 65,534개 — 신중히
# 너무 큰 서브넷 방어
def safe_list_hosts(cidr: str, max_hosts: int = 1024) -> list[str]:
    network = ipaddress.ip_network(cidr, strict=False)
    if network.num_addresses > max_hosts:
        raise ValueError(f'{cidr}: {network.num_addresses}개 호스트 — 너무 큼 (최대 {max_hosts})')
    return [str(ip) for ip in network.hosts()]

활성 호스트 탐지 — Ping Sweep

PYTHON📋 코드 (33줄)
# ⚠️ 이 코드는 허가된 환경에서만 사용하세요.
import platform
import subprocess
from concurrent.futures import ThreadPoolExecutor, as_completed

def is_alive(host: str, timeout: int = 1) -> tuple[str, bool]:
    """단일 호스트 ping 1회로 도달 여부 확인."""
    is_windows = platform.system().lower() == 'windows'
    if is_windows:
        cmd = ['ping', '-n', '1', '-w', str(timeout * 1000), host]
    else:
        cmd = ['ping', '-c', '1', '-W', str(timeout), host]

    try:
        result = subprocess.run(cmd, capture_output=True, timeout=timeout + 1)
        return host, result.returncode == 0
    except subprocess.TimeoutExpired:
        return host, False

def ping_sweep(cidr: str, workers: int = 50) -> list[str]:
    """서브넷 전체 ping sweep — 활성 호스트 추출."""
    hosts = safe_list_hosts(cidr)
    alive = []
    with ThreadPoolExecutor(max_workers=workers) as ex:
        futures = {ex.submit(is_alive, h, 1): h for h in hosts}
        for fut in as_completed(futures):
            host, ok = fut.result()
            if ok:
                alive.append(host)
    return sorted(alive, key=lambda x: ipaddress.ip_address(x))

# /24 서브넷 sweep → 약 5초
# alive_hosts = ping_sweep('192.168.1.0/24')

TCP 기반 활성 탐지 — Ping이 차단됐을 때

일부 환경은 ICMP를 차단하지만 TCP 80/443은 열어둠:

PYTHON📋 코드 (16줄)
import socket

def tcp_alive(host: str, ports: list[int] = None, timeout: float = 1.0) -> bool:
    """일반적 포트 중 하나라도 응답하면 활성."""
    if ports is None:
        ports = [80, 443, 22, 8080]

    for port in ports:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.settimeout(timeout)
        try:
            if s.connect_ex((host, port)) == 0:
                return True
        finally:
            s.close()
    return False

ARP 스캔 (root 권한 필요)

같은 LAN 내에서는 ARP가 가장 정확합니다 (방화벽이 못 차단):

PYTHON📋 코드 (15줄)
# pip install scapy
# 주의: ARP 스캔은 root/Administrator 권한 필요
# ⚠️ 이 코드는 허가된 환경에서만 사용하세요.

# from scapy.all import ARP, Ether, srp
#
# def arp_scan(cidr: str, timeout: int = 2) -> list[dict]:
#     """LAN ARP 스캔 — IP+MAC 페어 수집."""
#     arp = ARP(pdst=cidr)
#     ether = Ether(dst='ff:ff:ff:ff:ff:ff')
#     packet = ether / arp
#     answered, _ = srp(packet, timeout=timeout, verbose=False)
#     return [{'ip': r.psrc, 'mac': r.hwsrc} for _, r in answered]
#
# 후속 트랙(scapy 모듈)에서 자세히 다룸

실습: 통합 호스트 디스커버리

PYTHON📋 코드 (34줄)
def discover_hosts(cidr: str, methods: list[str] = None, workers: int = 50) -> dict:
    """ICMP + TCP 결합 — 어떤 방어를 뚫고도 호스트 탐지."""
    if methods is None:
        methods = ['icmp', 'tcp']

    hosts = safe_list_hosts(cidr)
    result = {'cidr': cidr, 'total': len(hosts), 'alive': []}

    with ThreadPoolExecutor(max_workers=workers) as ex:
        futures = {}
        for h in hosts:
            futures[ex.submit(_check_host, h, methods)] = h

        for fut in as_completed(futures):
            host, info = fut.result()
            if info['alive']:
                result['alive'].append({'host': host, **info})

    result['alive'].sort(key=lambda x: ipaddress.ip_address(x['host']))
    return result


def _check_host(host: str, methods: list[str]) -> tuple[str, dict]:
    info = {'alive': False, 'methods': []}
    if 'icmp' in methods:
        _, ok = is_alive(host)
        if ok:
            info['alive'] = True
            info['methods'].append('icmp')
    if 'tcp' in methods and not info['alive']:
        if tcp_alive(host):
            info['alive'] = True
            info['methods'].append('tcp')
    return host, info

⚠️ 핵심 안전 규칙

  • ✅ 자기 LAN(192.168.x.x, 10.x.x.x, 172.16~31.x.x)
  • ✅ TryHackMe/HackTheBox 랩 환경
  • ❌ 회사 네트워크(허가 없이) — 인사 문제 + 법적 위험
  • ❌ 공용 IP 대역 — 명백한 불법

속도 vs 부하 균형

PYTHON📋 코드 (7줄)
# 안전한 기본값
SAFE_DEFAULTS = {
    'workers': 50,           # 동시 50개
    'timeout': 1.0,          # 1초
    'rate_per_host': 'once', # 호스트당 1회만
    'delay_between_batches': 0.1,  # 배치 간 100ms
}

AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
Claude

무료: Sonnet 4.6 / Pro $20/mo: Opus 4.6

내 서브넷 스캐너의
동시성·차단 회피·속도 균형을 분석하고
실전 환경에서 안정적으로 동작하도록 개선해줘.
ChatGPT

무료: GPT-5.5 / Plus $20/mo: GPT-5.5 Pro

ICMP vs TCP vs ARP 호스트 디스커버리
각각의 장단점을 표로 비교하고
환경별 추천 방법을 보여줘.
Gemini

무료: 2.5 Flash / Pro $19.99/mo: 3.1 Pro

내 LAN 스캔 결과 데이터를 분석해서
알려진 디바이스 vs 미식별 디바이스·
응답 시간 이상 패턴을 종합 리포트로 만들어줘.
Grok

무료: Grok 4.1 / SuperGrok $30/mo

2026년 LAN 스캐닝 트렌드 —
IPv6 LAN/SDN 환경에서 전통 스캔이 여전히 유효한지
실무자 관점으로 솔직히 알려줘.

⭐ 이것만 기억하세요
서브넷 스캐너 만들기 이 3가지만 확실히 잡으세요
1.ipaddress.ip_network로 서브넷을 안전하게 순회하고 ThreadPoolExecutor로 빠르게 스캔할 수 있다
2.ICMP만으로는 부족 — TCP 80/443 fallback을 결합해야 방화벽 환경에서도 호스트를 찾을 수 있다
3.다음 챕터에서 모듈 3 종합 — DNS+포트+서비스를 결합한 정찰 도구를 만든다


공유하기
진행도 71 / 84