트래픽을 직접 만들어 tcpdump로 잡는 실습 환경

🛡️ 강사 제공 인가된 실습 환경에서 수행

주어진 pcap을 해석하는 게 아니라, 내가 트래픽을 만들어서 잡아보는 쪽 실습이다. 무엇이 어디에 찍히는지 감을 잡는 게 목적이었다.

Host OSmacOS (192.168.64.1)
Guest VMKali Linux ARM64 on UTM (192.168.64.6)
연결 방식macOS Terminal → SSH → Kali

SSH 연결

칼리 VM의 IP를 먼저 확인한다.

# 칼리 터미널에서
ip -br addr
# 맥 터미널에서
ssh kali@192.168.64.6

이후 모든 칼리 명령은 SSH로 연결된 터미널에서 실행한다.

환경 변수 세팅

printf 'Host IP: '; read -r SW_HOST_IP
printf 'Kali IP: '; read -r SW_KALI_IP
export SW_HOST_IP SW_KALI_IP
printf 'Host=%s Kali=%s\n' "$SW_HOST_IP" "$SW_KALI_IP"
nc -vz "$SW_KALI_IP" 22

마지막 줄에서 Connection to 192.168.64.6 port 22 succeeded! 가 나오면 정상이다.

여기서 한 번 헤맸다. 맥의 일반 네트워크 IP(192.168.x.x)가 아니라 UTM 가상 네트워크 IP(192.168.64.1) 를 써야 한다. ping 으로 실제 통신하는 IP를 먼저 확인할 것.

칼리 환경 확인

# wireshark, tshark, tcpdump 설치 확인
tshark --version
tcpdump --version

# SSH 서비스 상태 확인
sudo systemctl status ssh --no-pager

# 꺼져 있으면 활성화
sudo systemctl enable --now ssh
ss -tnlp

기본 상태라면 22번(SSH)만 열려 있어야 한다.

LISTEN   0   128   0.0.0.0:22   0.0.0.0:*
LISTEN   0   128      [::]:22      [::]:*

받을 포트를 먼저 연다

tcpdump가 캡처할 트래픽을 받아줄 서버 3개를 백그라운드로 띄운다.

# HTTP 서버 (8080 포트)
python3 -u -m http.server 8080 --bind 0.0.0.0 > http8080.log 2>&1 &

# TCP 리스너 (2222 포트)
nc -lvnp 2222 > tcp2222.log 2>&1 &

# TCP 리스너 (53530 포트)
nc -lvnp 53530 > udp53530.log 2>&1 &
ss -lntup | grep -E ':8080|:2222|:53530'

셋 다 LISTEN 상태여야 한다.

tcp  LISTEN  0  1  0.0.0.0:2222   0.0.0.0:*  users:(("nc",...))
tcp  LISTEN  0  5  0.0.0.0:8080   0.0.0.0:*  users:(("python3",...))
tcp  LISTEN  0  1  0.0.0.0:53530  0.0.0.0:*  users:(("nc",...))

tcpdump로 캡처 시작

export HOST_IP=192.168.64.1
export KALI_IP=192.168.64.6

sudo tcpdump -i eth0 -nn \
  "((icmp and host $HOST_IP) or \
  (tcp and host $HOST_IP and (port 8080 or port 2222)) or \
  (udp and src host $HOST_IP and dst host $KALI_IP and dst port 53530))" \
  -w ~/security-wave/week01/day03-lab01-host-vm.pcapng
  • -i eth0 — eth0 인터페이스 캡처
  • -nn — IP/포트를 이름으로 변환하지 않고 숫자 그대로 표시
  • -w 파일명 — pcapng 파일로 저장
  • 필터 — Host IP 기준으로 ICMP, TCP(8080/2222), UDP(53530)만

tcpdump: listening on eth0 이 뜨면 대기 중이다. 이 창은 캡처가 끝날 때까지 유지해야 하므로 새 SSH 창을 열어서 나머지를 진행한다.

패킷 쏘기

맥에서 칼리로 ICMP/TCP/HTTP/UDP를 보낸다.

curl -O https://security-wave.kro.kr/week01/v2/downloads/Day03-Lab01-SendPacket.sh
chmod +x ./Day03-Lab01-SendPacket.sh
bash ./Day03-Lab01-SendPacket.sh "$SW_KALI_IP" 8080 2222 53530
[1/4] ICMP ping to 192.168.64.6       → 3 packets, 0% loss
[2/4] TCP probe to 192.168.64.6:2222
[3/4] HTTP requests to http://192.168.64.6:8080/
      HTTP sent: 10.10.10.11 / 10.10.20.21 / 172.16.30.31 / 192.168.99.41
[4/4] UDP datagrams to 192.168.64.6:53530
      UDP sent: 10.10.10.11 / 10.10.20.21 / 172.16.30.31 / 192.168.99.41

여기가 이 실습의 함정이자 핵심이다. HTTP/UDP 패킷의 src_label(가짜 출발지 IP)은 애플리케이션 레이어의 라벨일 뿐이고, tcpdump에 실제로 찍히는 ip.src 는 Host IP(192.168.64.1)다.

종료하고 Wireshark로 열기

Ctrl + C

N packets captured 가 출력되면 파일이 저장된 것이다.

wireshark ~/security-wave/week01/day03-lab01-host-vm.pcapng

무엇이 보이는가

색상프로토콜내용
분홍ICMPping request/reply (맥↔칼리 왕복)
빨강TCP RST2222 포트 강제 연결 종료
회색TCP8080 포트 3-way handshake
노랑HTTPGET 요청 (가짜 src_label 포함)

TCP 플래그는 이렇게 읽는다.

  • SYN — 연결 시작 요청
  • SYN, ACK — 연결 수락 응답
  • ACK — 수신 확인
  • FIN, ACK — 연결 종료 요청
  • RST, ACK — 연결 강제 리셋

Source가 192.168.64.1 이면 맥(Host)이 보낸 패킷, 192.168.64.6 이면 칼리가 응답한 패킷이다.

남는 것

HTTP 패킷의 X-Forwarded-For 헤더에 가짜 IP가 들어 있어도 실제 ip.src 는 속일 수 없다. 애플리케이션 로그만 보면 속지만, 패킷 레벨에서는 실제 출발지가 그대로 드러난다.

로그와 패킷이 다른 이야기를 할 때 어느 쪽을 믿어야 하는지 — 그게 이 실습에서 얻은 감각이다.