117. ICMP 패킷 분석 — Type·Code와 오류 메시지 속 원본 헤더 읽기

changseop lee·1일 전

네트워크 · 패킷 분석

목록 보기
117/300

📚 네트워크 · 패킷 분석 › 03. Wireshark 패킷 분석 — 117편
이전 글: 116. IPv6 Packet 분석 · 다음 글: 118. Ping Packet 분석
참고(01. TCP/IP 네트워크 구조 이해): 34. ICMP와 ping — 오류 보고 프로토콜 읽는 법 — ICMP의 역할과 ping·traceroute의 원리는 이 글에서 다뤘습니다.

1. 왜 알아야 하는가

ICMP는 데이터를 나르는 프로토콜이 아니라 네트워크 상태를 알려 주는 프로토콜입니다. 그래서 ICMP 패킷은 관제 분석에서 "다른 통신에 무슨 일이 있었는가"를 알려 주는 간접 증거가 됩니다.

  • ping 요청에 응답이 있었는가, 없었는가? 몇 ms 걸렸는가?
  • "Port unreachable"을 보낸 호스트는 어떤 패킷 때문에 그 오류를 보냈는가?
  • "Time-to-live exceeded"는 누구의 어떤 패킷이 어디서 만료되었다는 뜻인가?
  • ICMP Echo의 데이터 크기와 내용이 일반적인 ping과 다르지 않은가?

특히 ICMP 오류 메시지 안에는 오류를 일으킨 원본 패킷의 IP 헤더와 그 뒤 일부 바이트가 들어 있습니다. 이 구조를 모르면 필터 결과를 잘못 해석하기 쉽습니다. 이번 글은 ICMP 필드를 읽는 방법과 이 "패킷 속 패킷"을 다루는 방법에 집중합니다.


2. 핵심 개념

ICMP 오류 구조
그림 1. ICMP 오류 패킷은 '어떤 패킷이 왜 실패했는지'를 원본 헤더와 함께 알려 줍니다

2-1. ICMP 공통 필드와 Echo 전용 필드

항목Wireshark 필드의미
Typeicmp.type메시지 종류
Codeicmp.codeType 안의 세부 사유
Checksumicmp.checksumICMP 메시지 전체의 오류 검출값
Identifiericmp.ident (icmp.ident_le)Echo 요청·응답을 묶는 값. 보통 ping 프로세스별로 다름
Sequenceicmp.seq (icmp.seq_le)Echo 요청 순번
응답 프레임 번호icmp.resp_in이 요청에 대한 응답이 몇 번 프레임인지 (Wireshark 계산)
요청 프레임 번호icmp.resp_to이 응답이 몇 번 프레임의 요청에 대한 것인지
응답 시간icmp.resptime요청~응답 사이 시간(ms)
응답 없음icmp.no_resp캡처 안에서 응답을 찾지 못한 요청
데이터 길이data.lenEcho 데이터 부분의 바이트 수
다음 홉 MTUicmp.mtuType 3 / Code 4에서 알려 주는 MTU

Info 열의 id=0x0005, seq=1/256에서 1/256은 같은 2바이트를 빅엔디언(1)과 리틀엔디언(256)으로 각각 읽은 값입니다. OS마다 이 값을 기록하는 방식이 달라 Wireshark가 두 해석을 모두 보여 주는 것이며, 필드로는 icmp.seq와 icmp.seq_le에 해당합니다.

2-2. 분석에서 자주 보는 Type·Code

Type / Code이름관제에서의 의미
8 / 0Echo Requestping 요청
0 / 0Echo Replyping 응답
3 / 0Network Unreachable목적지 네트워크로 가는 경로 없음
3 / 1Host Unreachable목적지 호스트에 도달 불가 (ARP 응답 없음 등)
3 / 3Port Unreachable목적지 호스트에 도달했지만 해당 UDP 포트가 닫혀 있음
3 / 4Fragmentation Needed and DF setDF 때문에 조각낼 수 없음 → icmp.mtu 확인
3 / 13Communication Administratively Prohibited필터링 장비가 차단했음을 알림
5 / xRedirect더 나은 게이트웨이를 알려 줌 (일반 LAN에서는 드묾)
11 / 0Time-to-live exceeded in transit전달 중 TTL 만료 (traceroute에서 활용)
11 / 1Fragment reassembly time exceeded조각 재조립 시간 초과

2-3. 오류 메시지 안의 원본 헤더

Type 3, 5, 11 같은 오류 메시지는 오류를 일으킨 원본 패킷의 IP 헤더와 그 뒤의 최소 8바이트(UDP라면 헤더 전체, TCP라면 포트·시퀀스 번호)를 담고 돌아옵니다. Wireshark는 이 부분을 다시 IP·UDP·TCP로 해석해 상세 트리 안에 두 번째 IP 헤더로 보여 줍니다.

그 결과 한 프레임 안에 ip.src, ip.dst, ip.ttl 같은 필드가 두 번 존재하게 됩니다.

위치ip.src / ip.dst의미
바깥 IP 헤더 (1번째)오류를 보낸 장비 → 원래 송신자"누가 오류를 알려 왔는가"
안쪽 IP 헤더 (2번째)원래 송신자 → 원래 목적지"어떤 패킷이 문제였는가"

3. 동작 원리

UDP로 닫힌 포트에 보냈을 때 Port Unreachable이 만들어지는 과정을 필드로 따라가 보면 다음과 같습니다.

[원본 패킷]
192.168.10.20:51515  ──UDP──→  192.168.10.30:33434 (닫힌 포트)
ip.id=0x4444, ip.ttl=64
        ↓
192.168.10.30 커널: 해당 UDP 포트에서 기다리는 프로세스 없음
        ↓
[ICMP 오류 패킷]
바깥 IP : 192.168.10.30 → 192.168.10.20      (ip.src#1, ip.dst#1)
ICMP    : icmp.type=3, icmp.code=3 (Port unreachable)
안쪽 IP : 192.168.10.20 → 192.168.10.30      (ip.src#2, ip.dst#2), ip.id=0x4444
안쪽 UDP: 51515 → 33434                      (udp.srcport, udp.dstport)
        ↓
분석자: 안쪽 헤더를 보고 "어떤 요청이 거부되었는지" 원본 패킷과 매칭

이 구조 때문에 tshark -T fields -e ip.src로 출력하면 ICMP 오류 프레임에서는 192.168.10.30,192.168.10.20처럼 두 값이 쉼표로 함께 나옵니다. 또한 ip.src == 192.168.10.20이라는 필터는 바깥 헤더가 아니라 안쪽 헤더에서 일치해도 해당 프레임을 보여 줍니다. 원하는 계층을 명확히 지정하는 방법은 다음과 같습니다.

목적방법
바깥 헤더 값만 출력-T fields -E occurrence=f -e ip.src
안쪽(마지막) 헤더 값만 출력-T fields -E occurrence=l -e ip.dst
바깥 헤더 기준 필터ip.src#1 == 192.168.10.30 (레이어 연산자, Wireshark 4.2 기준 지원)
안쪽 헤더 기준 필터ip.dst#2 == 192.168.10.30

4. 실제 명령어 / 실습

실습 환경: 본인 소유 Linux VM (Rocky Linux 또는 Ubuntu). 인터페이스 이름은 ens33을 예시로 사용합니다. tshark 설치는 112편과 같습니다(Rocky: sudo dnf install -y wireshark-cli, Ubuntu: sudo apt install -y tshark).

4-1. 도구 설치

# traceroute (기본 동작: UDP 사용)
sudo dnf install -y traceroute        # Rocky Linux
sudo apt install -y traceroute        # Ubuntu

4-2. 캡처와 트래픽 발생

# 터미널 1: ICMP와 traceroute의 UDP를 함께 캡처
sudo tshark -i ens33 -f "icmp or udp portrange 33434-33534" -w /tmp/pcap10-icmp.pcapng

# 터미널 2
ping -c 4 <게이트웨이 IP>           # Echo Request / Reply
traceroute -n -m 5 example.com      # TTL 초과(11/0) 메시지 발생

traceroute는 목적지 포트 33434부터 올라가는 UDP 패킷을 TTL 1부터 보내며, 중간 라우터가 Time-to-live exceeded를, 목적지 호스트가 Port unreachable을 돌려주는 방식으로 동작합니다. 방화벽이 ICMP나 UDP를 막는 환경에서는 * * *만 보이고 ICMP가 캡처되지 않을 수 있습니다. 이것도 "그 구간에서 ICMP가 돌아오지 않았다"는 관찰 결과입니다.

📷 [실습 화면 삽입] traceroute 실행 결과와, Wireshark에서 Time-to-live exceeded 패킷을 선택한 화면

4-3. 필드 단위로 읽기

F=/tmp/pcap10-icmp.pcapng

# (1) Echo 요청·응답 매칭 (-2: 두 번 읽어 응답 프레임 번호를 채움)
tshark -2 -r $F -Y "icmp.type == 8 || icmp.type == 0" -T fields -E header=y \
  -e frame.number -e ip.src -e ip.dst -e icmp.type -e icmp.ident -e icmp.seq \
  -e icmp.resp_in -e icmp.resp_to -e icmp.resptime -e data.len

# (2) 응답 없는 요청
tshark -2 -r $F -Y "icmp.no_resp"

# (3) 오류 메시지: 누가 보냈고, 어떤 패킷이 원인인가
tshark -r $F -Y "icmp.type == 3 || icmp.type == 11" -T fields -E header=y \
  -e frame.number -e ip.src -e ip.dst -e icmp.type -e icmp.code \
  -e udp.srcport -e udp.dstport

# (4) 바깥 헤더(보낸 장비)만 정리
tshark -r $F -Y "icmp.type == 11" -T fields -E occurrence=f -e ip.src | sort | uniq -c

# (5) Type/Code 분포
tshark -r $F -Y icmp -T fields -e icmp.type -e icmp.code | sort | uniq -c | sort -rn

icmp.resp_in처럼 뒤에 나오는 패킷을 참조하는 필드는 tshark가 파일을 한 번만 읽으면 비어 있을 수 있어, -2(2-pass 분석) 옵션을 붙였습니다. Wireshark GUI에서는 파일을 연 뒤 자동으로 채워집니다.

📷 [실습 화면 삽입] Destination unreachable 또는 Time-to-live exceeded 패킷의 상세 트리에서 안쪽 Internet Protocol·User Datagram Protocol을 펼친 화면


5. 결과 확인

아래는 형식 예시(값은 환경마다 다름) 입니다.

frame  ip.src         ip.dst         type  ident  seq  resp_in  resp_to  resptime  data.len
1      192.168.10.20  192.168.10.1   8     5      1    2                           56
2      192.168.10.1   192.168.10.20  0     5      1             1        0.512     56
frame  ip.src                       ip.dst                       type  code  udp.srcport  udp.dstport
9      192.168.10.1,192.168.10.20   192.168.10.20,203.0.113.5    11    0     40000        33435
12     203.0.113.5,192.168.10.20    192.168.10.20,203.0.113.5    3     3     40011        33446
  • 9번: 192.168.10.1(첫 번째 홉)이 "내가 보낸 203.0.113.5 행 UDP(목적지 포트 33435)의 TTL이 만료되었다"고 알려 온 것
  • 12번: 목적지 203.0.113.5가 "해당 UDP 포트는 닫혀 있다"고 알려 온 것 → traceroute가 목적지에 도달했다는 뜻

확인 체크리스트

  • Echo 요청과 응답이 icmp.ident·icmp.seq로 짝지어지는 것을 확인했다
  • -2 옵션 유무에 따라 icmp.resp_in이 채워지는 차이를 확인했다
  • 오류 메시지 프레임에서 ip.src가 두 값으로 출력되는 이유를 설명할 수 있다
  • 바깥 헤더(오류를 보낸 장비)와 안쪽 헤더(원인 패킷)를 구분해 읽었다
  • 안쪽 UDP 포트로 원인 패킷을 특정했다
  • Type/Code 분포에서 예상하지 못한 메시지가 없는지 확인했다

6. 패킷 / 로그 분석

관찰정상일 수 있는 경우의심해야 하는 경우
응답 없는 Echo Request 다수목적지가 ICMP 차단, 호스트 꺼짐한 출발지가 대역 내 여러 IP로 순차 요청 (호스트 탐색, 05. 네트워크 스캔 · 공격 징후 분석 시리즈에서 다룸)
큰 data.len, 일정하지 않은 데이터MTU 점검용 ping, 일부 모니터링 도구일반적인 ping 크기와 다른 요청이 장시간 반복, 데이터 내용이 매번 다름 (ICMP 터널링 가능성)
Port Unreachable (3/3) 다수 수신DNS 서버 장애, traceroute내부 호스트가 여러 UDP 포트에 대해 3/3을 연속으로 돌려줌 (UDP 포트 스캔 흔적)
Admin Prohibited (3/13)방화벽 정책에 따른 차단허용되어야 할 업무 통신이 차단됨 (정책 확인 필요)
Redirect (5)일부 라우터 구성일반 호스트가 Redirect를 보냄 (경로 조작 시도 가능성)
TTL exceeded (11/0)traceroute, 일시적 라우팅 루프대량 발생 → 라우팅 루프 또는 경로 탐색 활동

확인 명령 예시입니다.

# 출발지별 Echo Request 목적지 수 (여러 IP로 퍼지는지)
tshark -r $F -Y "icmp.type == 8" -T fields -e ip.src -e ip.dst | sort -u \
  | awk '{c[$1]++} END {for (s in c) print c[s], s}' | sort -rn

# Echo 데이터 길이 분포
tshark -r $F -Y "icmp.type == 8" -T fields -e data.len | sort | uniq -c | sort -rn

# Port Unreachable을 보낸 호스트와 원인이 된 목적지 포트
tshark -r $F -Y "icmp.type == 3 && icmp.code == 3" -T fields \
  -E occurrence=f -e ip.src -e udp.dstport | sort | uniq -c | sort -rn

# Redirect 존재 여부
tshark -r $F -Y "icmp.type == 5" -T fields -e ip.src -e icmp.redir_gw

일반적으로 Linux의 ping은 기본 56바이트 데이터(앞부분에 타임스탬프 포함, Wireshark에서 icmp.data_time으로 해석)를, Windows의 ping은 32바이트 데이터를 보냅니다. 이 기준과 다른 크기나 내용이 보인다고 곧바로 악성은 아니지만, 어떤 도구가 보낸 것인지 설명이 필요한 패킷이 됩니다.


7. 보안관제 관점

흔적이 남는 곳

  • 방화벽 로그: ICMP 허용·차단 기록(Type/Code가 함께 남는 장비가 많음). 3/13 메시지는 방화벽이 차단 사실을 알려 준 흔적일 수 있습니다.
  • IDS: ping 스윕, 비정상 크기 ICMP, ICMP 터널링 의심 패턴 탐지 규칙(06. 방화벽 · IDS/IPS 분석 시리즈에서 다룸).
  • 호스트: Linux 방화벽이 ICMP를 거부할 때의 동작과 로그는 Firewalld 이해 글을 참고합니다.

한계와 오탐 주의

  • ICMP 차단은 매우 흔한 정책이라 "응답 없음"이 곧 "호스트 없음"은 아닙니다.
  • ip.src, ip.dst, udp.dstport 필터는 오류 메시지의 안쪽 헤더에도 걸립니다. "이 IP가 보낸 패킷"을 찾으려다 "이 IP가 원인이 된 오류 메시지"까지 섞여 나올 수 있으므로, 계층 지정(#1, occurrence=f)을 습관화합니다.
  • 오류 메시지 안의 원본 헤더도 결국 패킷 안의 데이터이므로 위조가 가능합니다. 원본 패킷이 캡처에 실제로 있었는지(ip.id, 포트)로 대조하는 것이 좋습니다.
  • ICMP 터널링 판단은 데이터 길이·내용·빈도를 함께 봐야 하며, 한두 개의 큰 ping으로 결론 내리지 않습니다.

8. 핵심 정리

  • ICMP 분석의 출발점은 icmp.type·icmp.code 조합이며, 특히 3/3(포트 닫힘), 3/4(MTU), 3/13(관리적 차단), 11/0(TTL 만료)을 구분할 수 있어야 합니다.
  • Echo는 icmp.ident·icmp.seq로 요청·응답이 짝지어지고, Wireshark의 icmp.resp_in·icmp.resptime·icmp.no_resp로 응답 여부를 빠르게 확인합니다(tshark는 -2 필요).
  • 오류 메시지에는 원인 패킷의 IP 헤더와 일부 상위 헤더가 들어 있어, 한 프레임에 ip.src 등이 두 번 나타납니다.
  • 바깥·안쪽 헤더 구분은 -E occurrence=f/l과 레이어 연산자(ip.src#1)로 명확히 합니다.
  • ICMP는 "다른 통신에 무슨 일이 있었는지"를 알려 주는 간접 증거이며, 차단 정책·도구 특성을 고려해 해석합니다.

다음 글: 119. TCP 헤더와 Flag 분석 — 포트·시퀀스·Flag·옵션 필드 읽는 법

profile
코드에 숨겨진 위협을 읽고 AI로 보안의 미래를 설계합니다. 프론트엔드 개발 경험을 자산 삼아 더 견고하고 지능적인 보안 운영 시스템을 구축해 나가는 과정을 기록합니다

0개의 댓글