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

포트 스캐닝: 열린 문 찾기


핵심 개념

TCP Connect 스캔 + 멀티스레딩으로 빠른 포트 스캐너를 만든다.

본문

TCP Connect 스캔 — 가장 기본

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

def scan_port(host: str, port: int, timeout: float = 1.0) -> tuple[int, bool, str]:
    """단일 포트 상태 확인."""
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(timeout)
    try:
        # connect_ex는 예외 대신 errno 반환 — 더 빠름
        result = s.connect_ex((host, port))
        if result == 0:
            return port, True, 'open'
        return port, False, f'closed({result})'
    except socket.timeout:
        return port, False, 'timeout'
    finally:
        s.close()

단일 스레드 — 느림

PYTHON📋 코드 (13줄)
import time

def scan_serial(host: str, ports: list[int]) -> list[int]:
    open_ports = []
    start = time.time()
    for p in ports:
        port, is_open, _ = scan_port(host, p, 0.5)
        if is_open:
            open_ports.append(port)
    print(f'{len(ports)}개 포트, {time.time() - start:.1f}초')
    return open_ports

# 1024개 포트 → 약 8분 (timeout 0.5초 × 1024)

멀티스레딩 — 100배 빠름

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

def scan_parallel(host: str, ports: list[int], workers: int = 100) -> list[int]:
    """병렬 포트 스캔."""
    open_ports = []
    with ThreadPoolExecutor(max_workers=workers) as ex:
        futures = {ex.submit(scan_port, host, p, 1.0): p for p in ports}
        for fut in as_completed(futures):
            port, is_open, _ = fut.result()
            if is_open:
                open_ports.append(port)
    return sorted(open_ports)

# 1024개 포트 → 약 10초 (100 worker)

일반적인 포트 셋

PYTHON📋 코드 (25줄)
COMMON_PORTS = {
    'top10': [21, 22, 23, 25, 53, 80, 110, 143, 443, 3306],
    'top100_web': list(range(80, 90)) + [443, 8080, 8443, 8888],
    'all_well_known': list(range(1, 1024)),
}

WELL_KNOWN_SERVICES = {
    21:    'FTP',
    22:    'SSH',
    23:    'Telnet',
    25:    'SMTP',
    53:    'DNS',
    80:    'HTTP',
    110:   'POP3',
    143:   'IMAP',
    443:   'HTTPS',
    3306:  'MySQL',
    5432:  'PostgreSQL',
    6379:  'Redis',
    8080:  'HTTP-Alt',
    27017: 'MongoDB',
}

def label_port(port: int) -> str:
    return WELL_KNOWN_SERVICES.get(port, 'Unknown')

실습: 자신의 로컬 서버 포트 스캔

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

logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s')
log = logging.getLogger('portscan')

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--host', default='127.0.0.1')
    parser.add_argument('--start', type=int, default=1)
    parser.add_argument('--end', type=int, default=1024)
    parser.add_argument('--workers', type=int, default=100)
    args = parser.parse_args()

    # 안전 검증 — 자기 호스트만 허용
    import ipaddress
    ip = ipaddress.ip_address(socket.gethostbyname(args.host))
    if not (ip.is_private or ip.is_loopback):
        raise PermissionError(f'공용 IP 스캔 금지: {ip}')

    ports = list(range(args.start, args.end + 1))
    log.info(f'{args.host} 포트 {args.start}~{args.end} 스캔 시작')

    open_ports = []
    with ThreadPoolExecutor(max_workers=args.workers) as ex:
        futures = {ex.submit(scan_port, args.host, p, 1.0): p for p in ports}
        for fut in as_completed(futures):
            port, is_open, _ = fut.result()
            if is_open:
                open_ports.append(port)
                log.warning(f'OPEN: {port}/tcp ({label_port(port)})')

    print(f'\n결과: {len(open_ports)}개 열린 포트')
    for p in sorted(open_ports):
        print(f'  {p:5d}/tcp  {label_port(p)}')

if __name__ == '__main__':
    main()

⚠️ 윤리적 경계

  • ✅ 자기 서버, 로컬 환경(127.0.0.1, 192.168.x.x)
  • ✅ TryHackMe, HackTheBox 같은 허가 랩
  • ❌ 임의의 외부 IP 스캔 → 명백한 불법
  • ❌ Rate Limit 무시 (서버 마비 우려)

SYN 스캔(Half-Open)은 다음 단계

이 챕터의 TCP Connect 스캔은 완전한 3-way handshake를 수행해 로그에 남습니다. SYN 스캔(scapy 사용)은 더 은밀하지만 root 권한이 필요해서 후속 트랙에서 다룹니다.


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

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

내 포트 스캐너 코드에서
동시성·예외 처리·리소스 누수를 분석하고
프로덕션 수준으로 개선해줘.
ChatGPT

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

TCP Connect 스캔 vs SYN 스캔 vs UDP 스캔의
속도·은밀성·권한 요구사항을
실전 코드로 비교해줘.
Gemini

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

내 스캔 결과 로그를 분석해서
포트별 서비스·응답 시간·이상 패턴을
종합 리포트로 만들어줘.
Grok

무료: Grok 4.1 / SuperGrok $30/mo

2026년 포트 스캐닝 도구 — Python 자체 vs Nmap vs masscan
각각의 적합한 케이스를 솔직히 알려줘.

⭐ 이것만 기억하세요
포트 스캐닝: 열린 문 찾기 이 3가지만 확실히 잡으세요
1.TCP Connect 스캔 + ThreadPoolExecutor로 1024개 포트를 10초 안에 스캔할 수 있다
2.connect_ex()는 예외 대신 errno를 반환해서 try/except 오버헤드를 줄여준다
3.다음 챕터에서 열린 포트의 서비스를 식별하는 배너 그래빙 기법을 배운다


공유하기
진행도 68 / 84