icon

안동민 개발노트

5장 : 라우팅

라우팅 실습과 진단


라우팅의 이론을 배웠으니, 이제 실제로 패킷이 어떤 경로를 따라 이동하는지 직접 확인해 보겠습니다. 라우팅 경로를 눈으로 볼 수 있다는 것은 네트워크 문제를 진단할 때 매우 강력한 무기가 됩니다.


traceroute로 경로 추적

traceroute(Windows에서는 tracert)는 패킷이 목적지까지 거치는 모든 라우터를 순서대로 보여주는 도구입니다.

macOS / Linux
traceroute google.com
Windows
tracert google.com

실행하면 각 홉(라우터)의 IP 주소와 응답 시간이 출력됩니다.

출력 예시
 1  192.168.1.1      1.234 ms   0.987 ms   1.102 ms    ← 공유기
 2  10.0.0.1         5.432 ms   4.987 ms   5.123 ms    ← ISP 첫 번째 라우터
 3  172.16.0.1      12.345 ms  11.987 ms  12.102 ms    ← ISP 백본
 4  72.14.204.68    35.678 ms  34.987 ms  35.234 ms    ← 해외 라우터
 5  142.250.196.110 36.789 ms  35.654 ms  36.123 ms    ← Google 서버

첫 번째 홉은 보통 자신의 게이트웨이(공유기)입니다. 이후 ISP의 라우터들을 거치고, 최종적으로 구글의 서버에 도달합니다. 각 홉에 세 개의 시간이 표시되는 것은 traceroute가 홉마다 3개의 패킷을 보내기 때문입니다.


traceroute의 동작 원리

traceroute의 원리는 TTL(Time To Live)을 활용한 것입니다.

traceroute TTL 동작 원리
Step 1: TTL=1인 패킷 전송
  PC ──[TTL=1]──→ R1 ──X (TTL 만료)

                   └──→ PC에게 ICMP Time Exceeded 응답
                        "나는 192.168.1.1 이야, 2ms 걸렸어"

Step 2: TTL=2인 패킷 전송
  PC ──[TTL=2]──→ R1 ──[TTL=1]──→ R2 ──X (TTL 만료)

                                    └──→ PC에게 ICMP Time Exceeded
                                         "나는 10.0.0.1 이야, 5ms"

Step 3: TTL=3인 패킷 전송
  PC ──[TTL=3]──→ R1 ──[TTL=2]──→ R2 ──[TTL=1]──→ R3 ──X

                                                     └──→ "12ms"

Step N: TTL=N으로 목적지 도달
  PC ──[TTL=N]──→ ... ──→ 목적지 서버

                           └──→ ICMP Echo Reply (도착!)

TTL이 1인 패킷을 보내면 첫 번째 라우터에서 만료되고, 그 라우터가 TTL 초과 메시지(ICMP Time Exceeded)를 돌려보냅니다. TTL을 2로 보내면 두 번째 라우터에서 만료됩니다. 이 과정을 반복하면 경로상의 모든 라우터를 하나씩 발견할 수 있습니다.

특정 홉에서 * * *가 표시되면, 해당 라우터가 ICMP 응답을 차단하고 있는 것입니다. 보안 정책상 많은 라우터가 traceroute 응답을 허용하지 않습니다. 이것이 반드시 문제를 의미하는 것은 아닙니다.


traceroute 결과 분석

traceroute 출력에서 문제를 진단하는 방법을 알아봅시다.

traceroute 결과 분석 패턴
정상적인 결과
 1  192.168.1.1      1 ms    1 ms    1 ms    ← 일관된 응답
 2  10.0.0.1         5 ms    5 ms    5 ms
 3  172.16.0.1      12 ms   12 ms   12 ms
 4  목적지           35 ms   35 ms   35 ms

패턴 1: 특정 홉에서 급격한 지연 증가
 3  172.16.0.1      12 ms   12 ms   12 ms
 4  203.0.113.1    150 ms  148 ms  152 ms   ← 3→4에서 138ms 증가
 5  목적지          151 ms  150 ms  149 ms   ← 이후로도 지연 유지
 → 홉 4 이전 구간(해저 케이블 등)에서 물리적 지연

패턴 2: 특정 홉에서만 지연 (이후 회복)
 3  172.16.0.1      12 ms   12 ms   12 ms
 4  203.0.113.1    200 ms  195 ms  210 ms   ← 높은 지연
 5  목적지           15 ms   14 ms   15 ms   ← 정상 복귀
 → 홉 4의 라우터가 ICMP 응답을 낮은 우선순위로 처리 (문제 아님)

패턴 3: 특정 홉부터 전부 * * *
 3  172.16.0.1      12 ms   12 ms   12 ms
 4  * * *
 5  * * *
 → 홉 4에서 패킷 차단 (방화벽) 또는 목적지 도달 불가

패턴 4: 루프 감지
 3  172.16.0.1      12 ms
 4  10.0.0.1         8 ms
 5  172.16.0.1      12 ms   ← 홉 3과 동일한 IP!
 6  10.0.0.1         8 ms
 → 라우팅 루프 발생 (긴급 대응 필요)

핵심 원칙: 지연이 특정 홉에서만 높고 이후에 정상이면 문제가 아닙니다. 지연이 특정 홉부터 누적되면 그 구간에 실제 문제가 있는 것입니다.


라우팅 테이블 읽는 법

자신의 컴퓨터에서도 라우팅 테이블을 확인할 수 있습니다.

Windows
route print
macOS / Linux
ip route
Linux 출력 예시
default via 192.168.1.1 dev eth0 proto dhcp metric 100
192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.100
10.0.0.0/8 via 192.168.1.2 dev eth0 proto static metric 50
172.16.0.0/12 via 192.168.1.3 dev eth1 proto ospf metric 110

각 필드의 의미를 해석해 봅시다.

필드설명예시
default디폴트 라우트 (0.0.0.0/0)일치하는 경로가 없을 때 사용
via다음 홉(Next Hop) IP192.168.1.1
dev출력 인터페이스eth0, eth1, wlan0
proto경로 학습 방법kernel(직접), dhcp, static, ospf
scope link직접 연결된 네트워크게이트웨이 불필요
src해당 경로 사용 시 출발지 IP192.168.1.100
metric경로 우선순위 (낮을수록 우선)100

첫 번째 줄은 디폴트 라우트입니다. 특별히 일치하는 경로가 없는 모든 패킷은 192.168.1.1(게이트웨이)로 보내라는 의미입니다. DHCP로 자동 설정되었고 메트릭은 100입니다.

두 번째 줄은 192.168.1.0/24 네트워크에 대한 경로입니다. 이 네트워크는 eth0 인터페이스에 직접 연결되어 있으므로, 게이트웨이를 거치지 않고 직접 전달하라는 의미입니다.


TTL과 ICMP

TTL(Time To Live)은 IP 패킷 헤더에 포함된 값으로, 패킷이 네트워크에서 무한히 떠돌아다니는 것을 방지합니다.

패킷이 라우터를 하나 지날 때마다 TTL이 1씩 감소합니다. TTL이 0이 되면 해당 라우터는 패킷을 폐기하고, 송신자에게 ICMP Time Exceeded 메시지를 보냅니다.

OS / 장비기본 TTL용도
Linux64서버, 컨테이너
Windows128데스크톱, 서버
macOS64데스크톱, 개발
Cisco 라우터255네트워크 장비
Solaris255엔터프라이즈 서버

이 차이를 이용하면 상대방의 운영체제를 추측할 수도 있습니다. ping 응답의 TTL이 118이면, 원래 128에서 시작해 10개의 라우터를 거쳤으므로 Windows 시스템일 가능성이 높습니다.

ICMP(Internet Control Message Protocol)는 IP 네트워크에서 제어 메시지와 오류 메시지를 전달하는 프로토콜입니다.

ICMP 타입이름용도
Type 0Echo Replyping 응답
Type 3Destination Unreachable목적지 도달 불가 (코드로 세분화)
Type 5Redirect더 좋은 경로 알림
Type 8Echo Requestping 요청
Type 11Time ExceededTTL 만료 (traceroute 동작 기반)
Type 30Traceroute확장 traceroute 정보

ICMP는 데이터 전송을 위한 프로토콜이 아니라 진단과 제어를 위한 프로토콜입니다. 하지만 네트워크 문제를 분석할 때 빠질 수 없는 존재입니다.


ping 심화 활용

단순히 ping google.com을 넘어, ping의 다양한 옵션을 활용한 진단법을 알아봅시다.

ping_diagnostics.sh
#!/bin/bash
# === ping 심화 진단 ===

echo "=== 기본 ping (4패킷) ==="
ping -c 4 google.com

echo ""
echo "=== MTU 확인 (Don't Fragment + 크기 지정) ==="
# Linux: -M do (Don't Fragment), -s (페이로드 크기)
# 1472 = 1500(MTU) - 20(IP헤더) - 8(ICMP헤더)
ping -c 1 -M do -s 1472 google.com
# 성공하면 MTU가 1500 이상
# "Frag needed" 오류 → 경로상 MTU가 1500 미만

echo ""
echo "=== 응답 시간 통계 ==="
ping -c 20 google.com | tail -3
# rtt min/avg/max/mdev = 2.123/3.456/15.789/2.345 ms
# mdev(표준편차)가 크면 → 네트워크 불안정 (jitter 높음)

echo ""
echo "=== 특정 인터페이스에서 ping ==="
ping -c 4 -I eth0 8.8.8.8

echo ""
echo "=== TTL 지정 ping ==="
# TTL을 5로 설정 → 5홉 이내에 도달하는지 확인
ping -c 4 -t 5 google.com

echo ""
echo "=== Windows에서 연속 ping ==="
# ping -t google.com      (Ctrl+C로 중지)
# ping -l 1472 -f google.com  (MTU 확인, -f = Don't Fragment)
ping 결과 해석
64 bytes from 142.250.196.110: icmp_seq=1 ttl=118 time=3.45 ms

해석
  64 bytes      : 응답 데이터 크기
  icmp_seq=1    : 1번째 패킷 (연속 번호)
  ttl=118       : 128 - 118 = 10홉 거침 (Windows 서버 추정)
  time=3.45 ms  : 왕복 시간 (RTT)

통계
  min = 2.1ms   : 최소 RTT (네트워크 최적 상태)
  avg = 3.5ms   : 평균 RTT (일반적 성능)
  max = 15.8ms  : 최대 RTT (일시적 혼잡)
  mdev = 2.3ms  : 편차 (jitter, 낮을수록 안정)

packet loss
  0%   = 정상
  1-5% = 경미한 문제 (무선 네트워크에서 흔함)
  >5%  = 심각한 문제 (링크 품질 확인 필요)

비대칭 라우팅 문제

네트워크에서 종종 발생하는 비직관적인 상황 하나를 짚어 두겠습니다.

A에서 B로 가는 경로와 B에서 A로 돌아오는 경로가 다를 수 있습니다. 이것을 비대칭 라우팅(Asymmetric Routing)이라고 합니다.

비대칭 라우팅
A → B (갈 때)
  A ──→ ISP-A ──→ IX ──→ ISP-B ──→ B
                    (경로 1)

B → A (올 때)
  B ──→ ISP-B ──→ ISP-C ──→ ISP-A ──→ A
                    (경로 2, 다른 경로!)

BGP 정책에 의해 각 방향의 최적 경로가 다름
→ traceroute로 확인하는 경로 ≠ 응답이 돌아오는 경로

비대칭 라우팅 자체는 문제가 아닙니다. 인터넷에서는 매우 흔한 현상입니다. 하지만 상태 기반 방화벽(Stateful Firewall)을 사용하는 환경에서는 문제가 됩니다.

비대칭 라우팅 + 방화벽 문제
요청 경로
Client → FW-A → Server
FW-A: "요청 기록"

응답 경로
Server → FW-B → Client
FW-B: "요청 기록 없음"
→ 차단! ✗

FW-A는 나가는 요청을 기록했지만
응답은 FW-B를 통해 돌아와서, FW-B는 해당 세션을 모름

이런 경우 방화벽 간에 세션 정보를 동기화하거나, 라우팅을 대칭적으로 조정해야 합니다. 클라우드 환경에서 다중 가용 영역(AZ)을 사용할 때 종종 마주치는 문제입니다.


MTR: traceroute + ping의 결합

MTR(My Traceroute)은 traceroute와 ping을 결합한 도구입니다. 각 홉에 대해 지속적으로 패킷을 보내며 실시간 통계를 수집합니다.

MTR 사용법
# 기본 사용
mtr google.com

# 리포트 모드 (100패킷 후 결과 출력)
mtr -r -c 100 google.com

# TCP 모드 (ICMP 차단 환경에서 유용)
mtr -T -P 443 google.com

# JSON 출력 (자동화용)
mtr -j -c 50 google.com
MTR 출력 예시
                        Packets               Pings
Host                  Loss%   Snt   Last   Avg  Best  Wrst StDev
1. 192.168.1.1         0.0%   100    0.8   0.9   0.5   2.1   0.3
2. 10.0.0.1            0.0%   100    5.2   5.5   4.1   8.3   0.8
3. 172.16.0.1          2.0%   100   12.1  12.8  10.2  45.3   5.2
4. 72.14.204.68        2.0%   100   35.4  36.1  33.2  52.1   3.1
5. 142.250.196.110     0.0%   100   36.2  36.8  34.1  41.2   1.5

분석
  홉 3: 2% 패킷 손실 + StDev 높음 → 이 구간에 간헐적 혼잡
  홉 4: 2% 손실은 홉 3에서 전파된 것 (누적)
  홉 5: 0% 손실 → 홉 3의 손실이 재전송으로 복구됨

MTR이 traceroute보다 유용한 이유는 시간에 따른 변화를 볼 수 있기 때문입니다. 일시적인 패킷 손실인지 지속적인 문제인지 구별할 수 있습니다.


네트워크 경로 진단 종합 가이드

network_diagnostics.py
import subprocess
import re
import sys
import statistics

def run_ping(host, count=10):
    """ping 테스트 수행 및 결과 분석"""
    cmd = ["ping", "-c", str(count), host]
    if sys.platform == "win32":
        cmd = ["ping", "-n", str(count), host]

    result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
    output = result.stdout

    # RTT 시간 파싱
    if sys.platform == "win32":
        times = re.findall(r'time[=<](\d+)ms', output)
    else:
        times = re.findall(r'time=(\d+\.?\d*)', output)

    times = [float(t) for t in times]

    if not times:
        return {"host": host, "status": "unreachable", "loss": 100}

    # 패킷 손실률 계산
    loss_match = re.search(r'(\d+)% packet loss', output)
    loss = int(loss_match.group(1)) if loss_match else 0

    return {
        "host": host,
        "status": "ok" if loss < 5 else "degraded" if loss < 20 else "critical",
        "loss": loss,
        "min_rtt": min(times),
        "avg_rtt": statistics.mean(times),
        "max_rtt": max(times),
        "jitter": statistics.stdev(times) if len(times) > 1 else 0,
        "samples": len(times),
    }

def diagnose_path(host):
    """경로 진단 수행"""
    print(f"=== {host} 경로 진단 ===\n")

    # 1. ping 테스트
    ping_result = run_ping(host)
    print(f"[Ping] 상태: {ping_result['status']}")
    if ping_result["status"] != "unreachable":
        print(f"  손실률: {ping_result['loss']}%")
        print(f"  RTT: min={ping_result['min_rtt']:.1f}ms "
              f"avg={ping_result['avg_rtt']:.1f}ms "
              f"max={ping_result['max_rtt']:.1f}ms")
        print(f"  Jitter: {ping_result['jitter']:.1f}ms")

    # 2. 진단 결과 해석
    print(f"\n[진단]")
    if ping_result["status"] == "unreachable":
        print("  ✗ 호스트 도달 불가")
        print("  → DNS 확인, 방화벽 확인, 라우팅 확인 필요")
    elif ping_result["loss"] > 0:
        print(f"  △ 패킷 손실 {ping_result['loss']}% 감지")
        print("  → MTR로 손실 구간 특정 권장")
    elif ping_result["jitter"] > 10:
        print(f"  △ 높은 Jitter ({ping_result['jitter']:.1f}ms)")
        print("  → 네트워크 혼잡 또는 무선 간섭 가능성")
    else:
        print("  ✓ 네트워크 상태 양호")

# 주요 목적지 진단
targets = ["8.8.8.8", "1.1.1.1"]
for target in targets:
    diagnose_path(target)
    print()

실무 라우팅 문제 체크리스트

증상가능한 원인진단 도구해결 방법
완전한 연결 불가디폴트 라우트 누락ip route show디폴트 게이트웨이 설정
특정 대역만 불가라우팅 테이블 누락ip route get [IP]정적 경로 추가 또는 동적 프로토콜 확인
간헐적 패킷 손실링크 혼잡 / 장비 불안정mtr -r -c 200대역폭 증설, 장비 교체
높은 지연비효율적 경로traceroute라우팅 정책 조정
비대칭 경로 차단방화벽 세션 불일치traceroute 양방향방화벽 세션 동기화
라우팅 루프경로 수렴 실패traceroute (IP 반복)라우팅 프로토콜 설정 확인
MTU 관련 장애경로상 MTU 불일치ping -M do -s 1472Path MTU Discovery 확인, MSS 조정

다음 장에서는 네트워크 계층 위에서 프로세스 간의 안정적인 통신을 보장하는 TCP를 자세히 살펴보겠습니다.

목차