트래픽을 직접 만들어 tcpdump로 잡는 실습 환경
주어진 pcap을 해석하는 게 아니라, 내가 트래픽을 만들어서 잡아보는 쪽 실습이다. 무엇이 어디에 찍히는지 감을 잡는 게 목적이었다.
| Host OS | macOS (192.168.64.1) |
| Guest VM | Kali 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
무엇이 보이는가
| 색상 | 프로토콜 | 내용 |
|---|---|---|
| 분홍 | ICMP | ping request/reply (맥↔칼리 왕복) |
| 빨강 | TCP RST | 2222 포트 강제 연결 종료 |
| 회색 | TCP | 8080 포트 3-way handshake |
| 노랑 | HTTP | GET 요청 (가짜 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 는 속일 수 없다. 애플리케이션 로그만 보면 속지만, 패킷 레벨에서는 실제 출발지가 그대로 드러난다.
로그와 패킷이 다른 이야기를 할 때 어느 쪽을 믿어야 하는지 — 그게 이 실습에서 얻은 감각이다.